基于矩阵分解的推荐算法
1.背景
推荐系统的两大应用场景分别是评分预测(Rating Prediction)和Top-N推荐(Item Ranking)。其中评分预测主要用于评价网站,比如用户给自己看过的电影评多少分,或者用户给自己看过的书籍评价多少分,矩阵分解技术主要应用于评分预测问题;Top-N推荐常用于购物网站或获取不到显式评分的网站,通过用户的隐式反馈为用户提供一个可能感兴趣的Item列表,此排序任务需要排序模型进行建模。本文主要介绍如何利用矩阵分解来解决评分预测问题。
2.矩阵分解概述
协同过滤技术可划分为基于内存/邻域的协同过滤(Memory-based CF)与基于模型的协同过滤技术(Model-based CF)。这里基于模型的协同过滤技术中矩阵分解(Matrix Factorization,MF)技术最为普遍和流行,因为它的可扩展性好并且易于实现。
矩阵分解是一种隐语义模型。隐语义模型是通过隐含特征(Latent Factor)联系用户兴趣和物品,基于用户行为的自动聚类。在评分预测问题中,收集到的用户行为评分数据可用一个评分矩阵表示,矩阵分解要做的是预测出评分矩阵中缺失的评分,使得预测评分能反映用户的喜欢程度,从而可以把预测评分最高的前K个电影推荐给用户。为了预测缺失的评分,矩阵分解学习 UserUserUser 矩阵和 ItemItemItem 矩阵,使得UserUserUser矩阵∗*∗ ItemItemItem矩阵与评分矩阵中已知的评分差异最小,此时评分预测问题转化为了一个最优化问题,求解该最优化问题即可将评分矩阵分解成User矩阵和Item矩阵,从而可以计算出缺失的评分。
在评分预测问题中:
- 构建 user -item 评分矩阵(数据是稀疏的,矩阵分解就是填充缺失的评分)
- 学习 UserUserUser 矩阵和 ItemItemItem 矩阵,使得评分与矩阵中已知的评分差异最小(最优化问题)
以电影评分预测为例,用评分矩阵表示收集到的用户行为数据,12个用户,9部电影。
对上述用户-物品评分矩阵(12×9)进行矩阵分解,得到User(12×3)矩阵和Item(3×9)矩阵。观察下图User矩阵,可知用户的观影爱好体现在User向量上,观察Item矩阵,可知电影的风格体现在Item向量上,MF用user向量和item向量的内积去拟合评分矩阵中该user对该item的评分,内积的大小反映了user对item的喜欢程度,内积越大表明用户对该电影的喜爱程度高,反之用户对该电影的喜爱程度低。这里“动作”、“动画”、“爱情”为隐含特征,隐含特征个数k越大,隐类别分得越细,计算量越大。
把User矩阵与Item矩阵相乘,就能预测每个用户对每部电影的预测评分了,评分值越大,表示用户喜欢该电影的可能性越大,该电影就越值得推荐给用户。
3.矩阵分解目标函数
在用户-物品评分矩阵 R\\bold RR 中,ruir_{ui}rui 表示 用户 uuu 对 Item $i$ 的评分 , 当 rui>0r_{ui}\\ \\gt 0rui >0 时,表示有评分,当rui=0\\ r_{ui}\\ = 0 rui =0,表示没有评分。
在User矩阵 X\\bold XX 中(M×kM×kM×k,用户数为M),xux_uxu 表示用户 uuu 的向量,k维列向量。X=[x1,x2,...,xM]\\bold X=[x_1,x_2,...,x_M]X=[x1,x2,...,xM]
在Item矩阵 Y\\bold YY 中(k×Nk×Nk×N,物品数为N),yiy_iyi 表示用户 itemiitem_iitemi 的向量,k维列向量。Y=[y1,y2,...,yN]\\bold Y=[y_1,y_2,...,y_{N}]Y=[y1,y2,...,yN]
用户向量与物品向量的内积,表示用户 uuu 对物品 iii 的预测评分。矩阵分解的目标函数为:
minX,Y∑rui≠0(rui−xuTyi)2+λ(∑u∣∣xu∣∣22+∑i∣∣yi∣∣22)\\min \\limits_{X,Y} \\sum\\limits_{r_{ui}\\neq\\ 0}\\left(r_{ui}-x^T_uy_i\\right)^2+\\lambda\\left(\\sum\\limits_{u}||x_u||^2_2+\\sum\\limits_{i}||y_i||^2_2\\right) X,Yminrui= 0∑(rui−xuTyi)2+λ(u∑∣∣xu∣∣22+i∑∣∣yi∣∣22)
上式前半部分表示的是User矩阵*Item矩阵与评分矩阵中已知的评分差异,后半部分是L2正则项,保证数值计算稳定性,防止过拟合。
4.目标函数最优化问题求解
目标函数最优化问题的工程解法一般采用交替最小二乘法( Alternating Least Squares , ALS)或随机梯度下降(SGD)。 在实际应用中,交替最小二乘更常用一些,这也是社交巨头 Facebook 在他们的推荐系统中选择的主要矩阵分解方法。
4.1 交替最小二乘法(ALS)
交替最小二乘的核心是 “交替”,接下来看看 ALS 是如何 “交替” :
矩阵分解的最终任务是找到两个矩阵 X\\bold XX 和 Y\\bold YY,让它们相乘后约等于原矩阵 R\\bold RR:
Rm×n=Xm×k×Yn×kT\\bold R_{m×n}=\\bold X_{m×k}\\ ×\\ \\bold Y_{n×k}^T Rm×n=Xm×k × Yn×kT
难就难在,X\\bold XX 和Y\\bold YY 两个都是未知的,如果知道其中一个的话,就可以按照线性代数标准解法求得,比如如果知道了 Y\\bold YY,那么 X\\bold XX 就可以这样算:
Rm×n=Xm×k×Yn×k−1\\bold R_{m×n}=\\bold X_{m×k}\\ ×\\ \\bold Y_{n×k}^{-1} Rm×n=Xm×k × Yn×k−1
也就是 R\\bold RR 矩阵乘以 Y\\bold YY 矩阵的逆矩阵就得到了结果,反之知道了 X\\bold XX 再求Y\\bold YY 也是一样。
交替最小二乘通过迭代的方式解决了这个鸡生蛋蛋生鸡的难题:
- 初始化随机矩阵 Y\\bold YY 里面的元素值;
- 把 Y\\bold YY 矩阵当做已知的,直接用线性代数的方法求得矩阵 X\\bold XX;
- 得到了矩阵 X\\bold XX后,把 X\\bold XX 当做已知的,故技重施,回去求解矩阵 Y\\bold YY ;
- 上面两个过程交替进行,一直到误差满足设定条件为止。
交替最小二乘法步骤:
-
Step1\\bold Step1Step1,固定 Y\\bold YY 优化 X\\bold XX
minX∑rui≠0(rui−xuTyi)2+λ∑u∣∣xu∣∣22\\min \\limits_{X} \\sum\\limits_{r_{ui}\\neq\\ 0}\\left(r_{ui}-x^T_uy_i\\right)^2+\\lambda\\sum\\limits_{u}||x_u||^2_2 Xminrui= 0∑(rui−xuTyi)2+λu∑∣∣xu∣∣22
将目标函数转化为矩阵表达形式:
J(xu)=(Ru−YuTxu)T(Ru−YuTxu)+λxuTxuJ(x_u)=(R_u-Y^T_ux_u)^T(R_u-Y^T_ux_u)+\\lambda x^T_ux_u J(xu)=(Ru−YuTxu)T(Ru−YuTxu)+λxuTxu
其中 Ru=[rui1,rui2,...ruin]TR_u=[r_{ui_1},r_{ui_2},...r_{ui_n}]^TRu=[rui1,rui2,...ruin]T 表示用户 uuu 对 nnn 个物品的评分;Yu=[yi1,yi2,...yim]Y_u=[y_{i_1},y_{i_2},...y_{i_m}]Yu=[yi1,yi2,...yim] 为 nnn 个物品的向量。求解目标函数 JJJ 关于 xux_uxu 的梯度,并令梯度等于0,得到:
∂J(xu)∂xu=−2Yu(Ru−YuTxu)+2λxu=0\\frac{\\partial J(x_u)}{\\partial x_u}=-2Y_u(R_u-Y^T_ux_u)+2\\lambda x_u=0 ∂xu∂J(xu)=−2Yu(Ru−YuTxu)+2λxu=0
求解后可得:
xu=(YuYuT+λI)−1YuRux_u = (Y_uY^T_u+\\lambda I)^{-1}Y_uR_u xu=(YuYuT+λI)−1YuRu -
Step2\\bold Step2Step2,固定 X\\bold XX 优化 Y\\bold YY
minY∑rui≠0(rui−xuTyi)2+λ∑i∣∣yi∣∣22\\min \\limits_{Y} \\sum\\limits_{r_{ui}\\neq\\ 0}\\left(r_{ui}-x^T_uy_i\\right)^2+\\lambda\\sum\\limits_{i}||y_i||^2_2 Yminrui= 0∑(rui−xuTyi)2+λi∑∣∣yi∣∣22-
将目标函数转化为矩阵表达形式:
J(yi)=(Ri−XiTyi)T(Ri−XiTyi)+λyiTyiJ(y_i)=(R_i-X^T_iy_i)^T(R_i-X^T_iy_i)+\\lambda y^T_iy_i J(yi)=(Ri−XiTyi)T(Ri−XiTyi)+λyiTyi
其中Ru=[ru1i,ru2i,...rumi]TR_u=[r_{u_1{i}},r_{u_2i},...r_{u_mi}]^TRu=[ru1i,ru2i,...rumi]T表示 mmm个用户对个物品 iii 的评分;Xi=[xu1,xu2,...xum]X_i=[x_{u_1},x_{u_2},...x_{u_m}]Xi=[xu1,xu2,...xum] 为 mmm个用户的向量。求解目标函数 JJJ关于 yiy_iyi 的梯度,并令梯度等于0,得到:
∂J(yi)∂xi=−2Xi(Ri−XiTyi)+2λyi=0\\frac{\\partial J(y_i)}{\\partial x_i}=-2X_i(R_i-X^T_iy_i)+2\\lambda y_i=0 ∂xi∂J(yi)=−2Xi(Ri−XiTyi)+2λyi=0
求解后可得:
yi=(XiXiT+λI)−1XiRiy_i = (X_iX^T_i+\\lambda I)^{-1}X_iR_i yi=(XiXiT+λI)−1XiRi
-
-
重复Step1\\bold Step1Step1和2\\bold 22,直到 X\\bold XX 和 Y\\bold YY 收敛,每次固定一个矩阵,优化另一个矩阵,都是最小二乘问题
除了针对显式评分矩阵,ALS还可以对隐式矩阵进行分解,将评分看成行为的强度,比如浏览次数,阅读时间等。 当 rui>0r_{ui}\\ \\gt 0rui >0时, 表示用户 uuu对商品 iii 有行为,当 rui=0r_{ui}\\ = 0rui =0, 表示用户 uuu对商品 iii 没有行为。
Pui={1rui>00rui=0P_{ui}=\\begin{cases} 1 & r_{ui} \\gt 0 \\\\ 0 & r_{ui} = 0 \\end{cases} Pui={10rui>0rui=0
上式 PuiP_{ui}Pui 称为用户偏好:当用户uuu对物品iii有过行为,认为用户uuu对物品iii感兴趣,PuiP_{ui}Pui=1;当用户uuu对物品iii没有过行为,认为用户uuu对物品iii不感兴趣,PuiP_{ui}Pui=0.
对隐式矩阵进行分解的步骤:
-
引入置信度(α\\alphaα 为置信系数)
cui=1+αruic_{ui}=1+\\alpha r_{ui} cui=1+αrui
当rui>0\\ r_{ui}\\ \\gt 0 rui >0时, cuic_{ui}cui 与 ruir_{ui}rui 线性递增,当 rui=0r_{ui}\\ = 0rui =0时, cui=1c_{ui}\\ = 1cui =1,即 cuic_{ui}cui 最小值为1. -
目标函数
minX,Y∑u=1m∑i=1ncui(rui−xuTyi)2+λ(∑u∣∣xu∣∣22+∑i∣∣yi∣∣22)\\min \\limits_{X,Y} \\sum\\limits_{u=1}\\limits^{m} \\sum\\limits_{i=1}\\limits^{n}c_{ui}\\left(r_{ui}-x^T_uy_i\\right)^2+\\lambda\\left(\\sum\\limits_{u}||x_u||^2_2+\\sum\\limits_{i}||y_i||^2_2\\right) X,Yminu=1∑mi=1∑ncui(rui−xuTyi)2+λ(u∑∣∣xu∣∣22+i∑∣∣yi∣∣22) -
ALS求解矩阵X\\bold XX和Y\\bold YY
ALS工具
- spark ml库(官方推荐)
- python代码:https://github.com/tushushu/imylu/blob/master/imylu/recommend/als.py
4.2 随机梯度下降SGD
SGD基本思路是以随机方式遍历训练集中的数据,并给出每个已知评分的预测评分。用户和物品特征向量的调整就沿着评分误差越来越小的方向迭代进行,直到误差达到要求。所以,SGD不需要遍历所有的样本即可完成特征向量的求解。
矩阵分解的目标函数为:
J(xu,yi)=minX,Y∑rui≠0(rui−xuTyi)2+λ(∑u∣∣xu∣∣22+∑i∣∣yi∣∣22)J(x_u,y_i)= \\min \\limits_{X,Y} \\sum\\limits_{r_{ui}\\neq\\ 0}\\left(r_{ui}-x^T_uy_i\\right)^2+\\lambda\\left(\\sum\\limits_{u}||x_u||^2_2+\\sum\\limits_{i}||y_i||^2_2\\right) J(xu,yi)=X,Yminrui= 0∑(rui−xuTyi)2+λ(u∑∣∣xu∣∣22+i∑∣∣yi∣∣22)
分别求解J(xu,yi)J(x_u,y_i)J(xu,yi)关于 xux_uxu 和 yiy_iyi的梯度如下:
∂J(xu,yi)∂xu=∑u,rui≠0−2(rui−xuTyi)yi+∑u2λ∣∣xu∣∣2∂J(xu,yi)∂yi=∑i,rui≠0−2(rui−xuTyi)xu+∑i2λ∣∣yi∣∣2\\begin{align} & \\frac{\\partial J(x_u,y_i)}{\\partial x_u}=\\sum\\limits_{u,r_{ui}\\neq 0}-2\\left(r_{ui}-x^T_uy_i\\right)y_i+\\sum\\limits_u 2\\lambda||x_u||_2 \\\\[2ex] & \\frac{\\partial J(x_u,y_i)}{\\partial y_i}=\\sum\\limits_{i,r_{ui}\\neq 0}-2\\left(r_{ui}-x^T_uy_i\\right)x_u+\\sum\\limits_i 2\\lambda||y_i||_2 \\end{align} ∂xu∂J(xu,yi)=u,rui=0∑−2(rui−xuTyi)yi+u∑2λ∣∣xu∣∣2∂yi∂J(xu,yi)=i,rui=0∑−2(rui−xuTyi)xu+i∑2λ∣∣yi∣∣2
不断更新矩阵 X\\bold XX 和 Y\\bold YY
xu=xu+α(∑u,rui≠0−2(rui−xuTyi)yi+∑u2λ1∣∣xu∣∣2)yi=yi+α(∑i,rui≠0−2(rui−xuTyi)xu+∑i2λ2∣∣yi∣∣2)\\begin{align} &x_u=x_u+\\alpha(\\sum\\limits_{u,r_{ui}\\neq 0}-2\\left(r_{ui}-x^T_uy_i\\right)y_i+\\sum\\limits_u 2\\lambda_1||x_u||_2) \\\\[2ex] &y_i=y_i+\\alpha(\\sum\\limits_{i,r_{ui}\\neq 0}-2\\left(r_{ui}-x^T_uy_i\\right)x_u+\\sum\\limits_i 2\\lambda_2||y_i||_2) \\end{align} xu=xu+α(u,rui=0∑−2(rui−xuTyi)yi+u∑2λ1∣∣xu∣∣2)yi=yi+α(i,rui=0∑−2(rui−xuTyi)xu+i∑2λ2∣∣yi∣∣2)
由于 X\\bold XX 和 Y\\bold YY 是两个不同的矩阵,通常分别采取不同的正则参数,如 λ1\\lambda_1λ1和λ2\\lambda_2λ2
5.矩阵分解算法
MF(Matrix Factorization,矩阵分解)模型核心思想是通过两个低维小矩阵(一个代表用户embedding矩阵,一个代表物品embedding矩阵)的乘积计算,来模拟真实用户点击或评分产生的大的协同信息稀疏矩阵,本质上是编码了用户和物品协同信息的降维模型。
当训练完成,每个用户和物品得到对应的低维embedding表达后,如果要预测某个 UseriUser_iUseri 对 ItemjItem_jItemj 的评分的时候,只要它们做个内积计算 <Useri,Itemj><User_i,Item_j><Useri,Itemj> ,这个得分就是预测得分。
5.1 Traditional SVD
5.1.1 回顾特征值和特征向量
特征值和特征向量的定义如下:
Ax=λxAx=\\lambda x Ax=λx
其中 AAA 是一个 n×nn×nn×n 的实对称矩阵,xxx 是一个 nnn 维向量,则我们说 λ\\lambdaλ 是矩阵 AAA 的一个特征值,而 xxx 是矩阵 AAA 的特征值 λ\\lambdaλ 所对应的特征向量。
求出特征值和特征向量有什么好处呢?
可以将矩阵A特征分解。
如果我们求出了矩阵AAA的nnn个特征值λ1≤λ2≤...≤λnλ_1≤λ_2≤...≤λ_nλ1≤λ2≤...≤λn,以及这 nnn个特征值所对应的特征向量w1,w2,...wn{w_1,w_2,...w_n}w1,w2,...wn,如果这 nnn 个特征向量线性无关,那么矩阵 AAA 就可以用下式的特征分解表示:
A=WΣW−1A=W\\Sigma W^{-1} A=WΣW−1
其中 WWW 是这 nnn 个特征向量所张成的 n×nn×nn×n 维矩阵,而 Σ\\SigmaΣ 为这 nnn 个特征值为主对角线的 n×nn×nn×n 维矩阵。
一般我们会把WWW的这nnn个特征向量标准化,即满足∣∣wi∣∣2=1||w_i||_2=1∣∣wi∣∣2=1, 或者说 wiTwi=1w^T_iw_i=1wiTwi=1,此时 WWW 的 nnn 个特征向量为标准正交基,满足WTW=IW^TW=IWTW=I,即WT=W−1W^T=W^{−1}WT=W−1, 也就是说WWW为酉矩阵。
A=WΣWTA=W\\Sigma W^{T} A=WΣWT
注意到要进行特征分解,矩阵AAA必须为方阵。那么如果AAA不是方阵,即行和列不相同时,我们还可以对矩阵进行分解吗?答案是可以,此时我们的SVD登场了。
5.1.2 SVD
假设矩阵AAA是一个m×nm×nm×n的矩阵,那么我们定义矩阵AAA的SVD为: :
A=UΣVTA=U\\Sigma V^{T} A=UΣVT
其中 UUU 是一个 m×mm×mm×m 的矩阵,Σ\\SigmaΣ 是一个 m×nm×nm×n 的矩阵,除了主对角线上的元素以外全为 000 ,主对角线上的每个元素都称为奇异值,VVV是一个 n×nn×nn×n 的矩阵。UUU 和 VVV 都是酉矩阵,即满足UTU=I,VTV=IU^TU=I,V^TV=IUTU=I,VTV=I。下图可以很形象的看出上面SVD的定义:
如何求出SVD分解后的U,Σ,VU,Σ,VU,Σ,V这三个矩阵呢?
如果将AAA的转置和AAA做矩阵乘法,那么会得到n×nn×nn×n的一个方阵ATAA^TAATA。既然ATAA^TAATA是方阵,那么可以进行特征分解,得到的特征值和特征向量满足下式:
(ATA)vi=λivi(A^TA)v_i=\\lambda_i v_i (ATA)vi=λivi
这样可以得到矩阵ATAA^TAATA的nnn个特征值和对应的nnn个特征向量vvv了。将ATAA^TAATA的所有特征向量张成一个n×nn×nn×n的矩阵VVV,即为SVD公式里面的VVV矩阵了。一般将VVV中的每个特征向量叫做AAA的右奇异向量。
如果我们将A和A的转置做矩阵乘法,那么会得到m×mm×mm×m的一个方阵AATAA^TAAT。既然AATAA^TAAT是方阵,那么可以进行特征分解,得到的特征值和特征向量满足下式:
(AAT)ui=λiui(AA^T)u_i=\\lambda_iu_i (AAT)ui=λiui
这样可以得到矩阵AATAA^TAAT的nnn个特征值和对应的mmm个特征向量uuu了。将AATAA^TAAT的所有特征向量张成一个m×mm×mm×m的矩阵UUU,即为SVD公式里面的UUU矩阵了。一般将UUU中的每个特征向量叫做AAA的左奇异向量。
UUU和VVV都求出来了,现在就剩下奇异值矩阵 Σ\\SigmaΣ 没有求出了。由于除了对 Σ\\SigmaΣ 角线上是奇异值其他位置都是0,那只需要求出每个奇异值σ\\sigmaσ 就可以了。
A=UΣVT⇒AV=UΣVTV⇒AV=UΣ⇒Avi=σiui⇒σi=Avi/uiA=U\\Sigma V^T \\Rightarrow AV=U\\Sigma V^TV \\Rightarrow AV=U\\Sigma \\Rightarrow Av_i = \\sigma_i u_i \\Rightarrow \\sigma_i = Av_i / u_i A=UΣVT⇒AV=UΣVTV⇒AV=UΣ⇒Avi=σiui⇒σi=Avi/ui
这样我们可以求出我们的每个奇异值,进而求出奇异值矩阵Σ\\SigmaΣ。
ATAA^TAATA的特征向量组成的就是我们SVD中的VVV矩阵,而AATAA^{T}AAT的特征向量组成的就是我们SVD中的UUU矩阵,这有什么根据吗?这个其实很容易证明,我们以VVV矩阵的证明为例。
A=UΣVT⇒AT=VΣTUT⇒ATA=VΣTUTUΣVT=VΣ2VTA=U\\Sigma V^T \\Rightarrow A^T=V\\Sigma^T U^T \\Rightarrow A^TA = V\\Sigma^T U^TU\\Sigma V^T = V\\Sigma^2V^T A=UΣVT⇒AT=VΣTUT⇒ATA=VΣTUTUΣVT=VΣ2VT
上式证明使用了: UTU=I,ΣTΣ=Σ2U^TU=I, \\Sigma^T\\Sigma=\\Sigma^2UTU=I,ΣTΣ=Σ2。 可以看出ATAA^TAATA的特征向量组成的的确就是我们SVD中的VVV矩阵。类似的方法可以得到AATAA^TAAT的特征向量组成的就是我们SVD中的UUU矩阵。
特征值矩阵等于奇异值矩阵的平方,也就是说特征值和奇异值满足如下关系:
σi=λi\\sigma_i = \\sqrt{\\lambda_i} σi=λi
通过求出ATAA^{T}AATA的特征值取平方根来求奇异值更加方便。
5.1.3 SVD的性质
对于奇异值,它跟特征分解中的特征值类似,在奇异值矩阵中也是按照从大到小排列,而且奇异值的减少特别的快,在很多情况下,前10%甚至1%的奇异值的和就占了全部的奇异值之和的99%以上的比例。也就是说,可以用最大的kkk个的奇异值和对应的左右奇异向量来近似描述矩阵。也就是说:
Am×n=Um×mΣm×nVn×nT≈Um×kΣk×kVk×nTA_{m \\times n} = U_{m \\times m}\\Sigma_{m \\times n} V^T_{n \\times n} \\approx U_{m \\times k}\\Sigma_{k \\times k} V^T_{k \\times n} Am×n=Um×mΣm×nVn×nT≈Um×kΣk×kVk×nT
SVD可以用于PCA降维,来做数据压缩和去噪。也可以用于推荐算法,将用户和喜好对应的矩阵做特征分解,进而得到隐含的用户需求来做推荐。同时也可以用于NLP中的算法,比如潜在语义索引(LSI)。
5.1.4 SVD与PCA的关系
PCA的算法流程
求样本x(i)x^{(i)}x(i)的n′n'n′维的主成分其实就是求样本集的协方差矩阵XXTXX^TXXT的前n′n'n′个特征值对应特征向量矩阵WWW,然后对于每个样本x(i)x^{(i)}x(i),做如下变换 z(i)=WTx(i)z^{(i)}=W^Tx^{(i)}z(i)=WTx(i),即达到降维的PCA目的。
下面我们看看具体的算法流程。
输入:nnn维样本集D=(x(1),x(2),...,x(m))D=(x^{(1)}, x^{(2)},...,x^{(m)})D=(x(1),x(2),...,x(m)),要降维到的维数n′n'n′.
输出:降维后的样本集D′D′D′
-
对所有的样本进行中心化: x(i)=x(i)−1m∑j=1mx(j)x^{(i)} = x^{(i)} - \\frac{1}{m}\\sum\\limits_{j=1}^{m} x^{(j)}x(i)=x(i)−m1j=1∑mx(j)
-
计算样本的协方差矩阵XXTXX^{T}XXT
-
对矩阵XXTXX^{T}XXT进行特征值分解
4)取出最大的n’个特征值对应的特征向量(w1,w2,...,wn′)(w_1,w_2,...,w_n′)(w1,w2,...,wn′), 将所有的特征向量标准化后,组成特征向量矩阵WWW。
5)对样本集中的每一个样本x(i)x^{(i)}x(i),转化为新的样本z(i)=WTx(i)z^{(i)}=W^Tx^{(i)}z(i)=WTx(i)
- 得到输出样本集D′=(z(1),z(2),...,z(m))D' =(z^{(1)}, z^{(2)},...,z^{(m)})D′=(z(1),z(2),...,z(m))
有时候,我们不指定降维后的n′n'n′的值,而是换种方式,指定一个降维到的主成分比重阈值ttt。这个阈值ttt在(0,1](0,1](0,1]之间。假如我们的n个特征值为λ1≥λ2≥...≥λn\\lambda_1 \\geq \\lambda_2 \\geq ... \\geq \\lambda_nλ1≥λ2≥...≥λn,则n′n'n′可以通过下式得到:
∑i=1n′λi∑i=1nλi≥t\\frac{\\sum\\limits_{i=1}^{n'}\\lambda_i}{\\sum\\limits_{i=1}^{n}\\lambda_i} \\geq t i=1∑nλii=1∑n′λi≥t
SVD用于PCA
PCA仅仅使用了我们SVD的右奇异矩阵,没有使用左奇异矩阵,那么左奇异矩阵有什么用呢?
现有样本是m×nm×nm×n的矩阵XXX,如果我们通过SVD找到了矩阵XXTXX^{T}XXT最大的ddd个特征向量张成的m×dm×dm×d维矩阵UUU,则如果进行如下处理:
Xd×n′=Ud×mTXm×nX'_{d \\times n} = U_{d \\times m}^TX_{m \\times n} Xd×n′=Ud×mTXm×n
可得一个d×nd×nd×n的矩阵X'X'X',和原来的m×nm×nm×n维样本矩阵XXX相比,行数从mmm减到了ddd,可见对行数进行了压缩。也就是说,左奇异矩阵可以用于行数的压缩。相对的,右奇异矩阵可以用于列数即特征维度的压缩,也就是PCA降维。
5.2 FunkSVD(LFM)
2006年的Netflix Prize之后, Simon Funk公布了一个矩阵分解算法叫做Funk-SVD, 后来被 Netflix Prize 的冠军Koren称为Latent Factor Model(LFM)。
FunkSVD是在传统SVD面临计算效率问题时提出来的,既然将一个矩阵做SVD分解成3个矩阵很耗时,同时还面临稀疏的问题,那么能不能避开稀疏问题的同时只分解成两个矩阵呢?即现在期望我们的矩阵MMM这样进行分解:
Mm×n=Pm×kTQk×nM_{m \\times n}=P_{m \\times k}^TQ_{k \\times n} Mm×n=Pm×kTQk×n
目标:让用户的评分和用矩阵乘积得到的评分残差尽可能的小,也就是说,可以用均方差作为损失函数,来寻找最终的PPP和QQQ。
对于某一个用户评分mijm_{ij}mij,如果用FunkSVD进行矩阵分解,则对应的表示为qjTpiq_j^Tp_iqjTpi,采用均方差做为损失函数,则我们期望(mij−qjTpi)2(m_{ij}-q_j^Tp_i)^2(mij−qjTpi)2尽可能的小,如果考虑所有的物品和样本的组合,则我们期望最小化下式:
∑i,j(mij−qjTpi)2\\sum\\limits_{i,j}(m_{ij}-q_j^Tp_i)^2 i,j∑(mij−qjTpi)2
只要能最小化上面的式子,并求出极值所对应的pi,qjp_i, q_jpi,qj,则可以得到矩阵PPP和QQQ,那么对于任意矩阵MMM任意一个空白评分的位置,我们可以通过qjTpiq_j^Tp_iqjTpi计算预测评分。
在实际应用中,为了防止过拟合,会加入一个L2的正则化项,因此正式的FunkSVD的优化目标函数J(p,q)J(p,q)J(p,q)是这样的:
argmin⏟pi,qj∑i,j(mij−qjTpi)2+λ(∣∣pi∣∣22+∣∣qj∣∣22)\\underbrace{arg\\;min}_{p_i,q_j}\\;\\sum\\limits_{i,j}(m_{ij}-q_j^Tp_i)^2 + \\lambda(||p_i||_2^2 + ||q_j||_2^2 ) pi,qjargmini,j∑(mij−qjTpi)2+λ(∣∣pi∣∣22+∣∣qj∣∣22)
其中 λ\\lambdaλ 为正则化系数,需要调参。对于这个优化问题,一般通过梯度下降法来进行优化得到结果。
将上式分别对pi,qjp_i, q_jpi,qj求导得:
∂J∂pi=−2(mij−qjTpi)qj+2λpi∂J∂qj=−2(mij−qjTpi)pi+2λqj\\begin{align} &\\frac{\\partial J}{\\partial p_i} = -2(m_{ij}-q_j^Tp_i)q_j + 2\\lambda p_i\\\\[2ex] & \\frac{\\partial J}{\\partial q_j} = -2(m_{ij}-q_j^Tp_i)p_i + 2\\lambda q_j \\end{align} ∂pi∂J=−2(mij−qjTpi)qj+2λpi∂qj∂J=−2(mij−qjTpi)pi+2λqj
则在梯度下降法迭代时,pi,qjp_i, q_jpi,qj的迭代公式为:
pi=pi+α((mij−qjTpi)qj−λpi)qj=qj+α((mij−qjTpi)pi−λqj)\\begin{align} & p_i = p_i + \\alpha((m_{ij}-q_j^Tp_i)q_j - \\lambda p_i)\\\\[2ex] & q_j =q_j + \\alpha((m_{ij}-q_j^Tp_i)p_i - \\lambda q_j) \\end{align} pi=pi+α((mij−qjTpi)qj−λpi)qj=qj+α((mij−qjTpi)pi−λqj)
通过迭代我们最终可以得到PPP和QQQ,进而用于推荐。
5.3 BiasSVD算法
BiasSVD算法是在FunkSVD算法的基础上考虑了用户和商品的偏好。用户有自己的偏好(Bias),比如乐观的用户打分偏高;商品也有自己的偏好(Bias),比如质量好的商品,打分偏高;BiasSVD算法将与个性化无关的部分,设置为偏好(Bias)部分。
假设评分系统平均分为 μ\\muμ,第i个用户的用户偏置项为 bib_ibi ,而第 jjj 个物品的物品偏置项为 bjb_jbj,则加入了偏置项以后的优化目标函数 J(p,q)J(p,q)J(p,q) 如下:
argmin⏟pi,qj∑i,j(mij−μ−bi−bj−qjTpi)2+λ(∣∣pi∣∣22+∣∣qj∣∣22+∣∣bi∣∣22+∣∣bj∣∣22)\\underbrace{arg\\;min}_{p_i,q_j}\\;\\sum\\limits_{i,j}(m_{ij}-\\mu-b_i-b_j-q_j^Tp_i)^2 + \\lambda(||p_i||_2^2 + ||q_j||_2^2 + ||b_i||_2^2 + ||b_j||_2^2) pi,qjargmini,j∑(mij−μ−bi−bj−qjTpi)2+λ(∣∣pi∣∣22+∣∣qj∣∣22+∣∣bi∣∣22+∣∣bj∣∣22)
优化目标也可以采用梯度下降法求解。 bi,bjb_i,b_jbi,bj一般可以初始设置为000,然后参与迭代。bi,bjb_i,b_jbi,bj迭代方法如下:
bi=bi+α(mij−μ−bi−bj−qjTpi−λbi)bj=bj+α(mij−μ−bi−bj−qjTpi−λbj)\\begin{align} & b_i = b_i + \\alpha(m_{ij}-\\mu-b_i-b_j-q_j^Tp_i -\\lambda b_i)\\\\[2ex] & b_j = b_j + \\alpha(m_{ij}-\\mu-b_i-b_j-q_j^Tp_i -\\lambda b_j) \\end{align} bi=bi+α(mij−μ−bi−bj−qjTpi−λbi)bj=bj+α(mij−μ−bi−bj−qjTpi−λbj)
通过迭代我们最终可以得到PPP和QQQ,进而用于推荐。
5.4 SVD++算法
SVD++算法在BiasSVD算法上进一步做了增强,这里它增加考虑用户的隐式反馈。
对于某一个用户iii,它提供了隐式反馈的物品集合定义为N(i)N(i)N(i), 这个用户对某个物品jjj对应的隐式反馈修正的评分值为cijc_{ij}cij, 那么该用户所有的评分修正值为∑s∈N(i)cis\\sum\\limits_{s \\in N(i)}c_{is}s∈N(i)∑cis。一般我们将它表示为用qsTyiq_s^Ty_iqsTyi形式,则加入了隐式反馈项以后的优化目标函数J(p,q)J(p,q)J(p,q)如下:
argmin⏟pi,qj∑i,j(mij−μ−bi−bj−qjTpi−qjT∣N(i)∣−1/2∑s∈N(i)qs)2+λ(∣∣pi∣∣22+∣∣qj∣∣22+∣∣bi∣∣22+∣∣bj∣∣22+∑s∈N(i)∣∣qs∣∣22)\\underbrace{arg\\;min}_{p_i,q_j}\\;\\sum\\limits_{i,j}(m_{ij}-\\mu-b_i-b_j-q_j^Tp_i - q_j^T|N(i)|^{-1/2}\\sum\\limits_{s \\in N(i)}q_{s})^2+ \\lambda(||p_i||_2^2 + ||q_j||_2^2 + ||b_i||_2^2 + ||b_j||_2^2 + \\sum\\limits_{s \\in N(i)}||q_{s}||_2^2) pi,qjargmini,j∑(mij−μ−bi−bj−qjTpi−qjT∣N(i)∣−1/2s∈N(i)∑qs)2+λ(∣∣pi∣∣22+∣∣qj∣∣22+∣∣bi∣∣22+∣∣bj∣∣22+s∈N(i)∑∣∣qs∣∣22)
其中,引入∣N(i)∣−1/2|N(i)|^{-1/2}∣N(i)∣−1/2是为了消除不同∣N(i)∣|N(i)|∣N(i)∣个数引起的差异。式子够长的,不过需要考虑用户的隐式反馈时,使用SVD++还是不错的选择。
6.矩阵分解算法的优缺点
优点:
-
泛化能力强。一定程度上解决了数据稀疏的问题。
-
空间复杂度低。 仅仅存储用户和物品隐向量。空间复杂度有 n2n^2n2 降低到 (m+n)∗k(m+n)*k(m+n)∗k
-
更好的扩展性和灵活性。 矩阵分解的最终产物是用户和物品隐向量, 这个深度学习的embedding思想不谋而合, 因此矩阵分解的结果非常便于与其他特征进行组合和拼接, 并可以与深度学习无缝结合。
缺点:
- 矩阵分解算法依然是只用到了评分矩阵, 没有考虑到用户特征, 物品特征和上下文特征, 这使得矩阵分解丧失了利用很多有效信息的机会。
- 在缺乏用户历史行为的时候, 无法进行有效的推荐。
本文仅仅做个人学习记录所用,不作为商业用途,谢谢理解。
参考:
1.https://www.cnblogs.com/pinard/p/6351319.html
2.https://alice1214.github.io/%E6%8E%A8%E8%8D%90%E7%AE%97%E6%B3%95/2020/07/08/%E6%8E%A8%E8%8D%90%E7%AE%97%E6%B3%95%E5%AD%A6%E4%B9%A0-%E4%BA%94-%E7%9F%A9%E9%98%B5%E5%88%86%E8%A7%A3/