前言
上一篇文章我们介绍了协同过滤算法,协同过滤算法虽然广泛应用在推荐一下中,但是还存在很多不足,比如:
上述两个问题,在矩阵分解中可以得到解决。在隐语义模型基础中常用的分解算法有SVD和SVD++。
矩阵分解
矩阵分解,就是把原来的大矩阵,近似分解成两个小矩阵的乘积,在实际推荐计算时不再使用大矩阵协同过滤算法 java [推荐系统]6—SVD和SVD++,而是使用分解得到的两个小矩阵。
具体来说,假设用户物品评分矩阵为 R,形状为 mxn,即 m 个用户, n 个物品。我们选择一个很小的数 k,k 比 m 和 n 都小很多,然后通过算法生成两个矩阵 P 和 Q,这两个矩阵的要求如下:P 的形状是 mxk,Q 的形状是 nxk, P 和 Q 的转置相乘结果为 R。也就是说分解得到的矩阵P和Q可以还原成原始的矩阵R。
用公式来描述就是:
其中 R 表示真实的用户评分矩阵,一般有很多缺失值(缺失值表示用户没有对该物品评分),带尖帽的 R 表示使用分解矩阵预测的用户评分矩阵,它补全了所有的缺失值。
从另一个角度来看,矩阵分解就是把用户和物品都映射到一个 k 维空间中(这里映射后的结果用户用矩阵P表示,物品用矩阵Q表示),这个 k 维空间不是我们直接看得到的,也不一定具有非常好的可解释性,每一个维度也没有名字,所以常常叫做隐因子。用户向量代表了用户的兴趣,物品向量代表了物品的特点,且每一个维度相互对应,两个向量的内积表示用户对该物品的喜好程度。
SVD
SVD 全程奇异值分解,原本是是线性代数中的一个知识,在推荐算法中用到的 SVD 并非正统的奇异值分解。
前面已经知道通过矩阵分解协同过滤算法 java,可以得到用户矩阵和物品矩阵。针对每个用户和物品,假设分解后得到的用户 u 的向量为 p_u,物品 i 的向量为 q_i,那么用户 u 对物品 i 的评分为:
其中,K 表示隐因子个数。
问题关键来了,如何为每个用户和物品生成k维向量呢?这个问题可以转化成机器学习问题,要解决机器学习问题,就需要寻找损失函数以及优化算法。
这里单个用户对单个物品的真实评分与预测评分之间的差值记为 e{ui}。
将所有用户对物品的真实评分与预测评分之间的差值的平方之和作为损失函数,即
其中,R 表示所有的用户对所有物品的评分集合,K 表示隐因子个数。
我们要做的就是求出用户向量 p_u 和物品向量 q_i ,来保证损失函数结果最小。
求解损失函数优化算法常用的选择有两个,一个是梯度下降(GD),另一个是交替最小二乘(ALS) 。这里以梯度下降为例。
准备好用户物品的评分矩阵,每一条评分数据看做一条训练样本;给分解后的 P 矩阵和 Q 矩阵随机初始化元素值;用 P 和 Q 计算预测后的分数;计算预测的分数和实际的分数误差;沿着损失函数梯度下降的方向更新 P 和 Q 中的元素值;重复步骤 3 到 5,直到达到停止条件。
梯度下降算法的一个关键点在于计算损失函数对于每个参数的梯度。
增加偏置的SVD
在实际应用中,会存在以下情况:相比于其他用户,有些用户给分就是偏高或偏低。相比于其他物品,有些物品就是能得到偏高的评分。所以使用 pu*qi^T 来定义评分是有失偏颇的。我们可以认为 评分 = 兴趣 + 偏见。
其中,μ表示全局均值, bu表示用户偏见,bi表示物品偏见。
SVD++
实际生产中,用户评分数据很稀少,也就是说显式数据比隐式数据少很多,这些隐式数据能否加入模型呢?
SVD++ 就是在 SVD 模型中融入用户对物品的隐式行为。我们可以认为 评分=显式兴趣 + 隐式兴趣 + 偏见。那么隐式兴趣如何加入到模型中呢?
我们将将的预测算法改成如下方式:
这里wij不再是根据算法计算出的物品相似度矩阵,而是一个和P、Q一样的参数,它可以通过优化如下的损失函数进行优化:
不过,这个模型有一个缺点,就是w将是一个比较稠密的矩阵,存储它需要比较大的空间。此外,如果有n个物品,那么该模型的参数个数就是n2个,这个参数个数比较大协同过滤算法 java,容易造成结果 的过拟合。因此,Koren提出应该对w矩阵也进行分解,将参数个数降低到2∗n∗F个,模型如下:
这里xi、yi是两个F维的向量。由此可见,该模型用xiTyj代替了wij,从而大大降低了参数的数量和存储空间。 再进一步,我们可以将前面的SVD和上面的模型相加,从而得到如下模型:
Koren又提出,为了不增加太多参数造成过拟合,可以令x=q,从而得到终的SVD++模型:
总结
学习推荐系统就从SVD算法开始吧。
<pre>PS:喜欢小编的请关注我,觉得文章写得还可以的请帮忙评论、收藏、点赞、转发,你们的赞赏是对我最大的鼓励。
</pre>