文章内容摘自《推荐系统实践》
实现个性化推荐的最理想情况是用户能在注册的时候主动告诉我们他喜欢什么,但这种方法有3个缺点:
- 首先,现在的自然语言理解技术很难理解用户用来描述兴趣的自然语言
- 其次,用户的兴趣是不断变化的,但用户不会不停地更新兴趣描述
- 最后,很多用户并不知道自己喜欢什么,或者很难用语言描述自己喜欢什么
基于用户行为分析的推荐算法是个性化推荐系统的重要算法,学术界一般将这种类型的算法成为协同过滤算法。顾名思义,协同过滤就是指用户可以齐心协力,通过不断地和网站互动,使自己的推荐列表能够不断地过滤掉自己不感兴趣的物品,从而越来越满足自己的需求。
用户行为数据简介
用户行为在个性化系统中一般分为两种——显性反馈行为(explicit feedback)和隐性反馈行为(implicit feedback)。显性反馈行为包括用户明确表示对物品喜好的行为,主要方式就是评分和喜欢/不喜欢。隐性反馈行为指的那些不能明确反应用户喜欢的行为。最具代表性的隐性反馈行为就是页面浏览行为。用户浏览一个物品的页面并不代表用户一定喜欢这个页面展示的物品,比如可能因为这个页面链接显示在首页,用户更容易点击它而已。
显性反馈数据 | 隐性反馈数据 |
---|---|
用户兴趣 | 明确 |
数量 | 较少 |
正负反馈 | 都有 |
按照反馈的明确性分,用户行为数据可分为显性反馈和隐性反馈,但按照反馈的方向分,又可以分为正反馈和负反馈。正反馈指用户的行为倾向于用户喜欢该物品,而负反馈指用户的行为倾向于指用户不喜欢该物品。在显性反馈中,很容易区分一个反馈是正反馈还是负反馈,而在隐性反馈行为中,就相对比较难确定。
用户活跃度和物品流行度的分布
很多关于互联网的研究发现,互联网上的很多数据分布都满足一种称为Power Law的分布,这个分布在互联网领域也称为长尾分布。
比如:
- 横轴是物品流行度,纵轴是刘成都为k的物品总数
- 横轴是用户活跃度,纵轴是活跃度为k的用户总数
用户活跃度和物品流行度的关系
一般认为,新用户倾向于浏览热门的物品,因为他们对网站还不熟悉,只能点击首页的热门物品,而老用户会逐渐开始浏览冷门物品。
仅仅基于用户行为数据设计的推荐算法一般称为协同过滤算法。最著名的、在工业界得到最广泛使用的算法是基于邻域的方法,主要包括:
- 基于用户的协同过滤算法:这种算法给用户推荐和他兴趣相似的其他用户喜欢的物品
- 基于物品的协同过滤算法:这种算法给用户推荐和他之前喜欢的物品相似的物品
试验设计和算法评测
实验设计
首先,将用户行为数据集按照均匀分布随机分成M份,挑选一份作为测试集,将剩下的M-1份作为训练集。然后在训练集上建立用户兴趣模型,并在测试集上对用户进行预测,统计出相应地评测指标。为了保证评测指标并不是过拟合的结果,需要进行M次实验,并且每次使用不同的测试集。然后将M次实验测出的评测指标平均值作为最终那个的评测指标。
如上描述的切分train及test数据的伪代码如下:
def SplitData(data, M, k, seed):
test = []
train = []
random.seed(seed)
for user, item in data:
# random.randint(a,b) 用于生成一个指定范围内的整数,a为下限,b为上限,生成的随机整数a<=n<=b
if random.randint(0, M) == k:
test.append( [user, item] )
else:
train.append( [user, item] )
return train, test
这里,每次实验选取不同的k (0<=k<=M-1)和相同的随机数种子seed,进行M次实验就可以得到M个不同的训练集和测试集,然后分别进行实验,用M次实验的平均值作为最后的评测指标。这样做主要是防止某次实验的结果是过拟合的结果(over fitting),但如果数据集够大,模型够简单,为了快速通过离线实验初步选择算法,也可以只进行一次实验。
评价指标
对用户u推荐N个物品记为R(u),令用户u在测试集上喜欢的物品集合为T(u),然后可以通过准确率/召回率评测推荐算法的精度:
召回率表示在用户最终喜欢的集合中,你推荐所占的百分比。比如,用户最终喜欢20个物品,你给用户推荐了10个物品,最终这推荐的物品中有5个在用户喜欢的列表中,那么召回率就是 5/20。
准确率表示你的推荐列表,用户接受多少百分比。比如,用户最终喜欢20个物品,你给用户推荐了10个物品,最终这推荐的物品中有5个在用户喜欢的列表中,那么召回率就是 5/10。
覆盖率即推荐给所有用户的物品的并集除以所有物品的集合,反映了推荐算法发掘长尾能力,覆盖率越高,说明推荐算法越能够将长尾中的物品推荐给用户。如果所有物品都被推荐给至少一个用户,那么覆盖率就是100%。
评价算法最重要的指标就是以上三个,其余还有多样性、新颖度、惊喜度、信任度、健壮性等。由于在实际生产过程中暂未使用这些指标,这些说明将在以后使用过后介绍。
基于用户的协同过滤算法(UserBasedCF)
基于用户的协同过滤算法主要包含两个步骤:
1. 找到和目标兴趣相似的用户集合
2. 找到这个集合中用户喜欢的,且目标用户没有听说过的物品推荐给目标用户
步骤1的关键就是计算两个用户的兴趣相似度。这里,协同过滤算法主要利用行为的相似度计算兴趣的相似度。给定用户u和用户v,令N(u)表示用户u曾经有过正反馈的物品集合,令N(v)为用户v曾经有过正反馈的用户集合。那么,我们可以通过如下的Jaccard公式简单计算u和v的兴趣相似度:
或者通过余弦相似度计算
要计算所有用户之间(假设有m个用户)的相似度,需要:
1. 建立 物品-用户 倒排表,及哪些用户喜欢了某物品
2. 建立m*m的用户共同喜欢物品矩阵,该矩阵每个元素为该元素对应两个用户共同喜欢的物品个数
如下图,a,b,c等小写字母为物品;A,B,C等大写字母。上半部分为 物品-用户 倒排表,下半部分为用户共同喜欢物品矩阵
得到用户之间的相似度后,UserBasedCF算法会给用户推荐和他最相似的K个用户喜欢的物品。如下公式度量了UserBasedCF算法中用户u对物品i的感兴趣程度:
其中, S(u,K) 为和用户u最相似的K个用户集合, N(i) 为喜欢物品i的用户集合, Wuv 为用户u和用户v的相似度, rvi 代表用户v对物品i的兴趣。如果使用的是单一行为的隐反馈数据,那么所有的 rvi 均为1;如果是显性反馈数据 rvi 就会有不同值,比如1,2,3,4,5的打分值等。
K
UserBasedCF只有一个重要的参数K,即为每个用户选出K个和他兴趣最相似的用户,然后推荐那K个用户感兴趣的物品。K值得不同,将直接影响召回率、准确率、覆盖率。
在UserBasedCF中,一般来说:
- 准确率和召回率:并不和K成线性关系。选择合适的K对于获得高的推荐系统精度比较重要
- 流行度:K越大则推荐结果就越热门。K越大,参考的人越多,结果就越来越趋近于全局人们的物品
- 覆盖率:K越大则覆盖率越低。流行度增大导致覆盖率降低
用户相似度计算的改进
有研究表明,两个用户对都喜欢冷门物品更能说明他们兴趣的相似度。越冷门的物品应该对『兴趣』影响越大。
可以看到,该公式通过 1log(1+|N(i)|) 惩罚了用户u和用户v共同喜欢的物品中热门物品对他们相似度的影响
UserBasedCF在现实中应用并不多