推荐系统的评分预测场景可看做是一个矩阵补全的游戏,矩阵补全是推荐系统的任务,矩阵分解(Matrix Factorization)是其达到目的的手段。因此,矩阵分解是为了更好的完成矩阵补全任务(欲其补全,先其分解之)。之所以可以利用矩阵分解来完成矩阵补全的操作,那是因为基于这样的假设:假设UI矩阵是低秩的,即在大千世界中,总会存在相似的人或物,即物以类聚,人以群分,然后我们可以利用两个小矩阵相乘来还原它。
矩阵分解方法在基于模型推荐算法中最先得到发展。后面很多的推荐算法也都是基于矩阵分解方法的。
矩阵分解的思想是:像对整数进行质因数分解一样,将矩阵分解成一些更有代表性的特征向量,进而方便研究。矩阵分解方法有很多,在线性代数中比较常见的就是特征分解和奇异值分解两种。在推荐系统中还有Funk-SVD,SVD++等方法。
特征分解
特征分解是对方阵而言的,我们只可以对可对角化矩阵进行特征值分解。如果一个方块矩阵 A 相似于对角矩阵,也就是说,如果存在一个可逆矩阵 P 使得\(P^{-1}AP\) 是对角矩阵,则它就被称为可对角化的。
N 维非零向量 v 是 N×N 的矩阵 A 的特征向量,当且仅当\(Av=\lambda v\)。
其中v为\(\lambda\)对应的特征向量,\(\lambda\)为特征值。
则矩阵A可以被分解为:
\[A=Q\sum Q^{-1} \]
任意的 N×N 实对称矩阵都有 N 个线性无关的特征向量。并且这些特征向量都可以正交单位化而得到一组正交且模为 1 的向量。故实对称矩阵 A 可被分解成:
\[A=Q\hat{A}Q^T \]
其中Q为正交矩阵,\(\hat{A}\)为实对角矩阵。
然而我们在推荐系统中常见的UI矩阵都不是方阵。所以特征分解的方法不适用。
奇异值分解 SVD
特征分解是将方阵A分解为特征向量矩阵,特征值对角矩阵和特征向量矩阵的逆(实对称矩阵则使用转置)的矩阵乘积。
而奇异值分解则是可以对M*N的矩阵也进行分解的方法。它将矩阵M分解为:
\[M=U\sum V^T \]
假设A是一个M * N的矩阵,那么得到的U是一个M * M的方阵(里面的向量是正交的,U里面的向量称为左奇异向量),Σ是一个M * N的实数对角矩阵(对角线以外的元素都是0,对角线上的元素称为奇异值),VT(V的转置)是一个N * N的矩阵,里面的向量也是正交的,V里面的向量称为右奇异向量)。
具体不展开了,利用奇异值分解,我们就可以达到使用更少的存储空间,表示我们的UI矩阵。
但是,实际场景中,我们的UI矩阵又大都是稀疏的。奇异值分解在矩阵稠密的情况下表示效果才会好。所以我们也不能使用奇异值分解。
于是,真正推荐场景下的矩阵分解方法来了。
隐语义模型 LFM
LFM(Latent Factor Model,隐语义模型)的主要思想是将原始评分矩阵M(mn)分解成两个矩阵P(mk)和Q(kn),同时仅考察原始评分矩阵中有评分的项分解结果是否准确,而判别标准则是均方差(MSE)。即对于矩阵M(mn),我们想办法将其分解为P(mk)、Q(kn),此时对于原始矩阵中有评分的位置MUI来说,其在分解后矩阵中对应的值就是
\[M_{UI}=\sum\limits_{k=1}^K P_{u,k}Q_{k,i} \]
这种方法就是基于隐语义模型(LFM,Latent Factor Model)的矩阵分解。其算法意义层面的解释为通过隐含特征(latent factor)将user兴趣与item特征联系起来。
LFM的思想其实很简单,就是人为设计一个“隐类别”的类别数,各个隐类别的意义我们不用去管,然后通过训练user和item在每个隐类别上的“兴趣”或者“比重”,进而恢复出UI矩阵的思想(后面提到的很多模型都是可以得到用户对未交互过的物品的打分或者点击购买概率,那也相当于恢复出了UI矩阵)。
那么使用LFM的好处是什么呢?为什么要用LFM呢?
还是回到推荐系统的场景中。我们遇到的UI矩阵都是稀疏的,即用户基本和绝大多数的item都没有交互过,体现在隐式反馈的数据中则是一大片的0。
那么我们比如想利用模型恢复出(i,j)位置(用户i对物品j的打分),而这个位置正好没有交互过,是0,那么我们是无法训练到这个点的。使用SVD也是很难训练出一个理想的结果的,因为矩阵太稀疏了,很难学到可以表示UI矩阵的特征值和特征向量们。
而使用了LFM之后,我们将UI矩阵抽象到了两个矩阵P和Q上,这两个矩阵一个代表用户兴趣矩阵,一个代表物品矩阵,两者相乘恢复出UI矩阵。
那么只要这个用户或者物品与其他物品或者用户交互过,其矩阵就能得到训练,所以不需要矩阵稠密,即可训练。
所以我们使用LFM。
Funk-SVD
在LFM的基本思想下,考虑了评分基准的偏置,这样矩阵分解的用户物品向量只用学习评分和评分基准的差值;考虑了用户和物品的偏置,比如有些用户就是倾向于给予很低的评分,或者某部电影很烂,大家评分都很低。
使用偏置来处理特殊情况,这样的话,用户和物品矩阵就更容易学到泛化性能更好的表示。
\[\hat{r_{ui}}=\mu+b_i+b_u+p_uq_i^T \]
目标函数:
\[argmin \sum (r_{ui}-\hat{r_{ui}})^2+\lambda(\sum(b_u^2+||p_u||^2)+\sum(b_i^2+||q_i||^2)) \]
SVD++
SVD++在SVD的基础上引入隐式反馈,使用用户的历史浏览数据、用户历史评分数据、电影的历史浏览数据、电影的历史评分数据等作为新的参数。
某个用户对某个电影进行了评分,那么说明他看过这部电影,那么这样的行为事实上蕴含了一定的信息,因此我们可以这样来理解问题:评分的行为从侧面反映了用户的喜好,可以将这样的反映通过隐式参数的形式体现在模型中.
\[\hat{r_{ui}}=\mu+b_i+b_u+(p_u+\frac{\sum\limits_{j\epsilon I_u}y_j}{\sqrt{|I_u|}})q_i^T \]
其中 I(u) 为该用户所评价过的所有电影的集合,yj为隐藏的“评价了电影 j”反映出的个人喜好偏置,是一个和\(p_u\)维度相同的向量,而非标量。收缩因子取集合大小的根号是一个经验公式,并没有理论依据。