
目录
一、引言
在如今这个信息爆炸的时代,互联网上的内容如潮水般涌来。无论是电商平台上琳琅满目的商品,还是视频网站里海量的影视资源,又或是音乐APP中数不尽的歌曲,用户都面临着信息过载的难题。推荐系统就如同一位贴心的助手,能从这茫茫信息中筛选出符合用户兴趣的内容。而协同过滤,作为推荐系统的核心技术之一,发挥着至关重要的作用。
二、协同过滤的基本原理
协同过滤基于一个很直观的假设:如果用户A和用户B对一些物品的评价相似,那么他们对其他物品的喜好可能也相似。这就好比在一个美食爱好者的圈子里,你发现朋友甲和朋友乙都对巧克力蛋糕、冰淇淋等甜食赞不绝口,那很有可能他们对新出的草莓慕斯也会有相同的好感。
从数据层面看,协同过滤依赖于用户 - 物品评分矩阵。假设我们有 m m m个用户和 n n n个物品,这个矩阵就是 m × n m×n m×n的。矩阵里的元素 R i j R_{ij} Rij表示用户 i i i对物品 j j j的评分。要是用户 i i i没给物品 j j j评分, R i j R_{ij} Rij可以设为0或者空值。例如在一个电影评分网站,用户张三给电影《泰坦尼克号》评了4分,那在矩阵里 R 张三 , 泰坦尼克号 R_{张三,泰坦尼克号} R张三,泰坦尼克号就是4;李四还没看过《阿凡达》, R 李四 , 阿凡达 R_{李四,阿凡达} R李四,阿凡达就记为0。通过分析这个矩阵,我们就能挖掘出用户之间以及物品之间隐藏的相似关系。
三、协同过滤的算法类型
(一)基于用户的协同过滤
- 计算用户相似度
确定用户间的相似度是关键一步。常用的相似度度量方法有余弦相似度和皮尔逊相关系数。- 余弦相似度 :把用户的评分向量想象成空间中的向量。就像在一个多维空间里,用户甲对几部电影的评分构成一个向量,用户乙对同样几部电影的评分构成另一个向量。余弦相似度就是通过计算这两个向量夹角的余弦值来衡量相似程度。公式为:
s i m ( u , v ) = ∑ i ∈ I R u i × R v i ∑ i ∈ I R u i 2 × ∑ i ∈ I R v i 2 sim(u, v)=\frac{\sum_{i \in I}R_{ui} \times R_{vi}}{\sqrt{\sum_{i \in I}R_{ui}^2} \times \sqrt{\sum_{i \in I}R_{vi}^2}} sim(u,v)=∑i∈IRui2 ×∑i∈IRvi2 ∑i∈IRui×Rvi
这里 u u u和 v v v是两个用户, I I I是用户 u u u和 v v v共同评分的物品集合。简单说,就是把两个用户对共同评价过的物品的评分对应相乘,加起来,再除以两个用户各自评分向量的模的乘积。比如用户甲和用户乙都给《盗梦空间》《星际穿越》《蝙蝠侠》评了分,将他们对这三部电影的评分组成向量,代入公式就能算出相似度。值越接近1,说明两人兴趣越相似;越接近0,差异越大。 - 皮尔逊相关系数 :它衡量两个变量的线性相关程度,在协同过滤里判断两个用户评分模式的相似性。公式为:
s i m ( u , v ) = ∑ i ∈ I ( R u i − R ‾ u ) ( R v i − R ‾ v ) ∑ i ∈ I ( R u i − R ‾ u ) 2 × ∑ i ∈ I ( R v i − R ‾ v ) 2 sim(u, v)=\frac{\sum_{i \in I}(R_{ui}-\overline{R}{u})(R{vi}-\overline{R}{v})}{\sqrt{\sum{i \in I}(R_{ui}-\overline{R}{u})^2} \times \sqrt{\sum{i \in I}(R_{vi}-\overline{R}{v})^2}} sim(u,v)=∑i∈I(Rui−Ru)2 ×∑i∈I(Rvi−Rv)2 ∑i∈I(Rui−Ru)(Rvi−Rv)
其中, R ‾ u \overline{R}{u} Ru和 R ‾ v \overline{R}_{v} Rv分别是用户 u u u和 v v v的平均评分。这个公式考虑了用户评分的整体趋势,比如有的用户习惯打高分,有的习惯打低分,它能排除这种评分尺度的影响。假设用户丙和用户丁对很多电影的评分整体趋势相似,即便评分数值不同,皮尔逊相关系数也能准确判断他们的相似性。
- 余弦相似度 :把用户的评分向量想象成空间中的向量。就像在一个多维空间里,用户甲对几部电影的评分构成一个向量,用户乙对同样几部电影的评分构成另一个向量。余弦相似度就是通过计算这两个向量夹角的余弦值来衡量相似程度。公式为:
- 筛选邻居用户
根据算出的相似度,为目标用户挑选与其最相似的 k k k个用户,这 k k k个用户就是目标用户的邻居用户。比如要给用户王五推荐电影,计算王五与其他用户的相似度,选取相似度最高的5个用户作为邻居用户,这5个邻居用户的喜好对给王五推荐电影很关键。 - 预测评分与生成推荐列表
基于邻居用户对目标用户未评分物品的评分,预测目标用户对这些物品的评分。常用加权平均法,预测公式为:
P u j = ∑ v ∈ N ( u ) sim ( u , v ) × R v j ∑ v ∈ N ( u ) sim ( u , v ) P_{uj}=\frac{\sum_{v \in N(u)}\text{sim}(u, v) \times R_{vj}}{\sum_{v \in N(u)}\text{sim}(u, v)} Puj=∑v∈N(u)sim(u,v)∑v∈N(u)sim(u,v)×Rvj
这里 P u j P_{uj} Puj是用户 u u u对物品 j j j的预测评分, N ( u ) N(u) N(u)是用户 u u u的邻居用户集合。比如已找到王五的5个邻居用户,对于王五没看过的一部电影,5个邻居用户有不同评分,且与王五相似度不同。用这个公式,把邻居用户评分乘以相似度加起来,再除以所有邻居用户与王五相似度总和,得到王五对这部电影的预测评分。然后按评分从高到低排序,把评分高的物品推荐给王五。
(二)基于物品的协同过滤
- 计算物品相似度
和基于用户的协同过滤类似,用余弦相似度或皮尔逊相关系数计算物品间相似度,不过是基于物品被用户评分的向量。比如在电商平台,根据用户对不同商品的评分计算商品间相似度。若很多用户对商品A和商品B评分都高,那商品A和商品B相似度可能高。 - 查找相似物品
为目标物品找到与其最相似的 k k k个物品。例如对于一款热门手机,计算它与其他手机的相似度,找出相似度最高的5款手机作为相似物品。 - 预测评分与生成推荐列表
根据目标用户对已评分物品的评分,结合相似物品与已评分物品的相似度,预测目标用户对未评分物品的评分。预测公式与基于用户的协同过滤类似,把用户相似度换成物品相似度。最后按预测评分排序生成推荐列表。
四、协同过滤的应用案例
(一)电商平台的商品推荐
以淘宝为例,当用户浏览并购买了一款运动鞋后,淘宝会依据基于物品的协同过滤算法,找出与这款运动鞋相似的其他运动鞋以及相关运动配件,像运动袜、运动水壶等,并推荐给用户。
下面是基于用户的协同过滤在电商场景下的Python代码示例:
python
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
def user_based_collaborative_filtering(user_item_matrix, target_user, k=5):
# 计算用户之间的余弦相似度
user_similarity = cosine_similarity(user_item_matrix)
# 获取目标用户的索引
target_user_index = np.where(np.arange(user_item_matrix.shape[0]) == target_user)[0][0]
# 获取目标用户与其他用户的相似度得分
user_similarity_scores = user_similarity[target_user_index]
# 找出与目标用户最相似的k个用户的索引
similar_user_indices = np.argsort(user_similarity_scores)[::-1][1:k + 1]
# 初始化预测评分向量
prediction = np.zeros(user_item_matrix.shape[1])
for similar_user in similar_user_indices:
# 获取相似用户与目标用户的相似度
similarity = user_similarity_scores[similar_user]
for item in range(user_item_matrix.shape[1]):
# 如果目标用户未对该物品评分,且相似用户对该物品有评分
if user_item_matrix[target_user, item] == 0 and user_item_matrix[similar_user, item] != 0:
# 累加相似用户评分乘以相似度
prediction[item] += similarity * user_item_matrix[similar_user, item]
# 对预测评分进行归一化处理
prediction = prediction / np.sum(np.abs(user_similarity_scores[similar_user_indices]))
# 对预测评分进行排序,获取推荐物品的索引
recommended_items = np.argsort(prediction)[::-1]
return recommended_items
# 示例用户 - 物品评分矩阵,行表示用户,列表示物品
# 这里假设评分范围为0 - 5分,0表示未评分
user_item_matrix = np.array([
[5, 3, 0, 1],
[4, 0, 0, 1],
[1, 1, 0, 5],
[1, 0, 0, 4],
[0, 1, 5, 4]
])
target_user = 0
recommended_items = user_based_collaborative_filtering(user_item_matrix, target_user)
print("基于用户的协同过滤推荐物品:", recommended_items)
代码中,user_based_collaborative_filtering
函数实现基于用户的协同过滤。接收用户 - 物品评分矩阵、目标用户索引和邻居用户数量作为参数。用cosine_similarity
函数计算用户间余弦相似度,找到目标用户邻居用户索引。根据邻居用户对未评分物品评分,结合相似度加权求和,预测目标用户对未评分物品评分。最后归一化处理预测评分,返回推荐物品索引。
(二)音乐平台的歌曲推荐
在网易云音乐中,当用户经常收听某歌手的歌曲时,系统会根据基于物品的协同过滤算法,推荐与该歌手风格相似的其他歌手的歌曲给用户。
下面是基于物品的协同过滤在音乐推荐场景下的Python代码示例:
python
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
def item_based_collaborative_filtering(user_item_matrix, target_user, k=5):
# 计算物品之间的余弦相似度
item_similarity = cosine_similarity(user_item_matrix.T)
# 获取目标用户的评分向量
target_user_ratings = user_item_matrix[target_user]
# 获取目标用户已评分物品的索引
item_indices = np.where(target_user_ratings != 0)[0]
# 初始化预测评分向量
prediction = np.zeros(user_item_matrix.shape[1])
for item in item_indices:
# 找出与当前物品最相似的k个物品的索引
similar_item_indices = np.argsort(item_similarity[item])[::-1][1:k + 1]
for similar_item in similar_item_indices:
# 获取相似物品与当前物品的相似度
similarity = item_similarity[item, similar_item]
for other_item in range(user_item_matrix.shape[1]):
# 如果目标用户未对该物品评分,且相似物品对应的用户评分不为0
if target_user_ratings[other_item] == 0 and user_item_matrix[:, similar_item][other_item] != 0:
# 累加相似物品评分乘以相似度
prediction[other_item] += similarity * user_item_matrix[:, similar_item][other_item]
# 对预测评分进行归一化处理
prediction = prediction / np.sum(np.abs(item_similarity[item_indices, :][:, similar_item_indices]), axis=1)
# 对预测评分进行排序,获取推荐物品的索引
recommended_items = np.argsort(prediction)[::-1]
return recommended_items
# 示例用户 - 物品评分矩阵,行表示用户,列表示歌曲
# 这里假设评分范围为0 - 5分,0表示未评分
user_item_matrix = np.array([
[5, 3, 0, 1],
[4, 0, 0, 1],
[1, 1, 0, 5],
[1, 0, 0, 4],
[0, 1, 5, 4]
])
target_user = 0
recommended_items = item_based_collaborative_filtering(user_item_matrix, target_user)
print("基于物品的协同过滤推荐物品:", recommended_items)
代码中,item_based_collaborative_filtering
函数实现基于物品的协同过滤。接收用户 - 物品评分矩阵、目标用户索引和相似物品数量作为参数。计算物品间余弦相似度得到物品相似度矩阵。找到目标用户已评分歌曲索引,根据相似物品与已评分物品相似度,结合目标用户对已评分物品评分,预测目标用户对未评分歌曲评分。最后归一化处理预测评分,返回推荐歌曲索引。
五、协同过滤面临的挑战与解决方案
(一)数据稀疏性问题
实际中,用户 - 物品评分矩阵往往很稀疏,因为用户通常只对少量物品评分。数据稀疏会导致算出的相似度不准确,影响推荐效果。
解决办法可以用降维技术,像奇异值分解(SVD),把高维评分矩阵分解成低维矩阵,减少稀疏性;也能引入辅助信息,比如物品类别、用户属性等,丰富数据。
(二)冷启动问题
冷启动包括新用户冷启动和新物品冷启动。新用户加入系统没历史评分数据,无法算与其他用户相似度;新物品加入系统没人对其评分,无法算与其他物品相似度。
对于新用户冷启动,可用基于内容的推荐方法,根据用户注册信息(年龄、性别、兴趣爱好等)推荐相关物品;对于新物品冷启动,可先人工标注或基于内容分析,与已有物品建立联系,再推荐。
六、总结
协同过滤是推荐系统的经典技术,原理简单、易实现,在电商、音乐、视频等很多领域广泛应用。不过它也面临数据稀疏性和冷启动等问题。随着技术发展,可结合深度学习、内容推荐等其他技术改进协同过滤算法,提升推荐系统性能和准确性,给用户更个性化、精准的推荐服务。