Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import math
- # ============================================================
- # Матрица предпочтений (строки = товары, столбцы = пользователи)
- # ============================================================
- products = ['P1', 'P2', 'P3', 'P4', 'P5', 'P6']
- users = ['U1', 'U2', 'U3', 'U4', 'U5']
- # ratings[i][j] — оценка пользователя users[j] для товара products[i]
- ratings = [
- # U1 U2 U3 U4 U5
- [ 5, 4, 5, 3, 5 ], # P1
- [ 5, 5, 5, 3, 5 ], # P2
- [ 5, 4, 4, 2, 5 ], # P3
- [ 5, 3, 5, 0, 3 ], # P4
- [ 5, 0, 5, 0, 0 ], # P5
- [ 4, 5, 5, 3, 1 ], # P6
- ]
- # ============================================================
- # Режим демонстрации
- # ============================================================
- DEMO = False # Установите False для краткого вывода
- # ============================================================
- # Вспомогательные функции (без сторонних библиотек)
- # ============================================================
- def dot_product(a, b):
- """Скалярное произведение двух векторов."""
- return sum(x * y for x, y in zip(a, b))
- def norm(v):
- """Евклидова норма вектора."""
- return math.sqrt(sum(x ** 2 for x in v))
- def cosine_similarity(a, b):
- """
- Косинусное подобие двух векторов:
- cos(A, B) = (A · B) / (|A| * |B|)
- Возвращает 0, если один из векторов нулевой.
- """
- n_a = norm(a)
- n_b = norm(b)
- if n_a == 0 or n_b == 0:
- return 0.0
- return dot_product(a, b) / (n_a * n_b)
- def build_similarity_matrix(vectors, labels, entity_name, demo=False):
- """
- Строит симметричную матрицу косинусного подобия.
- vectors — список векторов (списков чисел)
- labels — названия объектов
- """
- n = len(vectors)
- sim = [[0.0] * n for _ in range(n)]
- if demo:
- print(f"\n{'='*60}")
- print(f" Вычисление косинусного подобия: {entity_name}")
- print(f"{'='*60}")
- for i in range(n):
- for j in range(i + 1, n):
- a, b = vectors[i], vectors[j]
- dp = dot_product(a, b)
- na = norm(a)
- nb = norm(b)
- cos = dp / (na * nb) if (na != 0 and nb != 0) else 0.0
- sim[i][j] = cos
- sim[j][i] = cos
- if demo:
- print(f"\n {labels[i]} vs {labels[j]}")
- print(f" Вектор {labels[i]}: {a}")
- print(f" Вектор {labels[j]}: {b}")
- print(f" Скалярное произведение ({labels[i]}·{labels[j]}): "
- f"{' + '.join(f'{x}×{y}' for x, y in zip(a, b))} = {dp}")
- print(f" |{labels[i]}| = sqrt({' + '.join(str(x**2) for x in a)}) = {na:.6f}")
- print(f" |{labels[j]}| = sqrt({' + '.join(str(x**2) for x in b)}) = {nb:.6f}")
- print(f" cos({labels[i]}, {labels[j]}) = {dp} / ({na:.4f} × {nb:.4f}) = {cos:.6f}")
- return sim
- def print_matrix(sim, labels, title):
- """Вывод матрицы подобия."""
- n = len(labels)
- col_w = 10
- label_w = 4
- print(f"\n {title}")
- # Заголовок
- header = " " * label_w + "".join(f"{lbl:>{col_w}}" for lbl in labels)
- print(" " + header)
- print(" " + "-" * len(header))
- for i, lbl in enumerate(labels):
- row = f"{lbl:<{label_w}}"
- for j in range(n):
- if i == j:
- row += f"{'1.000000':>{col_w}}"
- else:
- row += f"{sim[i][j]:>{col_w}.6f}"
- print(" " + row)
- def find_closest_pair(sim, labels):
- """
- Возвращает пару с наибольшим косинусным подобием
- (исключая диагональ i == j).
- """
- n = len(labels)
- best_val = -1.0
- best_pair = (None, None)
- for i in range(n):
- for j in range(i + 1, n):
- if sim[i][j] > best_val:
- best_val = sim[i][j]
- best_pair = (labels[i], labels[j])
- return best_pair, best_val
- # ============================================================
- # 1. Векторы пользователей (столбцы матрицы оценок)
- # ============================================================
- user_vectors = []
- for j, u in enumerate(users):
- vec = [ratings[i][j] for i in range(len(products))]
- user_vectors.append(vec)
- # ============================================================
- # 2. Векторы товаров (строки матрицы оценок)
- # ============================================================
- item_vectors = [list(row) for row in ratings]
- # ============================================================
- # 3. Вычисление матриц подобия
- # ============================================================
- if DEMO:
- print("\n" + "=" * 60)
- print(" МАТРИЦА ПРЕДПОЧТЕНИЙ")
- print("=" * 60)
- col_w = 5
- lbl_w = 4
- header = " " * lbl_w + "".join(f"{u:>{col_w}}" for u in users)
- print(" " + header)
- print(" " + "-" * len(header))
- for i, p in enumerate(products):
- row = f"{p:<{lbl_w}}" + "".join(f"{ratings[i][j]:>{col_w}}" for j in range(len(users)))
- print(" " + row)
- print()
- user_sim = build_similarity_matrix(user_vectors, users, "ПОЛЬЗОВАТЕЛИ", demo=DEMO)
- item_sim = build_similarity_matrix(item_vectors, products, "ТОВАРЫ", demo=DEMO)
- # ============================================================
- # 4. Вывод итоговых матриц
- # ============================================================
- print("\n\n" + "=" * 60)
- print(" ИТОГОВЫЕ РЕЗУЛЬТАТЫ")
- print("=" * 60)
- print_matrix(user_sim, users, "Матрица косинусного подобия ПОЛЬЗОВАТЕЛЕЙ")
- print_matrix(item_sim, products, "Матрица косинусного подобия ТОВАРОВ")
- # ============================================================
- # 5. Поиск двух самых близких пар
- # ============================================================
- (u1, u2), u_score = find_closest_pair(user_sim, users)
- (p1, p2), p_score = find_closest_pair(item_sim, products)
- print(f"\n Два самых близких пользователя: {u1} и {u2} "
- f"(cos = {u_score:.6f})")
- print(f" Два самых близких товара: {p1} и {p2} "
- f"(cos = {p_score:.6f})")
- print()
Advertisement
Add Comment
Please, Sign In to add comment