构建用户-物品交互矩阵需用pandas.crosstab()填充评分均值或1/0隐式反馈,填充nan为0,id转整数索引;相似度计算须用scipy稀疏矩阵输入cosine_similarity;推荐时过滤低相似度邻居、加权平均预测分,并fallback热门商品。

怎么构建用户-物品交互矩阵(User-Item Matrix)
协同过滤的核心是把用户行为转成数值矩阵,行是用户、列是商品、值是评分或是否点击/购买。关键不是“有没有数据”,而是“怎么填这个矩阵”——很多初学者直接用原始 CSV 行列硬转,结果矩阵稀疏得没法算相似度。
实操建议:
- 用
pandas.crosstab()最省事:比如pd.crosstab(df['user_id'], df['item_id'], values=df['rating'], aggfunc='mean'),自动处理重复评分取均值 - 如果只有隐式反馈(如点击、加购),就用 1/0 填充,别留空——
fillna(0)必做,否则余弦相似度会把 NaN 当 0 处理但逻辑错乱 - 矩阵太大?先用
df.sample(frac=0.3)抽样调试,别一上来就跑全量;用户或商品 ID 是字符串?必须先用pd.Categorical或LabelEncoder转成连续整数索引,否则scipy.sparse矩阵构建失败
为什么用 sklearn.metrics.pairwise.cosine_similarity 而不是手写公式
手写余弦公式看着简单,但实际容易在归一化、稀疏矩阵支持、广播维度上翻车。比如对用户向量做 np.linalg.norm 时没处理零向量,会触发除零警告;或者用 for 循环两两计算,1000 用户就要算 50 万次,慢且内存爆炸。
实操建议:
- 输入必须是
scipy.sparse.csr_matrix或二维numpy.ndarray,别传 DataFrame——cosine_similarity()不认pd.DataFrame的列名,会报ValueError: Expected 2D array, got 1D array instead - 算用户相似度就传
user_item_matrix本身;算商品相似度就传它的转置user_item_matrix.T - 返回的是对称方阵,第 i 行第 j 列就是用户 i 和 j 的相似度;想查 Top-K 相似用户?用
np.argsort(sim_matrix[i])[::-1][1:k+1],注意跳过自己(索引 i)
怎么基于相似用户生成推荐结果(冷启动和边界情况怎么处理)
拿到相似度矩阵后,直接加权平均邻居评分看似合理,但实际常遇到:某用户只评过 1 个商品,所有相似度都是 0;或邻居里没人评过目标商品,推荐列表为空。
实操建议:
- 给相似度加阈值过滤,比如只取
sim_score > 0.1的邻居,避免噪声干扰;用np.where(sim_matrix[i] > 0.1)[0]拿到有效邻居索引 - 预测评分公式用
np.sum(sim * ratings) / np.sum(np.abs(sim)),分母用绝对值之和,防止正负相似度抵消 - 对每个用户,先找出所有「邻居评过但该用户没评」的商品,再按预测分排序;如果空了,fallback 到热门商品(
user_item_matrix.sum(axis=0).argsort()[::-1][:10]) - 别忘了去重:同一个商品可能被多个邻居评过分,聚合时用
set或groupby防止重复推荐
常见报错和性能卡点在哪
最常卡在三处:矩阵太稀疏导致相似度全为 0;内存爆掉;推荐结果全是 NaN。这些问题往往不是算法错,而是数据预处理漏了一步。
实操建议:
-
cosine_similarity返回全 0 矩阵?大概率是用户向量全为 0(没评分)或用了未填充的稀疏矩阵——检查user_item_matrix.getnnz(axis=1),看每行非零元素数,低于 2 就得过滤掉该用户 - 内存不够?别用
toarray()把稀疏矩阵转稠密,改用scipy.sparse.csr_matrix+cosine_similarity(..., dense_output=False) - 推荐结果出现
nan?检查预测分计算时有没有除零,加一句np.nan_to_num(predicted_scores, nan=0.0)再排序 - 速度慢?关掉
scikit-learn的多线程(设n_jobs=1),小规模数据单线程更稳;真要加速就换implicit库,它底层是 C++,但那是另一个工程级选择了
真正难的不是算相似度,是让矩阵有足够密度、让邻居有意义、让空缺有 fallback。调参可以慢慢来,数据清洗和边界判断必须一开始就写进函数里。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











