最近想了解下推荐系统,阅读了《推荐系统实践》(项亮),本文简单介绍推荐系统常用算法的原理,大部分内容来自项亮大牛的书籍。
随着信息技术的发展,互联网上的信息量快速增长。为了在众多信息中找到想要的内容,常用的方式有——
与分类目录和搜索引擎相同,推荐系统也是一种针对信息过载的解决方案,通过分析用户的行为、兴趣等数据,主动给用户推荐满足其兴趣和需求的信息,区别在于——
推荐系统已经在很多互联网产品中使用,常见的使用场景有——
推荐系统根据优化目标的不同,常被分为两种类型——
由于早期推荐系统研究是基于电影评分数据的评分预测问题,因此绝大多数推荐系统研究都是基于用户评分数据的评分预测。而在实际应用中,TopN问题更加常用,原因在于——
本文介绍的推荐系统算法是用于求解TopN问题的。
实现推荐系统的算法有很多,但大致可分为三类,下面会依次介绍其基本原理。
在介绍的过程中,使用的数据为用户的隐性数据,如浏览行为。
协同过滤算法(也称为基于邻域的算法)分为两大类,分别是基于用户的协同过滤(UserCF)和基于物品的协同过滤(ItemCF),是推荐系统中最经典的算法。
UserCF的思想是根据用户行为数据,找到与目标用户有相似兴趣的其他用户,给用户推荐其他用户喜欢的物品。
其算法流程分为两步:
w u v = ∣ N ( u ) ∩ N ( v ) ∣ ∣ N ( u ) ∣ ∣ N ( v ) ∣ 其 中 , N ( u ) 表 示 用 户 u 产 生 过 行 为 的 物 品 集 合 w_{uv}=\frac{|N(u)\cap N(v)|}{\sqrt{|N(u)||N(v)|}}\\其中,N(u)表示用户u产生过行为的物品集合 wuv=∣N(u)∣∣N(v)∣∣N(u)∩N(v)∣其中,N(u)表示用户u产生过行为的物品集合
p ( u , i ) = ∑ v ∈ S ( u , K ) ∩ N ( i ) w u v r v i 其 中 , S ( u , K ) 是 用 户 u 最 相 似 的 K 个 用 户 集 合 , N ( i ) 为 对 i 有 过 行 为 的 用 户 集 合 , r v i 为 用 户 v 对 物 品 i 的 评 分 , 由 于 数 据 为 隐 性 数 据 而 不 是 评 分 数 据 , r v i 设 为 常 数 1 p(u,i)=\sum_{v\in S(u,K)\cap N(i)}w_{uv}r_{vi}\\ 其中,S(u,K)是用户u最相似的K个用户集合,N(i)为对i有过行为的用户集合,\\ r_{vi}为用户v对物品i的评分,由于数据为隐性数据而不是评分数据,r_{vi}设为常数1 p(u,i)=v∈S(u,K)∩N(i)∑wuvrvi其中,S(u,K)是用户u最相似的K个用户集合,N(i)为对i有过行为的用户集合,rvi为用户v对物品i的评分,由于数据为隐性数据而不是评分数据,rvi设为常数1
这样,就可以得到目标用户最感兴趣的TopN物品列表。
ItemCF的思想是根据用户行为数据,计算物品间的相似度,基于用户以往的喜好记录,推荐给用户相似的物品。
其算法流程分为两步:
w i j = ∣ N ( i ) ∩ N ( j ) ∣ ∣ N ( i ) ∣ ∣ N ( j ) ∣ 其 中 , N ( i ) 表 示 对 物 品 i 产 生 过 行 为 的 用 户 集 合 w_{ij}=\frac{|N(i)\cap N(j)|}{\sqrt{|N(i)||N(j)|}}\\其中,N(i)表示对物品i产生过行为的用户集合 wij=∣N(i)∣∣N(j)∣∣N(i)∩N(j)∣其中,N(i)表示对物品i产生过行为的用户集合
p u j = ∑ i ∈ N ( u ) ∩ S ( j , K ) w i j r u i p_{uj}=\sum_{i \in N(u)\cap S(j,K)}w_{ij}r_{ui} puj=i∈N(u)∩S(j,K)∑wijrui
这样,就可以得到目标用户最感兴趣的TopN物品列表。
上述介绍的算法是比较简单和原始的版本,使用的数据也只有用户的行为数据。
实际场景中,用户的画像信息、物品的属性、时间空间信息都会加入考虑,算法也会相应地改进以适应实际需求。
以上述介绍的用户相似度计算方式为例,在实际场景中,我们认为热门物品对相似度的贡献比冷门物品小,也就是两个人对冷门物品都产生过行为更能说明兴趣相似,因此用户相似度可以如下对热门物品做惩罚:
w u v = ∑ i ∈ N ( u ) ∩ N ( v ) l o g 1 1 + ∣ N ( i ) ∣ ∣ N ( u ) ∣ ∣ N ( v ) ∣ 其 中 , N ( u ) 表 示 用 户 u 产 生 过 行 为 的 物 品 集 合 , N ( i ) 表 示 对 物 品 i 产 生 过 行 为 的 用 户 集 合 w_{uv}=\frac{\sum_{i\in N(u)\cap N(v)} log\frac{1}{1+|N(i)|}}{\sqrt{|N(u)||N(v)|}}\\其中,N(u)表示用户u产生过行为的物品集合,N(i)表示对物品i产生过行为的用户集合 wuv=∣N(u)∣∣N(v)∣∑i∈N(u)∩N(v)log1+∣N(i)∣1其中,N(u)表示用户u产生过行为的物品集合,N(i)表示对物品i产生过行为的用户集合
类似地,在物品相似度中认为活跃用户的贡献小于非活跃用户,因此物品相似度可以如下对活跃用户做惩罚:
w i j = ∑ u ∈ N ( i ) ∩ N ( j ) l o g 1 1 + ∣ N ( u ) ∣ ∣ N ( i ) ∣ ∣ N ( j ) ∣ 其 中 , N ( u ) 表 示 用 户 u 产 生 过 行 为 的 物 品 集 合 , N ( i ) 表 示 对 物 品 i 产 生 过 行 为 的 用 户 集 合 w_{ij}=\frac{\sum_{u \in N(i)\cap N(j)}log \frac{1}{1+|N(u)|}}{\sqrt{|N(i)||N(j)|}}\\其中,N(u)表示用户u产生过行为的物品集合,N(i)表示对物品i产生过行为的用户集合 wij=∣N(i)∣∣N(j)∣∑u∈N(i)∩N(j)log1+∣N(u)∣1其中,N(u)表示用户u产生过行为的物品集合,N(i)表示对物品i产生过行为的用户集合
从上述UserCF与ItemCF的原理看,UserCF的推荐结果反映了与目标用户兴趣相似的小群体的热点,ItemCF的推荐结果是维护目标用户的历史兴趣,从不同角度对比如下:
UserCF常在新闻网站中使用,因为新闻数量很多,时效性很强,且从冷启动角度看,新的新闻出现后可快速用于推荐;
ItemCF则在电商、视频网站中使用,在这些网站中物品不容易过时,用户的兴趣也更持久。
LFM(Latent Factor Model),隐语义模型是推荐系统中很热门的研究话题。
隐语义模型最开始是在NLP领域中使用,用于找到文本的隐含语义,相关的主题模型有LSA、pLSA、LDA等,在这篇回答中解释得很清楚,建议看一下:既然 LDA 是一种比 PLSA 更高级的模型,为啥百度还在用 PLSA?
在NLP的主题模型中,通过在单词与文档之间引入 【主题】 这一隐含变量,来挖掘文本的语义,比如在上面回答中举到的例子:
文本1:“马云、马化腾和李彦宏”
文本2:“阿里巴巴、腾讯和百度掌门人”
如果通过单词来计算两个文本的距离,可能会得出两个文本完全不相关的结论。
但若把两个文本的 【主题】 抽离出来,会得到“企业家”、“互联网”、“BAT”等等这些主题,这样就发现两句话主题上是完全相同的,由此可知这两句话具有很高的相似性。
将LFM应用到推荐系统中,则是在用户和物品之间引入【类别】这一隐含变量——对于某个用户,首先得到他的兴趣分类,再从属于该分类的物品中挑选他可能喜欢的物品。
假设用户的兴趣分类(或物品的分类)有 F F F 种,用如下公式表示用户对物品的感兴趣程度——
P r e f e r e n c e ( u , i ) = r u i = p u q i = ∑ k = 1 F p u , k q k , i Preference(u,i)=r_{ui}=p_uq_i=\sum_{k=1}^{F}p_{u,k}q_{k,i} Preference(u,i)=rui=puqi=k=1∑Fpu,kqk,i
其中 r u i r_{ui} rui 表示用户是否对物品 i i i 产生行为, p u p_u pu 是用户-分类矩阵 P P P 的第 u u u 行,表示用户 u u u 与各个兴趣分类的关系, q i q_i qi 是分类-物品矩阵 Q Q Q 的第 i i i 列,表示物品 i i i 与各个兴趣分类的关系。
因此,只要求解出两个矩阵 P P P 和 Q Q Q,根据感兴趣程度的排序就可以推荐TopN列表给目标用户。
求解过程如下:
C = ∑ ( r u i − r ^ u i ) 2 + λ ∣ ∣ p u ∣ ∣ 2 + λ ∣ ∣ q i ∣ ∣ 2 = ∑ ( r u i − ∑ k = 1 F p u , k q k , i ) 2 + λ ∣ ∣ p u ∣ ∣ 2 + λ ∣ ∣ q i ∣ ∣ 2 C=\sum(r_{ui}-\hat r_{ui})^2+\lambda||p_u||^2+\lambda||q_i||^2=\sum(r_{ui}-\sum_{k=1}^{F}p_{u,k}q_{k,i})^2+\lambda||p_u||^2+\lambda||q_i||^2 C=∑(rui−r^ui)2+λ∣∣pu∣∣2+λ∣∣qi∣∣2=∑(rui−k=1∑Fpu,kqk,i)2+λ∣∣pu∣∣2+λ∣∣qi∣∣2
∂ C ∂ p u , k = − 2 q k , i + 2 λ p u , k ∂ C ∂ q k , i = − 2 p u , k + 2 λ q k , i \frac{\partial C}{\partial p_{u,k}}=-2q_{k,i}+2\lambda p_{u,k}\\ \frac{\partial C}{\partial q_{k,i}}=-2p_{u,k}+2\lambda q_{k,i} ∂pu,k∂C=−2qk,i+2λpu,k∂qk,i∂C=−2pu,k+2λqk,i
p u , k = p u , k + α ( q k , i − λ p u , k ) q k , i = q k , i + α ( p u , k − λ q k , i ) p_{u,k}=p_{u,k}+\alpha(q_{k,i}-\lambda p_{u,k})\\ q_{k,i}=q_{k,i}+\alpha(p_{u,k}-\lambda q_{k,i}) pu,k=pu,k+α(qk,i−λpu,k)qk,i=qk,i+α(pu,k−λqk,i)
用户行为可以用二分图表示,如下图所示,很多图的算法也可以应用到推荐系统上,此处介绍基于随机游走的PersonalRank算法。
PersonalRank算法跟用于网页排序的PageRank算法原理基本相同,其思路是,假设给用户 u u u 做推荐,可以从对应图上的 v u v_u vu 节点出发进行随机游走,最终每个节点被访问的概率(Rank值)会收敛,排序即可得到用户的推荐列表。
随机游走的规则为:
初始状态下, v u v_u vu 节点的Rank值为1,其余节点为0,每次游走,节点上的Rank值也会传递到下一个节点
在每个节点上,有 α \alpha α 的概率继续随机游走,即以相等的概率游走到该节点指向的任意节点上
在每个节点上,剩余有 1 − α 1-\alpha 1−α 的概率回到 v u v_u vu 起点
因此用迭代公式表达上述随机游走的过程如下:
R a n k ( v ) = { α ∑ v ′ ∈ i n ( v ) R a n k ( v ′ ) ∣ o u t ( v ′ ) ∣ ( v ≠ v u ) ( 1 − α ) + α ∑ v ′ ∈ i n ( v ) R a n k ( v ′ ) ∣ o u t ( v ′ ) ∣ ( v = v u ) Rank(v)=\left\{ \begin{aligned} \alpha & \sum_{v' \in in(v)} \frac{Rank(v')}{|out(v')|}&(v \ne v_u) \\ ( & 1-\alpha) + \alpha \sum_{v' \in in(v)} \frac{Rank(v')}{|out(v')|} &(v=v_u) \end{aligned} \right. Rank(v)=⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧α(v′∈in(v)∑∣out(v′)∣Rank(v′)1−α)+αv′∈in(v)∑∣out(v′)∣Rank(v′)(v=vu)(v=vu)
基于图的推荐算法(PersonalRank),这篇博客中有详细的代码实现和注释,可以参考一下。
上述算法需要在全图进行迭代,时间复杂度很高,可以通过转化为矩阵运算求解,此处不再说明。