基于物品的协同过滤算法:理论说明,代码实现及应⽤
基于物品的协同过滤算法:理论说明,代码实现及应⽤
标签: 爬⾍ Python
主要参考资料:
项亮. 推荐系统实践[M]. 北京:⼈民邮电出版社, 2012.
0.⼀些碎碎念
从4⽉中旬开始,被导师赶到北京的郊区搬砖去了,根本就没有时间学习看书,这个时候才知道之前的⽣活是多么的幸福:每天看⾃⼰想看的书,然后实践⼀下,最后写博⽂总结⼀下,偶尔还能去跑个步,游个泳。想实习的计划也泡汤了,这个项⽬最早要到七⽉中下旬才能结束,只能⾃⼰挤时间学习了。
逝者如斯夫,不舍昼夜。
1.基于物品的协同过滤算法简介
如今⽹上信息泛滥,想要在⾥⾯⼀条适合⾃⼰的信息的成本真的有点⾼,所以就有了推荐系统。于⽤户
⽽⾔,推荐系统能够节省⾃⼰的时间;于商家⽽⾔,推荐系统能够更好的卖出⾃⼰的商品。
基于邻域的推荐算法是推荐系统中最基本的算法,该算法分为两⼤类:基于⽤户的协同过滤算法(UserCF)和基于物品的协同过滤算法(ItemCF)。
基于⽤户的协同过滤算法就是到和“⽬标⽤户”相似的⽤户,然后把他喜欢的东西推荐给“⽬标⽤户”。例如⼩王和⼩赵⼀对好基友,他俩喜欢看的书风格基本相同。如果有⼀天,系统发现⼩赵给⾃⼰的书架添加了⼀本新书,并且评价很⾼,那么系统就把这本书⾃动推荐给了⼩王,因为⼩王喜欢这本书的概率很⼤。设表⽰⽤户喜欢的物品,表⽰⽤户喜欢的物品,则两个⽤户的相似度为:相⽐于基于⽤户的协同过滤算法,基于物品的协同过滤算法在⼯业界应⽤更多,因为基于⽤户的协同过滤算法主要有两个缺点:
随着⽹站的⽤户数⽬越来越⼤,计算⽤户数的相似度将会越来越困难,其运算的时间复杂度和空间复杂度基本和⽤户的增长数成平⽅关系
基于⽤户的协同过滤算法很难对推荐结果做出解释
基于物品的协同过滤算法就是到和“⽬标⽤户”喜欢的物品相似的物品,然后把相似的物品推荐给“⽬标⽤户”。例如我很喜欢《⿊客帝国》,⽽《盗梦空间》和《⿊客帝国》相似度很⾼,推荐系统就可以给我推荐《盗梦空间》,实际上我也很喜欢《盗梦空间》。
2.基于物品的协同过滤算法实现基于物品的协同过滤算法主要有两步:计算物品之间的相似度
根据物品的相似度和⽤户的历史⾏为给⽤户⽣成推荐列表
2.1计算物品的相似度
设表⽰喜欢物品的⽤户数,表⽰同时喜欢物品物品的⽤户数,则物品物品的相似度为:
N (u )u N (v )v w =∣N (u )N (v )∣⋃∣N (u )N (v )∣
⋂(1)
∣N (i )∣i ∣N (i )N (j )∣⋂i j i j w =ij ∣N (i )∣∣N (i )N (j )∣
⋂(2)
(2)式有⼀个问题,当物品是⼀个很热门的商品时,⼈⼈都喜欢,那么就会很接近于1,即(2)式会让很多物品都和热门商品有⼀个很⼤的相似度,所以可以改进⼀下公式:
2.1.1建⽴⽤户物品倒排表
ItemCF⾸先需要建⽴⽤户物品倒排表。设⽤⼤写字母表⽰⽤户,⼩写字母表⽰物品,则建⽴的⽤户物品倒排表为:
⼀般情况下,数据都是⽤户物品倒排表,只需要从原始数据中提炼出来即可,此处就不做代码实现了,因为不同系统的数据不⼀样(不过可以参考后⾯应⽤部分建⽴⽤户物品倒排表的代码)。
2.1.2计算共现矩阵C
共现矩阵C表⽰同时喜欢两个物品的⽤户数,是根据⽤户物品倒排表计算出来的。如根据上⾯的⽤户物品倒排表可以计算出如下的共现矩阵C:
共现矩阵的对⾓线元素全为0,且是实对称稀疏矩阵。
实现代码如下:
from collections import defaultdict #可以直接使⽤下标访问⼆维字典不存在的元素
def cal_corated_users (train ):
C = defaultdict (defaultdict ) #⽤户与⽤户共同喜欢物品的个数
N = defaultdict (defaultdict ) #⽤户个数
for u , items in train .items ():
for i in items :
if i not in self .N .keys (): #如果⼀维字典中没有该键,初始化值为0
N [i ] = 0
N [i ] += 1
for j in items :
if i == j :
continue
if j not in self .C [i ].keys (): #如果⼆维字典中没有该键,初始化值为0
C [i ][j ] = 0
C [i ][j ] += 1
2.1.3计算余弦相似度矩阵W
共现矩阵C其实就是式(3)的分⼦,矩阵N表⽰喜欢某物品的⽤户数,那么余弦相似度矩阵很容易就计算出来了,⽰例的矩阵N,以及余弦相似度矩阵如下所⽰:
a和d之间的相似度最⾼。
实现代码如下:
def cal_matrix_W ():
for i , related_items in C .items ():
for j , cij in related_items .items ():
W [i ][j ] = cij / math .sqrt (N [i ] * N [j ]) #余弦相似度
2.2根据物品的相似度和⽤户的历史⾏为给⽤户⽣成推荐列表
最终推荐的是什么物品,是由预测兴趣度决定的。物品预测兴趣度=⽤户喜欢的物品的兴趣度物品和物品的相似度。
例如某个⽤户喜欢物品a,b和c,对其兴趣度分别为1,2,2. 那么物品d和e的预测兴趣度分别为:
j w ij w =ij ∣N (i )∣∣N (j )∣∣N (i )N (j )∣⋂(3)
j i ×i j
d:e:所以应当向该⽤户推荐物品d。
实现代码如下:
def recommend (train , user_id , W , K ):
rank = dict ()
ru = train [user_id ] #⽤户数据,表⽰某物品及其兴趣度
for i , pi in ru .items (): #i 表⽰⽤户已拥有的物品id ,pi 表⽰其兴趣度
#j 表⽰相似度为前K 个物品的id ,wj 表⽰物品i 和物品j 的相似度
for j , wj in sorted (W [i ].items (), key =itemgetter (1), reverse =True )[0:K ]
if j in ru : #如果⽤户已经有了物品j ,则不再推荐
continue
rank [j ] += pi * wj
return rank
3.基于物品的协同过滤算法应⽤之前写了两篇博⽂,实现了⾖瓣书籍信息的爬取:
其中爬取的某项信息很关键,即某书籍的推荐书籍,如下图所⽰:
假设把《代码⼤全》看做⼀个⽤户,那么这些推荐书籍就可以看做该⽤户喜欢的物品,在数据库中的形式如下:
将爬取的数据稍微处理⼀下,⼀共得到40558本书籍的相关信息,即40558个⽤户的信息,那么就可以根据这40558个⽤户的信息计算余弦相似度矩阵,进⾏书籍推荐。
把整个计算过程封装到⼀个类⾥⾯,依次建⽴⽤户物品倒排表,计算共现矩阵C,计算余弦相似度矩阵
W。由于计算余弦相似度矩阵W较为费时(本例⼤概需要20分钟),所以计算之后使⽤pickle.dump()把W矩阵保存在本地,下次程序重启的时候直接使⽤pickle.load()载⼊即可,⼤概需要7s。编写itemCF(self, urls)函数⽣成推荐列表,urls表⽰⽤户所有添加到书架中的书籍的url,返回预测兴趣度TOP10书籍的url。
使⽤PyQt4编写⽤户界⾯,⽅便搜索,查看,添加,删除和推荐书籍,具体如下:
代码大全书籍《统计学习⽅法》是⼀本好书,加⼊到书架中,看看会推荐什么书籍:
《机器学习实战》不错,是《统计学习⽅法》的黄⾦搭档,添加到书架⾥⾯,再看看推荐书籍:
试⼀试⽂学类的书籍,⽐如《夏洛的⽹》,看看推荐书籍:
4.⼀些讨论
Q:UserCF和ItemCF分别适⽤于什么情况?
A:UserCF根据相似⽤户推荐,更社会化;ItemCF根据⽤户本⾝的历史记录推荐,更加个性化。UserCF较适⽤于新闻,社区等⽹站,ItemCF较适⽤于购物等⽹站。
1×0.71+2×0.58+2×0.58=3.03
2×0.58+2×0.58=2.32
Q:UserCF和ItemCF的余弦相似度矩阵W有什么异同?
A:UserCF的相似度矩阵表⽰⽤户之间的相似度,适⽤于⽤户较少物品较多的场合;ItemCF的相似度矩阵表⽰物品之间的相似度,适⽤于⽤户较多物品较少的场合。⽬前的购物⽹站中,物品数量远远⼩于⽤户数量,所以购物⽹站⼤多采⽤ItemCF。
Q:如何评价⼀个推荐系统的优劣?
A:评价⼀个推荐系统有3种⽅法:离线实验,⽤户调查和在线实验。评测的指标有:⽤户满意度,预测准确度,覆盖率,多样性,新颖性,惊喜度,信任度,实时性,健壮性和商业⽬标。
5.⼩结
,期待你的star
计算物品的相似度是ItemCF的关键
计算物品相似度矩阵W有3个步骤:建⽴⽤户物品倒排表,计算共现矩阵C,计算余弦相似度矩阵W
选取前K个相似度的物品进⾏推荐,其中参数K对推荐系统的准确率,召回率,覆盖率和流⾏度都有影响
协同过滤算法的推荐质量取决于⽤户的历史数据集,有可能有偏差
ItemCF需要维护物品相似度矩阵W,⼀般⼀天更新⼀次
实际应⽤中的ItemCF往往会增加对流⾏物品的惩罚度,因为流⾏物品和任意物品的相似度都很⾼,⽽⼀个优秀的推荐系统应该能够进⾏长尾物品推荐
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论