推荐系统的数学模型-- 从矩阵分解到推荐系统(scala实现)
词汇
Matrix Factorization 矩阵分解
Recommendation System 推荐系统
User 用户 Feature 特征 Item 物品
简介
不论有没有觉察到,互联网的搜索模式在近几年已经发生了颠覆性的变化。如果说是十年前搜索模式叫百度模式,那今天的就叫做头条模式。两者的区别在于,百度模式提供一个入口,让用户按照自己的需求查询关注的内容(各种广告暂不考虑);头条是按照用户的搜索习惯及浏览历史,主动推送与之相似的内容,如此,用户可以投入更少的精力,更大概率的获得符合自己喜好的节目。
这篇文章不讨论两种模式孰优孰劣,或者谁更有发展前景,只是从纯技术的角度,分析实现推荐系统的数学模型。
业务场景
假设我们在豆瓣上获取了一组用户评分,我们整理了四位用户 的评分信息,整理如下:
第一滴血 | 风月俏佳人 | 小萝莉的猴神大叔 | 海王 | 愤怒的黄牛 | 我是山姆 | 我不是药神 | 唐人街探案 | 星际穿越 | 变态假面 | |
---|---|---|---|---|---|---|---|---|---|---|
李雷 | 9.0 | - | - | 8.5 | 7.0 | 2.0 | 6.5 | 8.0 | - | - |
韩梅梅 | - | 9.5 | 9.0 | 2.0 | - | 9.0 | 9.3 | - | 9.5 | - |
Jim Green | 9.5 | 2 | 8.0 | 9.0 | - | 7.0 | - | 8.0 | 6.0 | 6.0 |
Lucy | 3.0 | 10.0 | - | 4.0 | 8.5 | - | 9.5 | 4.0 | - | - |
这里面 - 表示用户对某部电影没有相应的评分记录,可以理解成用户并没有看过这部电影,这部电影具有潜在推荐价值。
面对这样一组数据,你最直接的反应是什么?
我们先对这些电影打一个粗略的标签:
特征 | 电影 |
---|---|
剧情类 | 唐人街探案、我不是药神、星际穿越、我不是药神 |
动作类 | 第一滴血、愤怒的黄牛、海王 |
情感类 | 风月俏佳人、我是山姆、小萝莉的猴神大叔、星际穿越 |
恶趣味类 | 变态假面 |
如果我们把李雷和Jim Green分成一组,韩梅梅和Lucy分成一组,会发现同一组的成员对电影的喜好更为一致。那么,我们可不可以这样操作,将李雷看过但是Jim Green没有看过的电影推荐给Jim Green,其他人也采取相同的推荐方法。
这正是推荐系统要实现的。就好比两个好朋友互相推荐或者相约去电影院一样。唯一不同的地方就是,这里的两个人可能完全不知道对方的存在,但是通过推荐系统,我们帮助他们建立了”品味相近的朋友关系“。
引入特征
接下来,我们在 用户user 和 物品item(在上面的例子中就是电影)引入特征 feature,并且将 user 对具体 item 的喜好转换成 user 对具有某一类特征的item具有倾向性,也就是说,如果两个 user 对相同的特征具有倾向性,那么他们也大概率会喜欢彼此关注的具有这类feature 的 item。feature可以是各种因素,比如两个 user 都喜欢同一个明星,或者喜欢某一种导演的风格。在我们的分析中,我们不会挖掘究竟 user 是被哪一种 feature 吸引。
此外,我们还假设每一次分析,feature的个数都要小于 user 的个数以及 item 的个数。理由如下:我们不会考虑每一个 user 都只关心一种 feature,而不会和别的 user 共同关注一个feature的情况。否则的话,推荐就毫无意义,因为每一个 user 都对其他 user 关注的 item 毫无兴趣。对于 item 而言,也是一样的道理。
矩阵分解
假设我们获得了 user-item 矩阵,R: |U|✖|D|, |U| 表示 user 的个数,|D| 表示 item 的个数。元素 r i j r_{ij} rij 表示第i个user对第j个item的评分,如果用户对某一个产品没有评分,设为0。
接下来,我们将矩阵 R 分解成 user-feature 和 feature-item 矩阵的乘积:
R ≈ P ✖ Q = R = R ^ R ≈ P ✖ Q = R = \widehat{R} R≈P✖Q=R=R
P :|U|✖|K|,|K| 表示 feature 的个数,元素 p i k p_{ik} pik 表示第第i个user对第k个feature的喜好程度;
Q:|K|✖|D|,|K| 表示 feature 的个数,元素 q j k q_{jk} qjk 表示第第j个item对第k个feature的符合程度。item-feature关联矩阵为 Q T Q^T QT,求出Q之后,一般还要做一次转置或者item-feature矩阵。
对于 R ~ \widetilde{R} R 中的每一个因子,有 r ^ i j = p i q j T = ∑ k = 1 K p i k q k j \widehat{r}_{ij} = p_{i}q_{j}^T = \sum_{k=1}^{K}{p_{ik}q_{kj}} r ij=piqjT=∑k=1Kpikqkj
我们希望R 和 R ^ \widehat{R} R 尽可能的接近,因为每一个元素的差异可能为正,可能为负,我们采用所有元素差值的平方和作为R 和 R ^ \widehat{R} R 差异的表征。
e i j 2 = ( r i j − r ^ i j ) 2 = ( r i j − ∑ k = 1 K p i k q k j ) 2 e_{ij}^2 = (r_{ij} - \widehat{r}_{ij})^2 = (r_{ij} - \sum_{k=1}^{K}{p_{ik}q_{kj}})^2 eij2=(rij−r ij)2=(rij−∑k=1Kpikqkj)2
接下来就要用到梯度下降法了,以 p i k p_{ik} pik, q k j q_{kj} qkj 为自变量,求梯度。一个多元函数的梯度表示这个函数值增长最快的方向,因此如果要求这个函数的最小值,只要每次都沿着梯度的反方向移动就行。
计算梯度如下:
∂ ∂ p i k e i j 2 = − 2 ( r i j − r ^ i j ) ( q k j ) = − 2 e i j q k j \frac{\partial}{\partial{p_{ik}}}e_{ij}^2 = -2(r_{ij} - \widehat{r}_{ij})(q_{kj}) = -2e_{ij}q_{kj} ∂pik∂