1 什么是协同过滤算法
协同过滤算法是指根据用户过去的喜好或兴趣相近的用户的选择来进行推荐。根据用户过去的喜好来推荐,简单来说就是,如果用户过去购买过物品A,而物品B与物品A有着相似的特点(注意这里的特点与物品本身的属性无关,指的是不同用户对物品A和物品B的行为是相似的,例如各个用户对物品A和物品B的评分相似),那么我们就把物品B推荐给该用户,这就是基于物品的协同过滤算法(ItemCF)。根据兴趣相近的用户的选择来推荐,就是指如果用户A和用户B对于各个物品的行为(例如评分或浏览时长等)是相似的,而用户A喜欢物品C,我们就把物品C推荐给用户B,这就是基于用户的协同过滤算法(UserCF)。
2 如何衡量相似性
于是,问题就来了,我们要怎么判断两个用户或两个物品相似呢?我们可以通过三种方法来衡量相似性。
2.1 杰卡德(Jaccard)相似系数
杰卡德相似系数计算两用户u和v共同购买或喜爱的物品数量占他们二者总共购买或喜爱的物品数量的比值。其计算公式如下:

但是杰卡德相似系数只能判断用户是否会购买或喜爱某个物品,而无法给出用户对该物品的具体评分。
2.2 余弦相似度
余弦相似度是一种数学中常用的方法,用于计算两个向量之间的夹角,若夹角较小,那么该夹角的余弦就大,就说明两个向量越相似。其计算公式如下:

这里的u和v指的是用户u和用户v关于所有物品的评分向量。
2.3 皮尔逊相关系数
余弦相似度只考虑了用户的评分,但是不同用户的评分原则是不一样的,有些用户喜欢打高分,而另一些用户可能会比较挑剔,打分都偏低,这就导致光看用户的评分并不能判断该用户对某物品的喜爱程度。于是,皮尔逊相关系数采用用户评分的平均值来进行修正,根据用户评分与平均值的差值来计算相似度,其计算公式如下:

皮尔逊相关系数与余弦相似度的计算方法类似,都是计算两向量夹角的余弦值,不同的是皮尔逊相关系数计算的是两用户评分与平均值的差值向量的夹角余弦。
接下来,我们分别采用UserCF和ItemCF算法,根据以下用户-物品评分表,来预测user1对item7的评分,根据预测的评分判断是否要将item7推荐给user1。
| User\Item | item1 | item2 | item3 | item4 | item5 | item6 | item7 |
|---|---|---|---|---|---|---|---|
| user1 | 4 | 5 | 1 | 4 | 2 | 3 | None |
| user2 | 2 | 2 | 4 | 3 | 5 | 5 | 3 |
| user3 | 5 | 5 | 2 | 4 | 1 | 2 | 1 |
| user4 | 3 | 4 | 5 | 1 | 3 | 2 | 2 |
| user5 | 1 | 2 | 5 | 5 | 4 | 5 | 2 |
| user6 | 4 | 5 | 3 | 1 | 3 | 1 | 3 |
| user7 | 2 | 3 | 1 | 5 | 5 | 3 | 5 |
3 基于用户的协同过滤算法(UserCF)
UserCF算法主要有两个步骤:
- 计算目标用户user1与其他用户之间的相似度,取相似度高的前K个用户作为评分预测的依据
- 根据这K个用户对item7的评分来预测user1对item7的评分
要预测user1对item7的评分,我们首先刨掉各用户的item7的评分数据,计算其他用户对除item7以外物品的评分与user1对除item7以外物品的评分的相似度。
usercf_data = data.drop('item7', axis=1)
usercf_data

然后计算其他用户与user1的相似度,这里采用皮尔逊相关系数。
#计算皮尔逊相关系数的函数
def cal_pearson(data1, data2):
pearson = np.sum(np.multiply(data1-np.mean(data1), data2-np.mean(data2)))/np.sqrt(np.sum((data1-np.mean(data1))**2))/np.sqrt(np.sum((data2-np.mean(data2))**2))
return pearson
#计算其他各个用户与user1的皮尔逊相关系数
user_pearson = []
for u in range(2, 8):
data1 = usercf_data.loc['user1'].values
data2 = usercf_data.loc['user'+str(u)].values
pearson = cal_pearson(data1, data2)
user_pearson.append(pearson)
print('user'+str(u), pearson)

从以上结果可以看到,user3、user6和user7与user1的相关系数最高,于是我们取K=3。
如何根据这三个用户对item7的评分来预测user1对item7的评分呢,最简单的想法就是以相关系数为权重,将三个用户对item7的评分进行加权求和:

