主题
我将在这篇文章中简单介绍一下协同过滤,介绍下协同过滤的定义,介绍基于物品和基于用户协同过滤的含义和区别,重点介绍一下基于物品协同过滤的共现矩阵实现方式。
以此文记录下我学习协同过滤的的心得和实践感受,某些观点可能较为主观,有问题可以提出。
协同过滤
协同过滤推荐方法的主要思想是利用用户群过去的行为来预测当前用户可能喜欢哪些物品或者对哪些物品感兴趣。其包含两种协同过滤技术,一种是Memory Based的协同过滤技术,Memory Based协同又包含基于用户的协同过滤(User-Based CF)和基于物品的协同过滤(Item-Based CF);另一种是基于模型的协同过滤,基于模型的协同过滤包含隐语义模型(LFM)和Bayesian Networkds等技术。其中,基于用户和基于物品的协同过滤算法因为在推荐时需要利用近邻用户或物品,所以又称为基于邻域的算法。
基于用户的协同过滤
基于用户的协同过滤的思想是,如果你要给一个用户进行推荐,那么你先找到跟这个用户兴趣爱好相似的其他用户,然后将其他用户喜欢的物品推荐给该用户。比如计算发现A用户和B用户的兴趣爱好很相似,那么就可以给A推荐B喜欢的物品,给B推荐A喜欢的物品。基于用户的协同过滤主要包括两个步骤:
- 找到和这个目标用户兴趣相似的用户集合
- 找到这个集合中用户喜欢的,且目标用户没有听说过的物品推荐给目标用户。
1.计算用户相似度
给定一个平台的用户数据,比如豆瓣或者京东的,如何判断两个用户相似并且量化这种相似程度呢。推荐系统往往使用的用户对该平台的物品的评分或者行为来进行计算的。这里涉及到一个显式反馈和隐式反馈的概念。显式反馈就是用户行为能够明确表达用户喜好的行为数据,比如用户的评分、点赞、收藏等,相对的,隐式反馈就是用户行为无法直接体现用户的喜好的,比如用户的浏览、驻留时间、购买等。
对于显式反馈有用户评分这种,在得到用户-物品评分矩阵后,可以使用相关距离算法比如欧几里德、余弦、Pearson相关性系数等来计算用户之间的距离。
用户\物品 | item1 | item2 | item3 | item4 | item5 | item6 | item7 | item8 |
---|---|---|---|---|---|---|---|---|
user1 | 0.21 | 0 | 0 | 0 | 0.82 | 0 | 0 | 0.45 |
user2 | 0 | 0 | 0.23 | 0 | 0.65 | 0 | 0 | 0 |
user3 | 0.30 | 0.34 | 0 | 0 | 0.75 | 0 | 0 | 0.15 |
user4 | 0.23 | 0 | 0 | 0 | 0 | 0 | 0.78 | 0 |
user5 | 0 | 0 | 0.34 | 0.65 | 0 | 0 | 0 | 0.23 |
比如对于上面表格的数据,我们可以对任意两个用户计算余弦值以表示用户之间的相似度。
对于隐式反馈的用户行为不涉及评分的,在得到用户行为列表后可以将用户行为数据转化为上面的用户-物品评分矩阵,比如对用户不同的行为定义权值,用户对商品的行为次数也定义权值等来得到评分矩阵,然后运用上述的距离算法来计算。而在《推荐系统实践》一书里是在用户行为列表的基础上利用两用户对商品行为集合的差异使用Jaccard或者余弦进行相似度计算的。具体的,对于给定用户u和用户v,另N(u)表示用户u曾经有过正反馈的物品集合,N(v)表示用户v曾经有过正反馈的物品集合。
那么利用Jaccard公式来计算用户u和v之间的相似度可以:
或者通过余弦相似度计算:
2.进行推荐
在得到用户之间的兴趣相似度后,基于用户的协同过滤会给用户推荐与该用户最相似的K个用户喜欢的物品。可以使用如下的公式来度量用户u对物品i的感兴趣程度。
其中,S(u,K)包含和用户u兴趣最接近的K个用户,N(i)是对物品i有过行为的用户集合,
也就说,算法从所有用户中挑选出跟用户u最相似的K个用户作为近邻用户,接着在这些近邻用户中挑出所有对物品i有过行为的用户,之后利用这些有行为的用户对物品i的兴趣值以及这些用户与用户u之间的相似程度得到用户u对物品i的感兴趣程度分值。
这里,如果使用的是单一的隐式反馈行为数据,那么用户v对物品i的兴趣值
基于物品的协同过滤
基于物品的协同过滤的思想与基于用户的协同过滤相似,只是将用户替换成物品了。这个算法的思想是,如果你要给一个用户进行推荐,首先看这个用户喜欢过哪些物品,然后找到这些他喜欢过物品的相似的物品,然后将找到的这些相似的物品推荐给这个用户,比如用户喜欢《机器学习实战》这本书,然后计算发现《集体智慧编程》这本书与《机器学习实战》很像,然后就可以给用户推荐《集体智慧编程》这本书。基于物品的协同过滤主要包括两个步骤:
- 计算物品之间的相似度
- 根据物品之间的相似度和用户的历史行为给用户生成推荐列表
1. 计算物品之间的相似度
一般是使用用户的行为数据来计算两个物品之间相似度的。
用户\物品 | item1 | item2 | item3 | item4 | item5 | item6 | item7 | item8 |
---|---|---|---|---|---|---|---|---|
user1 | 0.21 | 0 | 0 | 0 | 0.82 | 0 | 0 | 0.45 |
user2 | 0 | 0 | 0.23 | 0 | 0.65 | 0 | 0 | 0 |
user3 | 0.30 | 0.34 | 0 | 0 | 0.75 | 0 | 0 | 0.15 |
user4 | 0.23 | 0 | 0 | 0 | 0 | 0 | 0.78 | 0 |
user5 | 0 | 0 | 0.34 | 0.65 | 0 | 0 | 0 | 0.23 |
对于用户评分矩阵(如上表),我们可以使用一些距离算法来计算物品之间的相似度,与基于用户的协同过滤不同的是,这里可以将一个物品的所有用户对其的评分作为这个物品的向量,然后计算两个物品向量之间的长度,而基于用户的协同过滤则是将一个用户对所有物品的评分作为这个用户向量从而计算用户之间相似度的。
同样的,如果我们获取的是隐式反馈数据,得到了用户物品的行为列表后,我们可以利用两物品之间的用户集合差异来计算物品之间的相似度。在《推荐系统实践》书中给出下面的公式来计算物品之间的相似度:
其中N(i)和N(j)分别表示喜欢物品i和j的用户数,
2. 进行推荐
在得到物品之间的相似度后,ItemCF通过如下公式来计算用户u对物品j的兴趣:
其中,N(u)是用户喜欢的物品的集合,S(j,K)是和物品j最相似的K个物品的集合,
这个公式的意思是说,如果要计算用户u对物品j的兴趣,当K为物品全集大小时,算法将计算用户u喜欢过的每个物品i与物品j之间的相似度,并将这个相似度用用户u对i的喜爱程度进行修饰,然后将这些修饰后的结果累计起来,就成了用户u对物品j的兴趣值。一般的,如果K不是物品全集大小的话,那么要将与物品j最相似的K个物品集合与用户u喜欢的物品集合做个交集,然后进行计算。
一般如果是使用隐式反馈数据集的话,
例子
这里举一个例子来介绍下基于物品的过滤的一种实现。
假如我们有用户行为记录如下:
User1:item2,item3,item4,item5
User2:item2,item4
User3:item1,item5
User4:item1,item3,item5
User5:item2,item3,item4
User6:item2,item3
1. 计算共现矩阵
利用这六个用户的行为记录,我们可以构建如下的共现矩阵C。共现矩阵的构建方法是,首先建立一个N*N的零矩阵,N为物品数目大小,遍历一条用户行为记录,如果用户行为记录中出现了物品i和j,那么将C[i][j]以及C[j][i]的值各加1,如此遍历完所有的用户行为记录即可。
C(concurrence matrix) | item1 | item2 | item3 | item4 | item5 |
---|---|---|---|---|---|
item1 | 0 | 0 | 1 | 0 | 2 |
item2 | 0 | 0 | 3 | 3 | 1 |
item3 | 1 | 3 | 0 | 2 | 2 |
item4 | 0 | 3 | 2 | 0 | 1 |
item5 | 2 | 1 | 2 | 1 | 0 |
2. 计算相似度矩阵
在得到上述共现矩阵C后,我们使用公式
依次按公式计算任意两个物品之间的相似度,比如计算物品1和3之间的相似度:
S(similarity matrix) | item1 | item2 | item3 | item4 | item5 |
---|---|---|---|---|---|
item1 | -100.0 | 0.0 | 0.354 | 0.0 | 0.816 |
item2 | 0.0 | -100.0 | 0.75 | 0.866 | 0.289 |
item3 | 0.354 | 0.75 | -100.0 | 0.577 | 0.577 |
item4 | 0.0 | 0.866 | 0.577 | -100.0 | 0.333 |
item5 | 0.816 | 0.289 | 0.577 | 0.333 | -100.0 |
3. 进行推荐
在得到物品相似度矩阵S后,即可进行推荐了。
假定我们要给用户User7进行推荐,User7的行为记录为:item3,item4,将该行为记录转化为用户行为向量U = [0.0, 0.0, a, b, 0.0]T,由于我们使用的隐式反馈数据集,所以a和b的分值一般为1.0,即用户向量U为[0.0, 0.0, 1.0, 1.0, 0.0]T。
将物品相似度矩阵S与用户向量U做乘法,得到结果向量R,即S×U=R。R为N*1的矩阵,即R = [r1, r2, r3, r4, r5],ri表示用户对物品i的兴趣值。
具体计算过程为:
r1 = [-100.0, 0.0, 0.354, 0.0, 0.816] * [0.0, 0.0, 1.0, 1.0, 0.0]T = 0.354
r2 = [0.0, -100.0, 0.75, 0.866, 0.289] * [0.0, 0.0, 1.0, 1.0, 0.0]T = 1.616
r3 = [0.354, 0.75, -100.0, 0.577, 0.577] * [0.0, 0.0, 1.0, 1.0, 0.0]T ≈ -100
r4 = [0.0, 0.866, 0.577, -100.0, 0.333] * [0.0, 0.0, 1.0, 1.0, 0.0]T ≈ -100
r5 = [0.816, 0.289, 0.577, 0.333, -100.0] * [0.0, 0.0, 1.0, 1.0, 0.0]T = 0.910
于是得到R = [0.354, 1.616, -100, -100, 0.910]
此时,如果想给User7推荐一个物品的话,那就首推物品2,如果想给User7推荐两个物品的话,那么就推荐物品2和物品5.
3. 效果评估
推荐系统效果的评估有很多种方法,离线的方式除了使用精确率(Precision),召回率(Recall),F1值之外,还可以使用覆盖率、流行度、新颖度等,而在线方式则可以通过ABtest进行相关数据统计与对比,比如进行GMV数据比较、PV与UV比较等。
4. 改进方式
一般来说这里没有非常统一的改进方法,具体的改进方法都是要结合实际的业务来进行的。这里提一下我遇到过的几种改进方式,主要是针对隐式反馈数据集的。
《推荐系统实践》那本书中提到的:
- 归一化:对ItemCF物品相似度矩阵进行行或列归一化可能能够提高推荐的准确率。
- User-IIF:如果两个用户对冷门物品采取过同样的行为更能说明他们的兴趣相似度。
- IUF(Inverse User Frequence): 活跃用户对物品的相似度的贡献应该小于不活跃的用户。
其他的:
- 时间衰减:实际中用户的行为都是带有时间戳的,往往越近的用户行为越能够表示用户/系统目前的状态,另外,如果用户对两个物品的行为的时间越近,那么这两个物品的就越可能相似,比如你看了A衬衫后会接着浏览B衬衫。
- 用户行为权值调整:虽然我们在使用隐式反馈数据集都默认其权重为1.0,但是如果我们能够更细化对待用户行为的话,可能能够带来更好的效果。比如对于电商,有浏览、加购物车、购买等行为,那用户对某个商品进行了购买肯定会比用户只是看了某商品更能体现其对该商品的喜好,于是用户的购买分值可以设为1.1,浏览就设为1.0这种。当然,用户对商品的行为次数可能不只一次,如果用户多次看了某商品,说明用户对该商品可能更感兴趣,所以可以根据行为次数进行权值的调整。
- 利用标签信息:利用下物品本身内容相关的信息可以用来提高物品之间的相似度,比如两个物品同属于亚洲恐怖电影这个小分类,或者物品的标签很相似,那么可以将两物品的相似度修饰一个更高的值。
- 利用关联规则结果:关联规则算法比如Apriori算法可以得出物品之间的购买关系,比如买了刮胡刀后推导出用户会购买刮胡刀片,此时可以用这个结果来修饰物品的相似度矩阵分值,将相似矩阵的S[刮胡刀][刮胡刀片]的用一个更大一点的分值修饰。
- 互信息:互信息能够提现两个物品之间的联系,比如物品A出现则多半出现物品B,或者物品A出现则多半不出现物品B,在这种情况下,可以利用物品之间的互信息来修饰相似度矩阵。
- 利用人口统计信息:假设我们拥有一些用户的人口统计信息,比如知道用户的性别,知道用户的年龄,知道用户的收入等,那么这个时候,我们在进行推荐的时候可以利用上这些信息,对于男性可以提高男性用户或偏男性用户的分值,提高符合其年龄的商品的分值,提高符合其收入的商品的分值等,这样使得符合用户特征的商品更容易被推荐出来。甚至,我们可以将用户按照性别等特征进行人群划分,然后在细分的人群上进行协同过滤,然后使用这种数据得出的推荐模型进行推荐。
- 数据清洗:数据必然是越准确越好,比如去除爬虫用户,去除用户行为太少的用户等
UserCF VS ItemCF
这里比较下基于用户的协同过滤和基于物品的协同过滤的异同。
- 基于用户的协同过滤:适合用户数不太大的场合,实时性较差,当用户行为有变化时,需要等待新的用户相似度矩阵计算完成后才能更新推荐结果。可解释性较差,但是新物品能够很快进入推荐列表。着重反映和用户兴趣相似的小群体的热点,推荐结果偏向于小群体内热门的物品。
- 基于物品的协同过滤:适合物品数较少的场合,然后可以进行即时推荐,当用户行为有变化时,即可进行新的推荐。但是推荐出的物品多和用户已经喜欢的物品高度相似,难以推出用户潜在的喜欢的物品,多样性较差。可解释性较强,你可以说给你推荐《集体智慧编程》是因为它跟用户曾经喜欢的《机器学习实战》很像。着重于维系用户的历史兴趣,推荐结果偏向于用户自身的兴趣,更个性化。
协同过滤的优点有:
- 能够处理非结构化数据,比如音乐,电影等
- 不需要领域知识,使用的是群体的智慧
- 随着用户量增长,用户行为的变多,推荐效果会变的越好
- 可以挖掘用户潜在的兴趣爱好
其缺点有:
- 稀疏问题,用户往往只会对少数物品有过行为,导致用户-物品评分矩阵比较稀疏
- 冷启动:对于新用户或新物品,如何对新用户进行推荐(新用户用户行为少,推荐推荐效果差),如何给用户推荐新物品(新物品的用户行为少,推荐效果差)
- 计算量问题:当用户数庞大或者物品数目庞大的时候,如何进行计算和存储并进行即时推荐是个问题