Solingen

Untitled

Mar 18th, 2026
36
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.64 KB | None | 0 0
  1. import math
  2.  
  3. # ============================================================
  4. # USER-BASED рекомендательная система
  5. # ============================================================
  6.  
  7. # Матрица предпочтений: ratings[товар][пользователь]
  8. # 0 = пользователь не оценил товар
  9.  
  10. products = ['P1', 'P2', 'P3', 'P4', 'P5']
  11. users = ['U1', 'U2', 'U3', 'U4']
  12.  
  13. # U1 U2 U3 U4
  14. ratings = [
  15. [5, 5, 4, 5], # P1
  16. [5, 5, 3, 0], # P2
  17. [5, 5, 5, 5], # P3
  18. [5, 0, 2, 0], # P4
  19. [0, 5, 1, 0], # P5
  20. ]
  21.  
  22. # Матрица косинусного подобия пользователей (задаётся вручную или берётся из задания 1)
  23. # sim[i][j] — подобие между users[i] и users[j]
  24. user_sim_raw = {
  25. ('U1', 'U2'): 0.9,
  26. ('U1', 'U3'): 0.7,
  27. ('U1', 'U4'): 0.0, # U4 исключён (мало оценок — все нули кроме P1, P3)
  28. ('U2', 'U3'): 0.6,
  29. ('U2', 'U4'): 0.0,
  30. ('U3', 'U4'): 0.0,
  31. }
  32.  
  33. # ============================================================
  34. # Вспомогательные функции
  35. # ============================================================
  36.  
  37. def dot_product(a, b):
  38. return sum(x * y for x, y in zip(a, b))
  39.  
  40. def norm(v):
  41. return math.sqrt(sum(x ** 2 for x in v))
  42.  
  43. def cosine_similarity(a, b):
  44. na, nb = norm(a), norm(b)
  45. if na == 0 or nb == 0:
  46. return 0.0
  47. return dot_product(a, b) / (na * nb)
  48.  
  49. def get_user_vector(user_idx):
  50. """Вектор оценок пользователя (по всем товарам)."""
  51. return [ratings[i][user_idx] for i in range(len(products))]
  52.  
  53. def get_item_vector(item_idx):
  54. """Вектор оценок товара (по всем пользователям)."""
  55. return ratings[item_idx]
  56.  
  57. def get_sim(u1, u2):
  58. """Косинусное подобие между двумя пользователями по имени."""
  59. if u1 == u2:
  60. return 1.0
  61. key = (u1, u2) if (u1, u2) in user_sim_raw else (u2, u1)
  62. return user_sim_raw.get(key, 0.0)
  63.  
  64. def avg_rating(user_idx):
  65. """Средняя оценка пользователя по всем товарам, которые он оценил (> 0)."""
  66. rated = [ratings[i][user_idx] for i in range(len(products)) if ratings[i][user_idx] > 0]
  67. return sum(rated) / len(rated) if rated else 0.0
  68.  
  69. def is_new_user(user_idx):
  70. """Новый пользователь — все оценки == 0."""
  71. return all(ratings[i][user_idx] == 0 for i in range(len(products)))
  72.  
  73. def best_avg_product():
  74. """Товар с наибольшим средним рейтингом (для новых пользователей)."""
  75. best_p, best_avg = None, -1
  76. for i, p in enumerate(products):
  77. rated = [ratings[i][j] for j in range(len(users)) if ratings[i][j] > 0]
  78. avg = sum(rated) / len(rated) if rated else 0.0
  79. if avg > best_avg:
  80. best_avg = avg
  81. best_p = p
  82. return best_p, best_avg
  83.  
  84. # ============================================================
  85. # Формула предсказания оценки (USER-BASED):
  86. #
  87. # Pr(a, i) = r̄(a) + Σ_{u∈K} (r(u,i) - r̄(u)) × cos(a,u)
  88. # ─────────────────────────────────────────────
  89. # Σ_{u∈K} |cos(a, u)|
  90. #
  91. # K — пользователи, похожие на a, которые оценили товар i (> 0)
  92. # r̄(a) — средняя оценка пользователя a
  93. # r̄(u) — средняя оценка пользователя u
  94. # r(u,i) — оценка пользователя u для товара i
  95. # cos(a,u) — косинусное подобие a и u
  96. # ============================================================
  97.  
  98. def predict(user_a_idx, item_i_idx, demo=True):
  99. """Предсказывает оценку пользователя a для товара i."""
  100. a_name = users[user_a_idx]
  101. i_name = products[item_i_idx]
  102.  
  103. # K — пользователи которые оценили товар i (кроме самого a)
  104. K = []
  105. for u_idx, u_name in enumerate(users):
  106. if u_idx == user_a_idx:
  107. continue
  108. if ratings[item_i_idx][u_idx] > 0:
  109. sim = get_sim(a_name, u_name)
  110. if sim > 0:
  111. K.append(u_idx)
  112.  
  113. if not K:
  114. if demo:
  115. print(f" K пуст — нет похожих пользователей, оценивших {i_name}")
  116. return None
  117.  
  118. r_a = avg_rating(user_a_idx)
  119.  
  120. numerator = 0.0
  121. denominator = 0.0
  122.  
  123. if demo:
  124. print(f" r̄({a_name}) = {r_a:.4f}")
  125. print(f" K = {{ {', '.join(users[u] for u in K)} }}")
  126.  
  127. for u_idx in K:
  128. u_name = users[u_idx]
  129. r_ui = ratings[item_i_idx][u_idx]
  130. r_u = avg_rating(u_idx)
  131. cos_au = get_sim(a_name, u_name)
  132.  
  133. term = (r_ui - r_u) * cos_au
  134. numerator += term
  135. denominator += abs(cos_au)
  136.  
  137. if demo:
  138. print(f" u={u_name}: r({u_name},{i_name})={r_ui}, "
  139. f"r̄({u_name})={r_u:.4f}, cos({a_name},{u_name})={cos_au:.4f} "
  140. f"→ ({r_ui} - {r_u:.4f}) × {cos_au:.4f} = {term:.4f}")
  141.  
  142. if denominator == 0:
  143. return None
  144.  
  145. pr = r_a + numerator / denominator
  146.  
  147. if demo:
  148. print(f" Pr({a_name},{i_name}) = {r_a:.4f} + {numerator:.4f} / {denominator:.4f} = {pr:.4f}")
  149.  
  150. return pr
  151.  
  152. # ============================================================
  153. # Главная функция — рекомендация для каждого пользователя
  154. # ============================================================
  155.  
  156. def recommend_for_user(user_idx, demo=True):
  157. a_name = users[user_idx]
  158.  
  159. print(f"\n{'='*60}")
  160. print(f" Пользователь: {a_name}")
  161. print(f"{'='*60}")
  162.  
  163. # Новый пользователь?
  164. if is_new_user(user_idx):
  165. best_p, best_avg = best_avg_product()
  166. print(f" Новый пользователь (все оценки = 0).")
  167. print(f" Рекомендуем товар с наибольшим средним рейтингом: {best_p} (avg={best_avg:.4f})")
  168. return best_p
  169.  
  170. # Товары, которые пользователь НЕ оценил
  171. unrated = [i for i in range(len(products)) if ratings[i][user_idx] == 0]
  172.  
  173. if not unrated:
  174. print(f" {a_name} оценил все товары — нечего рекомендовать.")
  175. return None
  176.  
  177. print(f" Неоцененные товары: {[products[i] for i in unrated]}")
  178. print(f" Считаем предсказанную оценку для каждого:\n")
  179.  
  180. predictions = {}
  181. for i_idx in unrated:
  182. i_name = products[i_idx]
  183. print(f" → Pr({a_name}, {i_name}):")
  184. pr = predict(user_idx, i_idx, demo=demo)
  185. if pr is not None:
  186. predictions[i_name] = pr
  187. print(f" Результат: {pr:.4f}")
  188. else:
  189. print(f" Нет данных для предсказания.")
  190. print()
  191.  
  192. if not predictions:
  193. print(f" Не удалось предсказать оценки.")
  194. return None
  195.  
  196. best = max(predictions, key=lambda x: predictions[x])
  197. print(f" Все предсказания: { {k: round(v,4) for k,v in predictions.items()} }")
  198. print(f" ✓ Рекомендуем {a_name}: товар {best} (Pr = {predictions[best]:.4f})")
  199. return best
  200.  
  201. # ============================================================
  202. # Вывод исходных данных
  203. # ============================================================
  204.  
  205. print("=" * 60)
  206. print(" USER-BASED РЕКОМЕНДАТЕЛЬНАЯ СИСТЕМА")
  207. print("=" * 60)
  208.  
  209. # Матрица предпочтений
  210. col_w = 6
  211. print("\n Матрица предпочтений:")
  212. print(" " + " " * 4 + "".join(f"{u:>{col_w}}" for u in users))
  213. print(" " + "-" * (4 + col_w * len(users)))
  214. for i, p in enumerate(products):
  215. row = f" {p:<4}" + "".join(f"{ratings[i][j]:>{col_w}}" for j in range(len(users)))
  216. print(row)
  217.  
  218. # Средние оценки
  219. print("\n Средние оценки пользователей (по оцененным товарам):")
  220. for j, u in enumerate(users):
  221. print(f" r̄({u}) = {avg_rating(j):.4f}")
  222.  
  223. # Матрица подобия
  224. print("\n Матрица косинусного подобия пользователей:")
  225. print(" " + " " * 4 + "".join(f"{u:>{col_w}}" for u in users))
  226. print(" " + "-" * (4 + col_w * len(users)))
  227. for i, u1 in enumerate(users):
  228. row = f" {u1:<4}"
  229. for j, u2 in enumerate(users):
  230. row += f"{get_sim(u1,u2):>{col_w}.2f}"
  231. print(row)
  232.  
  233. # ============================================================
  234. # Рекомендации для всех пользователей
  235. # ============================================================
  236. print("\n\n" + "=" * 60)
  237. print(" РАСЧЁТ РЕКОМЕНДАЦИЙ")
  238. print("=" * 60)
  239.  
  240. results = {}
  241. for j in range(len(users)):
  242. rec = recommend_for_user(j, demo=True)
  243. results[users[j]] = rec
  244.  
  245. # Итог
  246. print("\n" + "=" * 60)
  247. print(" ИТОГОВЫЕ РЕКОМЕНДАЦИИ")
  248. print("=" * 60)
  249. for u, rec in results.items():
  250. if rec:
  251. print(f" {u} → рекомендовать {rec}")
  252. else:
  253. print(f" {u} → нечего рекомендовать")
Advertisement
Add Comment
Please, Sign In to add comment