本文共 2264 字,大约阅读时间需要 7 分钟。
基于用户的协同过滤算法的核心思想是:有相似兴趣的用户可能会喜欢相同的物品。因此,计算用户的相似度成为实现推荐系统的关键步骤。本文采用了下列相似度公式:
[ \omega_{uv} = \frac{N(u) \bigcap N(v)}{\sqrt{N(u) \times N(v)}} ]
其中,( N(u) ) 表示用户 ( u ) 看过的电影数量。
本实现使用了 MovieLens 数据集,该数据集包含用户对电影的评分信息。具体步骤如下:
数据集加载:从 ratings.csv 文件中读取数据,将数据按用户-电影-评分-时间戳的格式存储,并整理成物品-用户的倒排表。
变量定义:
计算相似度矩阵:遍历倒排表,统计每个用户的交互次数,并计算用户之间的相似度。
推荐算法:为目标用户推荐电影,首先获取其已观看的电影列表,然后基于相似度排序的用户,计算并推荐未观看的电影。
import operatorclass UserBasedCF: def __init__(self): self.N = {} # 记录用户看过的电影数量 self.W = {} # 用户相似度矩阵 self.train = {} # 用户交互数据 self.item_users = {} # 物品-用户倒排表 self.k = 30 # 相似用户数量 self.n = 10 # 每个用户推荐的电影数量 def get_data(self, file_path): """加载数据集""" with open(file_path, 'r') as f: for line in f: if not line.strip(): continue user, item, rating, timestamp = line.split(',') self.train.setdefault(user, []) self.train[user].append((item, rating)) self.item_users.setdefault(item, []).append(user) def similarity(self): """计算用户相似度矩阵""" for item, users in self.item_users.items(): for u in users: self.N[u] = self.N.get(u, 0) + 1 for v in users: if u != v: self.W.setdefault(u, {}) self.W[u][v] = self.W.get(u, {}).get(v, 0) + 1 for u in self.W: for v in self.W[u]: self.W[u][v] /= (self.N[u] * self.N[v]) ** 0.5 def recommendation(self, user): """为指定用户推荐电影""" watched = {item for (item, _) in self.train[user]} ranked = {} for v, similarity in sorted(self.W[user].items(), key=operator.itemgetter(1), reverse=True)[:self.k]: for item, rating in self.train[v]: if item not in watched: ranked[item] = ranked.get(item, 0) + similarity * float(rating) return sorted(ranked.items(), key=operator.itemgetter(1), reverse=True)[:self.n] 程序随机选择一位用户,基于其最相似的 30 个用户,为其推荐 10 部电影。推荐结果包括电影 ID 和加权评分,具体结果请参考运行环境中的输出。
《推荐系统实践》——项亮
转载地址:http://sezmz.baihongyu.com/