然而,同样要考虑的不同用户有不同的评分原则,所以一种更常用的方法是将三个用户的评分与其评分均值之差进行加权求和,求和得到的结果是user1对item7的评分距其评分均值的偏差,所以还要加上他的评分均值才是最终预测的评分。
注意,计算皮尔逊相关系数时所采用的均值是各用户对item1至item6的评分均值,而在预测评分时我们会将用户对item7也考虑进去,计算各用户对包括item7的所有商品的均值。
k = 3
sort_u = np.argsort(user_pearson)[::-1] #取出相关系数最大的前K个用户的索引
user_k = []
for u in sort_u[:k]:
user_k.append('user'+str(u+2)) #得到该索引所代表的用户
pred = 0
sum_pearson = 0
#加权求得所预测的评分
for i, u in enumerate(user_k):
pred += (data['item7'].loc[u]-np.mean(data.loc[u])) * user_pearson[sort_u[i]]
sum_pearson += user_pearson[sort_u[i]]
pred /= sum_pearson
pred += np.mean(usercf_data.loc['user1'])
print(pred)
打印得到预测评分:

将user1对所有物品的评分进行排序:
item2>item1=item4>item6>item7>item5>item3
item7的评分并不靠前,所以如果我们只对user1推荐前3个物品的话,就不会将item7推荐给他。
4 基于物品的协同过滤算法(ItemCF)
ItemCF算法也分为两个步骤:
- 计算目标物品item7与其他物品之间的相似度,取相似度高的前K个物品作为评分预测的依据
- 根据user1对这K个物品的评分来预测其对item7的评分
同样,要预测user1对item7的评分,首先刨掉用户user1的评分数据。

然后,计算其他物品与item7之间的皮尔逊相关系数。
def cal_pearson(data1, data2):
pearson = np.sum(np.multiply(data1-np.mean(data1), data2-np.mean(data2)))/np.sqrt(np.sum((data1-np.mean(data1))**2))/np.sqrt(np.sum((data2-np.mean(data2))**2))
return pearson
item_pearson = []
for i in range(1, 7):
data1 = itemcf_data['item7'].values
data2 = itemcf_data['item'+str(i)].values
pearson = cal_pearson(data1, data2)
item_pearson.append(pearson)
print('item'+str(i), pearson)
得到各物品与item7的相关系数如下:

从以上结果可以看到,item4、item5和item6与item7的相关系数最高,于是我们同样取K=3。
同样以相关系数为权重,采用加权求和的方法,但在这里,用的是user1对这三个物品的评分与这三个物品的评分均值的差进行加权求和,也就是根据user1对三个相似物品的评分来得到预测评分,最后要加上item7的评分均值。
注意,同样的,这里计算的物品评分均值是考虑到包括user1在内的所有用户的评分均值。
k = 3
sort_i = np.argsort(item_pearson)[::-1]
item_k = []
for i in sort_i[:k]:
item_k.append('item'+str(i+1))
pred = 0
sum_pearson = 0
for j, i in enumerate(item_k):
pred += (data[i].loc['user1']-np.mean(data[i])) * item_pearson[sort_i[j]]
sum_pearson += item_pearson[sort_i[j]]
pred /= sum_pearson
pred += np.mean(itemcf_data['item7'])
print(pred)
打印预测评分:

将user1对所有物品的评分进行排序:
item2>item1=item4>item6>item5>item7>item3
item7的评分靠后,所以根据这个预测结果我们仍然不会推荐item7。
5 总结
UserCF要计算两两用户之间的相似度,当用户数量太大时,计算开销大,所以UserCF适用于用户数量较少的情况。
ItemCF要计算两两物品之间的相似度,所以只适用于物品数量较少的情况。
但是,不管是UserCF还是ItemCF都只考虑了用户的行为,而没有考虑到用户本身的属性和物品本身的属性所包含的信息,这就导致热门的物品与大量其他物品相似,而不够热门的物品就很难得到推荐。因此,协同过滤算法很少应用在实际的推荐系统中。
本文介绍了协同过滤算法的基础知识,包括UserCF和ItemCF两种策略。通过衡量用户或物品间的相似性(如杰卡德相似系数、余弦相似度和皮尔逊相关系数),预测用户对未评价物品的评分,从而实现推荐。在实践中,UserCF适用于用户数量较少,而ItemCF适用于物品数量较少的情况。但由于协同过滤算法忽视了用户属性和物品属性,所以在实际推荐系统中应用有限。

656

被折叠的 条评论
为什么被折叠?



