easy-algorithm-interview-an.../recommend/推荐系统中的矩阵分解详解.md

8.5 KiB
Raw Permalink Blame History

0.前言

推荐系统最常见的两种场景为评分预测与排序。评分预测的典型场景为豆瓣上一个用户对电影的评分淘宝上对某个商品的评分。排序的场景更为普遍比如信息流业务中从海量的内容中挑选出最合适的topN内容给用户展示就是一个典型的排序问题。
推荐系统中非常经典的技术之一就是矩阵分解(Matrix Factorization)。矩阵分解具有优秀的可扩展性,而且实现起来也不困难,因此在实际中使用非常广泛。下面我们针对推荐系统中的矩阵分解相关内容做一个详细梳理。

1.推荐系统中矩阵分解的场景

以最经典的电影评分为例通常将用户与i电影表示为二维矩阵其中矩阵的元素表示用户对电影的评分分数越高表示用户对电影越喜欢而?表示评分记录缺失。在实际中,评分矩阵一般都是非常稀疏的,因为电影的数量有很多,用户看过的电影必然是少数,评分的更少,所以这个矩阵会极度稀疏。因此实际项目中,如何根据比较少的数据来预测或者填充未观测到的数据一直是一个比较重要的课题,而矩阵分解就是解决这个问题非常好的一种方式。

2.特征值分解

说到矩阵分解,一般先会提到特征值分解(Eigen decomposition),或者说谱分解(Spectral decomposition)。
首先我们明确一点,矩阵乘法,其实对应的是一个变换,是把任意的一个向量变成另外一个方向或者长度的新向量。如果矩阵对某些向量只发生伸缩变换,不产生旋转效果,那么这些向量就称为这个矩阵的特征向量,伸缩的比例就是特征值。
比如矩阵A = \left[ \begin{matrix} 3 & 0 \\\\ 0 & 1 \\\\ \end{matrix} \right] \left[ \begin{matrix} 3 & 0 \\\\ 0 & 1 \\\\ \end{matrix} \right] . \left[ \begin{matrix} x \\\\ y \\\\ \end{matrix} \right] = \left[ \begin{matrix} 3 x \\\\ y \\\\ \end{matrix} \right]

因此矩阵A乘以一个向量 (x,y)的结果是沿X轴拉伸三倍沿Y轴拉伸一倍。
(以上例子来自网络)

对于一个矩阵A(A为方阵),一定有
A v = \lambda v
此时\lambda为特征向量v对应的特征值。而特征值分解为
A = Q \Sigma Q^{-1}
其中Q是A的特征向量组成的矩阵。
在这里插入图片描述
输入公式比较麻烦,大家参考一下手写的特征值分解过程。是不是有上大学时候学线性代数的感觉。

3.奇异值分解

上面特征值分解比较麻烦的一点在于要求矩阵A为方阵。但是实际中大部分矩阵不为方阵这个时候奇异值分解就可以大显身手了。
关于奇异值分解的原理,具体可以参考SVD分解

经典的SVD分解要求矩阵是稠密的否则无法进行分解。同事分解过程中有求逆运算时间复杂度为O(n^3)复杂度比较高。因此人们想了各种办法来优化SVD分解。

4.FunkSVD

Simon Funk提出的方案被称为FunkSVD。FunkSVD不将矩阵分解为三个矩阵U, \SigmaV而是分解为2个低秩的user-item矩阵降低了系统的复杂度
优化的目标函数为
\min \limits_{q^\*,p^\*} \sum \limits_{(u, i)} (r_{ui} - q_i^Tp_u) ^ 2

核心思想是通过最小化观测数据的MSE讲user与item的用一个低秩的隐向量表示出来。同时还可以加上L2正则
\min \limits_{q^\*,p^\*} \sum \limits_{(u, i)} (r_{ui} - q_i^T p_u) ^ 2 + \lambda (||q_i||^2 + ||p_u||^2)
优化求解的方法可以通过传统的GD或者SGD方法来求解。

5.BiasSVD

