应直接使用sklearn.metrics.pairwise.cosine_similarity,避免手写公式,因其自动处理归一化、稀疏矩阵和数值下溢问题,并支持dense_output=false返回稀疏矩阵以节省内存。

余弦相似度计算用 cosine_similarity 还是手写公式?
直接用 sklearn.metrics.pairwise.cosine_similarity,别自己实现向量点积除模长。手写容易忽略归一化、稀疏矩阵处理和数值下溢问题,比如对高维稀疏的用户-商品交互矩阵,cosine_similarity 内部会自动转为稀疏运算,而手动算 np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)) 可能触发内存爆炸或 0/0。
实操建议:
- 输入必须是二维数组或稀疏矩阵,每行一个样本(如每个商品是一个向量)
- 若原始数据是用户行为表(user_id, item_id, rating),先用
scipy.sparse.csr_matrix构建物品共现矩阵或用户画像向量,再传入cosine_similarity - 结果是方阵,
sim[i][j]表示第 i 个和第 j 个商品的相似度,注意对角线恒为 1
如何从用户历史行为生成推荐列表?
核心不是“找最相似商品”,而是“找用户没交互过但相似商品热度高的商品”。常见错误是直接取相似度 top-K 商品,却没过滤掉用户已点击/购买过的 item_id。
实操建议:
- 对每个用户,先用其历史交互商品 ID 查出对应行(在商品相似度矩阵中),得到该商品与其他所有商品的相似分
- 聚合策略选加权求和:
score[item] = sum(cosine_sim[known_item][item] * rating[known_item]),比单纯取 max 更鲁棒 - 过滤掉用户
history_items集合里的 ID,再按 score 降序取前 N - 避免用
argsort全排序,改用np.argpartition加速 top-K 提取
稀疏性高时相似度矩阵爆内存怎么办?
当商品数超 10 万,cosine_similarity 默认输出稠密 numpy.ndarray,可能吃光 64G 内存。这不是算法问题,是存储格式误用。
实操建议:
- 强制返回稀疏矩阵:
cosine_similarity(X, dense_output=False),返回scipy.sparse.csr_matrix - 后续检索改用
.data和.indices遍历非零值,跳过全零行 - 如果只要 top-K 相似商品,用
sklearn.neighbors.NearestNeighbors(algorithm='brute', metric='cosine'),它内部不显式构建完整相似度矩阵 - 预处理时对商品向量做 L2 归一化(
sklearn.preprocessing.normalize),这样余弦相似度就等价于点积,可加速计算
为什么推荐结果看起来“太泛”或“不相关”?
余弦相似度只反映向量方向一致,不保证业务语义合理。比如两个商品在“价格”“销量”“类目”三个维度上都低,方向接近,但实际不相关——这是特征工程缺陷,不是相似度函数的问题。
实操建议:
- 检查输入向量是否混入了量纲差异大的字段(如价格和评论数),必须标准化或分桶,别直接拼接原始数值
- 类别型特征(如类目、品牌)要用
OneHotEncoder或TargetEncoder,不能用 label encoding 后当连续值用 - 冷启动商品向量全零,会导致相似度全为 nan,需单独处理:对新商品,回退到类目层级相似或热门榜
- 上线前用人工抽检 case:挑几个用户,看其历史商品和推荐商品在业务维度(用途、价格带、场景)是否可解释
真正卡住进度的往往不是余弦计算本身,而是向量怎么定义、怎么更新、怎么应对新增商品——这些没对齐,相似度再准也没用。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











