Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

57 rindas
2.2 KiB

  1. from collections import Counter
  2. import logging
  3. from math import sqrt
  4. from collections.abc import Sequence
  5. logger = logging.getLogger(__name__)
  6. def cosine_similarity(a: Sequence[float], b: Sequence[float]) -> float:
  7. logger.debug("Computing cosine similarity between numerical vectors of length %d and %d", len(a), len(b))
  8. if len(a) != len(b):
  9. logger.error("Vector dimension mismatch: vector 'a' length (%d) != vector 'b' length (%d)", len(a), len(b))
  10. raise ValueError("Vectors must have the same dimension")
  11. dot = 0.0
  12. norm_a_sq = 0.0
  13. norm_b_sq = 0.0
  14. for x, y in zip(a, b):
  15. dot += x * y
  16. norm_a_sq += x * x
  17. norm_b_sq += y * y
  18. denominator = sqrt(norm_a_sq * norm_b_sq)
  19. if denominator == 0.0:
  20. logger.debug("Zero denominator encountered in cosine_similarity (norm_a_sq=%f, norm_b_sq=%f). Returning 0.0", norm_a_sq, norm_b_sq)
  21. return 0.0
  22. similarity = dot / denominator
  23. logger.debug("Calculated vector cosine similarity: dot=%f, denominator=%f, similarity=%f", dot, denominator, similarity)
  24. return similarity
  25. def cosine_lists(a: list[str], b: list[str], *, casefold: bool = True) -> float:
  26. logger.debug("Computing token cosine similarity for list_a=%s and list_b=%s (casefold=%s)", a, b, casefold)
  27. def tokens(xs: list[str]) -> Counter[str]:
  28. return Counter(x.casefold() if casefold else x for x in xs)
  29. ca, cb = tokens(a), tokens(b)
  30. if not ca or not cb:
  31. logger.debug("Empty token set detected (count_a=%d, count_b=%d). Cosine similarity is 0.0", len(ca), len(cb))
  32. return 0.0
  33. common_tokens = ca.keys() & cb.keys()
  34. dot = sum(ca[t] * cb[t] for t in common_tokens)
  35. norm_a = sqrt(sum(v * v for v in ca.values()))
  36. norm_b = sqrt(sum(v * v for v in cb.values()))
  37. if norm_a == 0.0 or norm_b == 0.0:
  38. logger.debug("Zero norm detected (norm_a=%f, norm_b=%f). Cosine similarity is 0.0", norm_a, norm_b)
  39. return 0.0
  40. similarity = dot / (norm_a * norm_b)
  41. logger.debug("Token similarity calculation: common_tokens=%s, dot=%f, norm_a=%f, norm_b=%f -> similarity=%.4f",
  42. list(common_tokens), dot, norm_a, norm_b, similarity)
  43. return similarity