(SVD)
1. 隐语义模型与矩阵分解
协同过滤算法的特点就是完全没有利用到物品本身或者是用户自身的属性, 仅仅利用了用户与物品的交互信息就可以实现推荐,是一个可解释性很强, 非常直观的模型, 但是也存在一些问题, 第一个就是处理稀疏矩阵的能力比较弱, 所以为了使得协同过滤更好处理稀疏矩阵问题, 增强泛化能力, 从协同过滤中衍生出矩阵分解模型(Matrix Factorization,MF)或者叫隐语义模型, 两者差不多说的一个意思, 就是在协同过滤共现矩阵的基础上, 使用更稠密的隐向量表示用户和物品, 挖掘用户和物品的隐含兴趣和隐含特征, 在一定程度上弥补协同过滤模型处理稀疏矩阵能力不足的问题。
2. 隐语义模型
隐语义模型最早在文本领域被提出,用于找到文本的隐含语义。在2006年, 被用于推荐中, 它的核心思想是通过隐含特征(latent factor)联系用户兴趣和物品(item), 基于用户的行为找出潜在的主题和分类, 然后对item进行自动聚类,划分到不同类别/主题(用户的兴趣)。
这么说可能有点抽象,所以下面拿项亮老师《推荐系统实践》里面的那个例子看一下:
如果我们知道了用户A和用户B两个用户在豆瓣的读书列表, 从他们的阅读列表可以看出,用户A的兴趣涉及侦探小说、科普图书以及一些计算机技术书, 而用户B的兴趣比较集中在数学和机器学习方面。 那么如何给A和B推荐图书呢?
先说说协同过滤算法, 这样好对比不同:
- 对于UserCF,首先需要找到和他们看了同样书的其他用户(兴趣相似的用户),然后给他们推荐那些用户喜欢的其他书。
- 对于ItemCF,需要给他们推荐和他们已经看的书相似的书,比如作者B看了很多关于数据挖掘的书,可以给他推荐机器学习或者模式识别方面的书。
而如果是隐语义模型的话, 它会先通过一些角度把用户兴趣和这些书归一下类, 当来了用户之后, 首先得到他的兴趣分类, 然后从这个分类中挑选他可能喜欢的书籍。
这里就看到了隐语义模型和协同过滤的不同, 这里说的角度其实就是这个隐含特征, 比如书籍的话它的内容, 作者, 年份, 主题等都可以算隐含特征,如果这个例子还不是很清晰的话, 那么下面再举个更为具体的例子, 看看是如何通过隐含特征来划分开用户兴趣和物品的。但是在这之前, 相信通过上面这个例子, 我们已经隐隐约约感受到了协同过滤和隐语义模型的区别了, 下面放上王喆老师《深度学习推荐系统》的一个原理图作为对比, 区别简直一目了然:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/6d67f48f17b72862b8defcb769d14219.png#pic_center)
我们下面拿一个音乐评分的例子来具体看一下隐特征矩阵的含义。
假设每个用户都有自己的听歌偏好, 比如A喜欢带有小清新的, 吉他伴奏的, 王菲的歌曲,如果一首歌正好是王菲唱的, 并且是吉他伴奏的小清新, 那么就可以将这首歌推荐给这个用户。 也就是说是小清新, 吉他伴奏, 王菲这些元素连接起了用户和歌曲。 当然每个用户对不同的元素偏好不同, 每首歌包含的元素也不一样, 所以我们就希望找到下面的两个矩阵:
- 潜在因子—— 用户矩阵Q
这个矩阵表示不同用户对于不同元素的偏好程度, 1代表很喜欢, 0代表不喜欢, 比如下面这样:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/f5cbee42f00e2867fd361008d2a0662c.png#pic_center)
- 潜在因子——音乐矩阵P
表示每种音乐含有各种元素的成分, 比如下表中, 音乐A是一个偏小清新的音乐, 含有小清新的Latent Factor的成分是0.9, 重口味的成分是0.1, 优雅成分0.2…
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/acbebf8cba61cce80200d672026a7934.png#pic_center)
利用上面的这两个矩阵, 我们就能得出张三对音乐A的喜欢程度:
张三对小清新的偏好 * 音乐A含有小清新的成分 + 张三对重口味的偏好 * 音乐A含有重口味的成分 + 张三对优雅的偏好 * 音乐A含有优雅的成分…,
下面是对应的两个隐向量:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/5f7dcd50beacd2eed9d3596ab3e10faa.png#pic_center)
根据隐向量其实就可以得到张三对音乐A的打分,即:
0.6
∗
0.9
+
0.8
∗
0.1
+
0.1
∗
0.2
+
0.1
∗
0.4
+
0.7
∗
0
=
0.69
0.6 * 0.9 + 0.8 * 0.1 + 0.1 * 0.2 + 0.1 * 0.4 + 0.7 * 0 = 0.69
0.6∗0.9+0.8∗0.1+0.1∗0.2+0.1∗0.4+0.7∗0=0.69
按照这个计算方式, 每个用户对每首歌其实都可以得到这样的分数, 最后就得到了我们的评分矩阵:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/e7ffbcd541c2075447e1576e10ed61a3.png#pic_center)
这里的红色表示用户没有打分,我们通过隐向量计算得到的。
上面例子中的小清晰, 重口味, 优雅这些就可以看做是隐含特征, 而通过这个隐含特征就可以把用户的兴趣和音乐的进行一个分类, 其实就是找到了每个用户每个音乐的一个隐向量表达形式(embedding的原理其实也是这样, 那里是找到每个词的隐向量表达), 这个隐向量就可以反映出用户的兴趣和物品的风格,并能将相似的物品推荐给相似的用户等。 有没有感觉到是把协同过滤算法进行了一种延伸, 把用户的相似性和物品的相似性通过了一个叫做隐向量的方式进行表达
但是, 真实的情况下我们其实是没有上面那两个矩阵的, 音乐那么多, 用户那么多, 我们没有办法去找一些隐特征去表示出这些东西, 另外一个问题就是即使能表示也不一定准, 对于每个用户或者每个物品的风格,我们每个人都有不同的看法。 所以事实上, 我们有的只有用户的评分矩阵, 也就是最后的结果, 并且一般这种矩阵长这样:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/372250a83a4317c9d0ec9a37e6044749.png#pic_center)
这种矩阵非常的稀疏,如果直接基于用户相似性或者物品相似性去填充这个矩阵是不太容易的, 并且很容易出现长尾问题, 所以矩阵分解就可以比较容易的解决这个问题。
矩阵分解模型其实就是在想办法基于这个评分矩阵去找到上面例子中的那两个矩阵, 也就是用户兴趣和物品的隐向量表达, 然后就把这个评分矩阵分解成Q和P两个矩阵乘积的形式, 这时候就可以基于这两个矩阵去预测某个用户对某个物品的评分了。 然后基于这个评分去进行推荐。这就是矩阵分解算法的原理。
矩阵分解算法的原理
在矩阵分解的算法框架下, 我们就可以通过分解协同过滤的共现矩阵来得到用户和物品的隐向量, 就是上面的用户矩阵Q和物品矩阵P, 这也是“矩阵分解”名字的由来。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/150df791ecb3bf36f9770e65665df200.png#pic_center)
矩阵分解算法将 m × n m\times n m×n维的共享矩阵 R R R分解成 m × k m \times k m×k维的用户矩阵 U U U和 k × n k \times n k×n维的物品矩阵 V V V相乘的形式。 其中 m m m是用户数量, n n n是物品数量, k k k是隐向量维度, 也就是隐含特征个数, 只不过这里的隐含特征变得不可解释了, 即我们不知道具体含义了, 要模型自己去学。 k k k的大小决定了隐向量表达能力的强弱, k k k越大, 表达信息就越强, 理解起来就是把用户的兴趣和物品的分类划分的越具体。
那么如果有了用户矩阵和物品矩阵的话, 我们就知道了如果想计算用户
u
u
u对物品
i
i
i的评分, 只需要
Preference
(
u
,
i
)
=
r
u
i
=
p
u
T
q
i
=
∑
f
=
1
F
p
u
,
k
q
k
,
i
\operatorname{Preference}(u, i)=r_{u i}=p_{u}^{T} q_{i}=\sum_{f=1}^{F} p_{u, k} q_{k,i}
Preference(u,i)=rui=puTqi=f=1∑Fpu,kqk,i
这里的
p
u
p_u
pu就是用户
u
u
u的隐向量, 就类似与上面的张三向量, 注意这是列向量,
q
i
q_i
qi是物品
i
i
i的隐向量, 就类似于上面的音乐A向量, 这个也是列向量, 所以才用了
p
u
T
q
i
p_{u}^{T} q_{i}
puTqi得到了一个数, 也就是用户的最终评分, 计算过程其实和上面例子中一样。 这里的
p
u
,
k
p_{u,k}
pu,k和
q
i
,
k
q_{i,k}
qi,k是模型的参数, 也正是我们想办法要计算的,
p
u
,
k
p_{u,k}
pu,k度量的是用户
u
u
u的兴趣和第
k
k
k个隐类的关系, 而
q
i
,
k
q_{i,k}
qi,k度量了第
k
k
k个隐类和物品
i
i
i之间的关系。
矩阵分解
通过分解协同过滤的共现矩阵来得到用户和物品的隐向量
这里的
p
u
p_u
pu就是用户
u
u
u的隐向量, 就类似与上面的张三向量, 注意这是列向量,
q
i
q_i
qi是物品
i
i
i的隐向量, 就类似于上面的音乐A向量, 这个也是列向量, 所以才用了
p
u
T
q
i
p_{u}^{T} q_{i}
puTqi得到了一个数, 也就是用户的最终评分, 计算过程其实和上面例子中一样。 这里的
p
u
,
k
p_{u,k}
pu,k和
q
i
,
k
q_{i,k}
qi,k是模型的参数, 也正是我们想办法要计算的,
p
u
,
k
p_{u,k}
pu,k度量的是用户
u
u
u的兴趣和第
k
k
k个隐类的关系, 而
q
i
,
k
q_{i,k}
qi,k度量了第
k
k
k个隐类和物品
i
i
i之间的关系。
Basic SVD
2006年的Netflix Prize之后, Simon Funk公布了一个矩阵分解算法叫做Funk-SVD, 后来被Netflix Prize的冠军Koren称为Latent Factor Model(LFM)。 Funk-SVD的思想很简单: 把求解上面两个矩阵的参数问题转换成一个最优化问题, 可以通过训练集里面的观察值利用最小化来学习用户矩阵和物品矩阵。
我们上面已经知道了, 如果有了用户矩阵和物品矩阵的话, 我们就知道了如果想计算用户
u
u
u对物品
i
i
i的评分, 只需要
Preference
(
u
,
i
)
=
r
u
i
=
p
u
T
q
i
=
∑
k
=
1
K
p
u
,
k
q
k
,
i
\operatorname{Preference}(u, i)=r_{u i}=p_{u}^{T} q_{i}=\sum_{k=1}^{K} p_{u, k} q_{k,i}
Preference(u,i)=rui=puTqi=k=1∑Kpu,kqk,i
而现在, 我们有真实的
r
u
,
i
r_{u,i}
ru,i, 但是没有
p
u
T
q
i
p_{u}^{T} q_{i}
puTqi, 那么我们可以初始化一个啊, 随机初始化一个用户矩阵
U
U
U和一个物品矩阵
V
V
V, 然后不就有
p
u
T
q
i
p_{u}^{T} q_{i}
puTqi了? 当然你说, 随机初始化的肯定不准啊, 但是, 有了
p
u
T
q
i
p_{u}^{T} q_{i}
puTqi之后, 我们就可以计算一个猜测的
r
^
u
i
\hat{r}_{u i}
r^ui, 即
r
^
u
i
=
p
u
T
q
i
\hat{r}_{u i}=p_{u}^{T} q_{i}
r^ui=puTqi
这时候, 肯定是不准, 那么这个猜测的和真实值之间就会有一个误差:
e
u
i
=
r
u
i
−
r
^
u
i
e_{u i}=r_{u i}-\hat{r}_{u i}
eui=rui−r^ui
有了误差, 我们就可以计算出总的误差平方和:
SSE
=
∑
u
,
i
e
u
i
2
=
∑
u
,
i
(
r
u
i
−
∑
k
=
1
K
p
u
,
k
q
k
,
i
)
2
\operatorname{SSE}=\sum_{u, i} e_{u i}^{2}=\sum_{u, i}\left(r_{u i}-\sum_{k=1}^{K} p_{u,k} q_{k, i}\right)^{2}
SSE=u,i∑eui2=u,i∑(rui−k=1∑Kpu,kqk,i)2
有了损失, 我们就可以想办法进行训练, 把SSE降到最小, 那么我们的两个矩阵参数就可以算出来。所以就把这个问题转成了最优化的的问题, 而我们的目标函数就是:
min q ∗ , p ∗ ∑ ( u , i ) ∈ K ( r u i − p u T q i ) 2 \min _{\boldsymbol{q}^{*}, \boldsymbol{p}^{*}} \sum_{(u, i) \in K}\left(\boldsymbol{r}_{\mathrm{ui}}-p_{u}^{T} q_{i}\right)^{2} q∗,p∗min(u,i)∈K∑(rui−puTqi)2
这里的 K K K表示所有用户评分样本的集合。
有了目标函数, 那么我们就可以使用梯度下降算法来降低损失。 那么我们需要对目标函数求偏导, 得到梯度。 我们的目标函数如果是上面的SSE, 我们下面来推导一下最后的导数:
SSE
=
∑
u
,
i
e
u
i
2
=
∑
u
,
i
(
r
u
i
−
∑
k
=
1
K
p
u
,
k
q
k
,
i
)
2
\operatorname{SSE}=\sum_{u, i} e_{u i}^{2}=\sum_{u, i}\left(r_{u i}-\sum_{k=1}^{K} p_{u,k} q_{k,i}\right)^{2}
SSE=u,i∑eui2=u,i∑(rui−k=1∑Kpu,kqk,i)2
首先我们求SSE在
p
u
,
k
p_{u,k}
pu,k(也就是Q矩阵的第
u
u
u行
k
k
k列)的梯度:
∂
∂
p
u
,
k
S
S
E
=
∂
∂
p
u
,
k
(
e
u
i
2
)
=
2
e
u
i
∂
∂
p
u
,
k
e
u
i
=
2
e
u
i
∂
∂
p
u
,
k
(
r
u
i
−
∑
k
=
1
K
p
u
,
k
q
k
,
i
)
=
−
2
e
u
i
q
k
,
i
\frac{\partial}{\partial p_{u,k}} S S E=\frac{\partial}{\partial p_{u,k}}\left(e_{u i}^{2}\right) =2e_{u i} \frac{\partial}{\partial p_{u,k}} e_{u i}=2e_{u i} \frac{\partial}{\partial p_{u,k}}\left(r_{u i}-\sum_{k=1}^{K} p_{u,k} q_{k,i}\right)=-2e_{u i} q_{k,i}
∂pu,k∂SSE=∂pu,k∂(eui2)=2eui∂pu,k∂eui=2eui∂pu,k∂(rui−k=1∑Kpu,kqk,i)=−2euiqk,i
然后求SSE在
q
k
,
i
q_{k,i}
qk,i处(也就是V矩阵的第
k
k
k行
i
i
i列)的梯度:
∂
∂
q
k
,
i
S
S
E
=
∂
∂
p
k
,
i
(
e
u
i
2
)
=
2
e
u
i
∂
∂
p
k
,
i
e
u
i
=
2
e
u
i
∂
∂
p
k
,
i
(
r
u
i
−
∑
k
=
1
K
p
u
,
k
q
k
,
i
)
=
−
2
e
u
i
p
u
,
k
\frac{\partial}{\partial q_{k,i}} S S E=\frac{\partial}{\partial p_{k,i}}\left(e_{u i}^{2}\right) =2e_{u i} \frac{\partial}{\partial p_{k,i}} e_{u i}=2e_{u i} \frac{\partial}{\partial p_{k,i}}\left(r_{u i}-\sum_{k=1}^{K} p_{u,k} q_{k,i}\right)=-2e_{u i} p_{u,k}
∂qk,i∂SSE=∂pk,i∂(eui2)=2eui∂pk,i∂eui=2eui∂pk,i∂(rui−k=1∑Kpu,kqk,i)=−2euipu,k
为了让公式更为简单, 把前面的2给他越掉, 即可以令SSE等于:
SSE
=
1
2
∑
u
,
i
e
u
i
2
=
1
2
∑
u
,
i
(
r
u
i
−
∑
k
=
1
K
p
u
k
q
k
i
)
2
\operatorname{SSE}=\frac{1}{2} \sum_{u, i} e_{u i}^{2}=\frac{1}{2} \sum_{u, i}\left(r_{u i}-\sum_{k=1}^{K} p_{u k} q_{k i}\right)^{2}
SSE=21u,i∑eui2=21u,i∑(rui−k=1∑Kpukqki)2
这时候, 梯度就没有前面的系数了, 有了梯度, 接下来我们就可以用梯度下降算法更新梯度了:
p
u
,
k
=
p
u
,
k
−
η
(
−
e
u
i
q
k
,
i
)
=
p
u
,
k
+
η
e
u
i
q
k
,
i
q
k
,
i
=
q
k
,
i
−
η
(
−
e
u
i
p
u
,
k
)
=
q
k
,
i
+
η
e
u
i
p
u
,
k
p_{u, k}=p_{u,k}-\eta (-e_{ui}q_{k,i})=p_{u,k}+\eta e_{ui}q_{k,i} \\ q_{k, i}=q_{k, i}-\eta (-e_{ui}p_{u,k})=q_{k, i}+\eta e_{ui}p_{u,k}
pu,k=pu,k−η(−euiqk,i)=pu,k+ηeuiqk,iqk,i=qk,i−η(−euipu,k)=qk,i+ηeuipu,k
这里的 η \eta η是学习率, 控制步长用的, 但上面这个有个问题就是当参数很多的时候, 就是两个矩阵很大的时候, 往往容易陷入过拟合的困境, 这时候, 就需要在目标函数上面加上正则化的损失, 就变成了RSVD, 关于RSVD的详细内容, 可以参考下面给出的链接, 由于篇幅原因, 这里不再过多的赘述。
但在实际中, 单纯的
r
^
u
i
=
p
u
T
q
i
\hat{r}_{u i}=p_{u}^{T} q_{i}
r^ui=puTqi也是不够的, 还要考虑其他的一些因素, 比如一个评分系统, 有些固有的属性和用户物品无关, 而用户也有些属性和物品无关, 物品也有些属性和用户无关。 因此, Netfix Prize中提出了另一种LFM, 在原来的基础上加了偏置项, 来消除用户和物品打分的偏差, 即预测公式如下:
r
^
u
i
=
μ
+
b
u
+
b
i
+
p
u
T
⋅
q
i
\hat{r}_{u i}=\mu+b_{u}+b_{i}+p_{u}^{T} \cdot q_{i}
r^ui=μ+bu+bi+puT⋅qi
这个预测公式加入了3项偏置
μ
,
b
u
,
b
i
\mu,b_u,b_i
μ,bu,bi, 作用如下:
- μ \mu μ: 训练集中所有记录的评分的全局平均数。 在不同网站中, 因为网站定位和销售物品不同, 网站的整体评分分布也会显示差异。 比如有的网站中用户就喜欢打高分, 有的网站中用户就喜欢打低分。 而全局平均数可以表示网站本身对用户评分的影响。
- b u b_u bu: 用户偏差系数, 可以使用用户 u u u给出的所有评分的均值, 也可以当做训练参数。 这一项表示了用户的评分习惯中和物品没有关系的那种因素。 比如有些用户比较苛刻, 对什么东西要求很高, 那么他评分就会偏低, 而有些用户比较宽容, 对什么东西都觉得不错, 那么评分就偏高
- b i b_i bi: 物品偏差系数, 可以使用物品 i i i收到的所有评分的均值, 也可以当做训练参数。 这一项表示了物品接受的评分中和用户没有关系的因素。 比如有些物品本身质量就很高, 因此获得的评分相对比较高, 有的物品本身质量很差, 因此获得的评分相对较低。
加了用户和物品的打分偏差之后, 矩阵分解得到的隐向量更能反映不同用户对不同物品的“真实”态度差异, 也就更容易捕捉评价数据中有价值的信息, 从而避免推荐结果有偏。 注意此时的
S
S
E
SSE
SSE会发生变化:
SSE
=
1
2
∑
u
,
i
e
u
i
2
+
1
2
λ
∑
u
∣
p
u
∣
2
+
1
2
λ
∑
i
∣
q
i
∣
2
+
1
2
λ
∑
u
b
u
2
+
1
2
λ
∑
u
b
i
2
=
1
2
∑
u
,
i
(
r
u
i
−
μ
−
b
u
−
b
i
−
∑
k
=
1
K
p
u
k
q
k
i
)
2
+
1
2
λ
∑
u
∣
p
u
∣
2
+
1
2
λ
∑
i
∣
q
i
∣
2
+
1
2
λ
∑
u
b
u
2
+
1
2
λ
∑
u
b
i
2
\begin{array}{l} \operatorname{SSE}=\frac{1}{2} \sum_{u, i} e_{u i}^{2}+\frac{1}{2} \lambda \sum_{u}\left|\boldsymbol{p}_{u}\right|^{2}+\frac{1}{2} \lambda \sum_{i}\left|\boldsymbol{q}_{i}\right|^{2}+\frac{1}{2} \lambda \sum_{u} \boldsymbol{b}_{u}^{2}+\frac{1}{2} \lambda \sum_{u} \boldsymbol{b}_{i}^{2} \\ =\frac{1}{2} \sum_{u, i}\left(\boldsymbol{r}_{u i}-\boldsymbol{\mu}-\boldsymbol{b}_{u}-\boldsymbol{b}_{i}-\sum_{k=1}^{K} \boldsymbol{p}_{u k} \boldsymbol{q}_{k i}\right)^{2}+\frac{1}{2} \lambda \sum_{u}\left|\boldsymbol{p}_{u}\right|^{2}+\frac{1}{2} \lambda \sum_{i}\left|\boldsymbol{q}_{i}\right|^{2}+\frac{\mathbf{1}}{2} \lambda \sum_{u} \boldsymbol{b}_{u}^{2}+\frac{1}{2} \lambda \sum_{u} \boldsymbol{b}_{i}^{2} \end{array}
SSE=21∑u,ieui2+21λ∑u∣pu∣2+21λ∑i∣qi∣2+21λ∑ubu2+21λ∑ubi2=21∑u,i(rui−μ−bu−bi−∑k=1Kpukqki)2+21λ∑u∣pu∣2+21λ∑i∣qi∣2+21λ∑ubu2+21λ∑ubi2
此时如果把
b
u
b_u
bu和
b
i
b_i
bi当做训练参数的话, 那么它俩的梯度是:
∂
∂
b
u
S
S
E
=
−
e
u
i
+
λ
b
u
∂
∂
b
i
S
S
E
=
−
e
u
i
+
λ
b
i
\frac{\partial}{\partial b_{u}} S S E=-e_{u i}+\lambda b_{u} \\ \frac{\partial}{\partial b_{i}} S S E=-e_{u i}+\lambda b_{i}
∂bu∂SSE=−eui+λbu∂bi∂SSE=−eui+λbi
更新公式为:
b
u
=
b
u
+
η
(
e
u
i
−
λ
b
u
)
b
i
=
b
i
+
η
(
e
u
i
−
λ
b
i
)
\begin{aligned} \boldsymbol{b}_{u}&=\boldsymbol{b}_{\boldsymbol{u}}+\boldsymbol{\eta}\left(\boldsymbol{e}_{u i}-\lambda \boldsymbol{b}_{\boldsymbol{u}}\right) \\ \boldsymbol{b}_{\boldsymbol{i}} &=\boldsymbol{b}_{\boldsymbol{i}}+\boldsymbol{\eta}\left(\boldsymbol{e}_{\boldsymbol{u} i}-\lambda \boldsymbol{b}_{\boldsymbol{i}}\right) \end{aligned}
bubi=bu+η(eui−λbu)=bi+η(eui−λbi)
而对于
p
u
,
k
p_{u,k}
pu,k和
p
k
,
i
p_{k,i}
pk,i, 导数没有变化, 更新公式也没有变化。
FM
1. FM模型的引入
1.1 逻辑回归模型及其缺点
FM模型其实是一种思路,具体的应用稍少。一般来说做推荐CTR预估时最简单的思路就是将特征做线性组合(逻辑回归LR),传入sigmoid中得到一个概率值,本质上这就是一个线性模型,因为sigmoid是单调增函数不会改变里面的线性模型的CTR预测顺序,因此逻辑回归模型效果会比较差。也就是LR的缺点有:
- 是一个线性模型
- 每个特征对最终输出结果独立,需要手动特征交叉( x i ∗ x j x_i*x_j xi∗xj),比较麻烦
1.2 二阶交叉项的考虑及改进
由于LR模型的上述缺陷(主要是手动做特征交叉比较麻烦),干脆就考虑所有的二阶交叉项,也就是将目标函数由原来的
y
=
w
0
+
∑
i
=
1
n
w
i
x
i
y = w_0+\sum_{i=1}^nw_ix_i
y=w0+i=1∑nwixi
变为
y
=
w
0
+
∑
i
=
1
n
w
i
x
i
+
∑
i
=
1
n
−
1
∑
i
+
1
n
w
i
j
x
i
x
j
y = w_0+\sum_{i=1}^nw_ix_i+\sum_{i=1}^{n-1}\sum_{i+1}^nw_{ij}x_ix_j
y=w0+i=1∑nwixi+i=1∑n−1i+1∑nwijxixj
但这个式子有一个问题,只有当
x
i
x_i
xi与
x
j
x_j
xj均不为0时这个二阶交叉项才会生效,后面这个特征交叉项本质是和多项式核SVM等价的,为了解决这个问题,我们的FM登场了!
FM模型使用了如下的优化函数:
y
=
w
0
+
∑
i
=
1
n
w
i
x
i
+
∑
i
=
1
n
∑
i
+
1
n
<
v
i
,
v
j
>
x
i
x
j
y = w_0+\sum_{i=1}^nw_ix_i+\sum_{i=1}^{n}\sum_{i+1}^n\lt v_i,v_j\gt x_ix_j
y=w0+i=1∑nwixi+i=1∑ni+1∑n<vi,vj>xixj
事实上做的唯一改动就是把
w
i
j
w_{ij}
wij替换成了
<
v
i
,
v
j
>
\lt v_i,v_j\gt
<vi,vj>,大家应该就看出来了,这实际上就有深度学习的意味在里面了,实质上就是给每个
x
i
x_i
xi计算一个embedding,然后将两个向量之间的embedding做内积得到之前所谓的
w
i
j
w_{ij}
wij好处就是这个模型泛化能力强 ,即使两个特征之前从未在训练集中同时出现,我们也不至于像之前一样训练不出
w
i
j
w_{ij}
wij,事实上只需要
x
i
x_i
xi和其他的
x
k
x_k
xk同时出现过就可以计算出
x
i
x_i
xi的embedding!
2. FM公式的理解
从公式来看,模型前半部分就是普通的LR线性组合,后半部分的交叉项:特征组合。首先,单从模型表达能力上来看,FM是要强于LR的,至少它不会比LR弱,当交叉项参数 w i j w_{ij} wij全为0的时候,整个模型就退化为普通的LR模型。对于有 n n n个特征的模型,特征组合的参数数量共有 1 + 2 + 3 + ⋯ + n − 1 = n ( n − 1 ) 2 1+2+3+\cdots + n-1=\frac{n(n-1)}{2} 1+2+3+⋯+n−1=2n(n−1)个,并且任意两个参数之间是独立的。所以说特征数量比较多的时候,特征组合之后,维度自然而然就高了。
定理:任意一个实对称矩阵(正定矩阵) W W W都存在一个矩阵 V V V,使得 W = V . V T W=V.V^{T} W=V.VT成立。
类似地,所有二次项参数 ω i j \omega_{ij} ωij可以组成一个对称阵 W W W(为了方便说明FM的由来,对角元素可以设置为正实数),那么这个矩阵就可以分解为 W = V T V W=V^TV W=VTV, V V V 的第 j j j列( v j v_{j} vj)便是第 j j j维特征( x j x_{j} xj)的隐向量。
y ^ ( X ) = ω 0 + ∑ i = 1 n ω i x i + ∑ i = 1 n − 1 ∑ j = i + 1 n < v i , v j > x i x j \hat{y}(X) = \omega_{0}+\sum_{i=1}^{n}{\omega_{i}x_{i}}+\sum_{i=1}^{n-1}{\sum_{j=i+1}^{n} \color{red}{<v_{i},v_{j}>x_{i}x_{j}}} y^(X)=ω0+i=1∑nωixi+i=1∑n−1j=i+1∑n<vi,vj>xixj
需要估计的参数有 ω 0 ∈ R \omega_{0}∈ R ω0∈R, ω i ∈ R \omega_{i}∈ R ωi∈R, V ∈ R V∈ R V∈R, < ⋅ , ⋅ > < \cdot, \cdot> <⋅,⋅>是长度为 k k k的两个向量的点乘,公式如下:
< v i , v j > = ∑ f = 1 k v i , f ⋅ v j , f <v_{i},v_{j}> = \sum_{f=1}^{k}{v_{i,f}\cdot v_{j,f}} <vi,vj>=f=1∑kvi,f⋅vj,f
上面的公式中:
- ω 0 \omega_{0} ω0为全局偏置;
- ω i \omega_{i} ωi是模型第 i i i个变量的权重;
- ω i j = < v i , v j > \omega_{ij} = < v_{i}, v_{j}> ωij=<vi,vj>特征 i i i和 j j j的交叉权重;
- $v_{i} 是 第 是第 是第i$维特征的隐向量;
- < ⋅ , ⋅ > <\cdot, \cdot> <⋅,⋅>代表向量点积;
-
k
(
k
<
<
n
)
k(k<<n)
k(k<<n)为隐向量的长度,包含
k
k
k 个描述特征的因子。
这里下载链接是这个
http://www.grouplens.org/system/files/ml-100k.zip 这里下载是对的