BiasSVD是在FunkSVD基础上的改进。其基本原理如下不同user与不同item天生就有“bias”。比如有的用户给所有的item打分都很高而有的item因为位置等客官因素打分也比一般的item要高。所以我们在预测评分的时候需要对这些“bias”有所体现。因此预测评分
\hat{r}_{ui} = \mu + b_u + b_i + q_i^Tp_u
其中,\mu表示整体的平均分数,b_u是user的偏置b_i是item的偏置。
所以最终的目标函数变为

\min_{q^\*,p^\*, b_i, b_u} \sum_{(u, i)} (r_{ui} - q_i^Tp_u) ^ 2 + \lambda (||q_i||^2 + ||p_u||^2 + ||b_i||^2 + ||b_u||^2)

6.SVD++

SVD++是在SVD的基础上加入隐式反馈使用user的各种历史浏览记录历史评分记item的各种历史浏览记录历史评分记录等作为新的参数加入到模型中。
\hat{r}\_{ui} = \mu + b_u + b_i + q_i^T(p_u + I_u^{-1}\sum \limits_ {j \in I_u} y_j)

其中,I_u为user i所产生隐反馈行为的物品集合y_i为隐藏的“评价了电影 j”反映出的个人喜好偏置。

7.NMF(non-negative matrix factorization)

NMF为非负矩阵分解。在其他矩阵分解方法的基础之上新增加了一个约束分解出来的矩阵均为非负的。
在大部分矩阵分解的方法中原始矩阵被分解为两个低秩矩阵的形式即使原始矩阵元素都非负但是也不能保证分解出来的小矩阵也非负。这就导致了分解结果的可解释性或者说跟现实世界的认知差别比较大因为现实世界很多场景事负数是没有意思的。比如用SVD做图像压缩像素显然不能为负数。比如td-idf值也不能为负数。
因此非负矩阵分解是有现实意义的。ALS算法里面就用到了NMF。
假设有矩阵A
A = P^TQ
其中,P >= 0, Q >= 0

8. One-Class Collaborative Filtering

首先我们来看one-class问题。预测用户行为的时候大部分的时候只有用户正向选择的行为记录(即正样本)。如果我们使用0-1矩阵表示这类问题1表示用户喜欢该物品0的话却不一定事用户不喜欢也有可能只是没有看到。

对于上面的情况,有三种解决方式。
第一是通过标注负样本来转化为一个传统的协同过滤问题,很明显这样代价很高,需要大量的人力来标注,而且标注的结果也不一定对。
第二是将所有缺失值作为负样本。这样做的缺点就是我们前面提到的,缺失的样本不一定为负样本,只是用户没看到而已。
第三是将缺失值看成未知,忽略所有缺失值。这种方法的结果就是预测结果也只有正类。
要解决上面问题就是如何填充这些缺失值,也就是如何收集负样本,有下面几种方法
1.均匀采样,即把所有的缺失数据看作负样本,以相同的概率进行抽样。
2.偏重用户采样,即活跃度用户的负样本要多一点,对活跃用户来说,他没有产生行为的物品将会以更高的概率选作负样本。
3.偏重物品采样,即热门物品的负样本要多一点,对热门物品来说,曝光机会多,如果用户对它没有行为,则高概率是负样本。
上面第二种与第三种方法相对来说更合理。

9.WMF WRMF(Weighted Regularized Matrix Factorization, WRMF)

加权正则化矩阵分解(Weighted Regularized Matrix Factorization, WRMF)是《Collaborative Filtering for Implicit Feedback Datasets》提出的用于解决隐式反馈推荐。
定义隐式反馈的损失函数为
\min \sum \limits_{(u, i)} c_{ui}(p_{ui} - q_i^Tp_u) ^ 2 + \lambda (||q_i||^2 + ||p_u||^2 + ||b_i||^2 + ||b_u||^2)

在隐式反馈中,模型事没有评分的,因此在式子中r_{ui}p_{ui}取代了,p_{ui}就表示偏好仅仅表示用户和物品之间有没有交互而不表示评分高低或者喜好程度。比如用户和物品之间有交互就让pui等于1没有就等于0。函数中的c_{ui}项,是表示用户对某个物品偏好的置信程度,比如交互次数较多的权重就会增加。例如我们用d_{ui}表示交互次数,那么置信度一般表示为

c_{ui} = 1 + \alpha d_{ui}
这里的\alpha就是上面的置信参数,也是模型的一个超参数,需要模型验证。