Latent-factor method

Latent-factor method

 上课所提到的电影推荐算法通过找到用户A的相似用户B进而向A推荐B喜欢的电影或找到A喜欢的电影C的相似电影来做推荐。而潜在因子方法是通过用户的潜在因子矩阵得知用户的电影偏好,通过电影的潜在因子矩阵得知电影的风格类型,两者相匹配得到用户喜欢的电影。
 用具体例子说明潜在因子矩阵:
 假设电影的类型分为恐怖,喜剧,科幻,用0~1范围内的数字表示用户对电影的喜欢程度或电影的符合程度,0表示不感兴趣或不符合,1表示非常喜欢或非常符合。那么用户A和B对各类型的喜欢程度可能如下:

恐怖喜剧科幻
A0.90.10.7
B00.90.3

 可以看出用户A喜欢恐怖、科幻的电影,而B更喜欢喜剧电影。
 假设电影C、D分别为科幻恐怖电影和喜剧电影,那么它们的符合程度可能如下:

恐怖喜剧科幻
C0.800.8
D00.90.1

 将用户表里的每一行视为一个向量 p u \mathbf{p}_u pu,电影表的每一行视为一个向量 q i \mathbf{q}_i qi,它们的内积 p u T q i \mathbf{p}_u^T\mathbf{q}_i puTqi可以反映用户的喜欢程度。
 例如用户A对C的喜欢程度: p a T q c = 0.9 ∗ 0.8 + 0.7 ∗ 0.8 = 1.28 \mathbf{p}_a^T\mathbf{q}_c=0.9*0.8+0.7*0.8=1.28 paTqc=0.90.8+0.70.8=1.28,A对D的喜欢程度: p a T q d = 0.1 ∗ 0.9 + 0.7 ∗ 0.1 = 0.16 \mathbf{p}_a^T\mathbf{q}_d=0.1*0.9+0.7*0.1=0.16 paTqd=0.10.9+0.70.1=0.16,用户B对C的喜欢程度: p b T q c = 0.3 ∗ 0.8 = 0.24 \mathbf{p}_b^T\mathbf{q}_c=0.3*0.8=0.24 pbTqc=0.30.8=0.24,B对D的喜欢程度: p b T q d = 0.9 ∗ 0.9 + 0.3 ∗ 0.1 = 0.84 \mathbf{p}_b^T\mathbf{q}_d=0.9*0.9+0.3*0.1=0.84 pbTqd=0.90.9+0.30.1=0.84。可以看出A更喜欢C,B更喜欢D。推荐系统就能利用这些内积来进行推荐。潜在因子矩阵即这两张表的矩阵形式 P \mathbf{P} P Q \mathbf{Q} Q
 实际中我们不能直接获得潜在因子,而是获得用户对电影的总评价。如:

CD
A1.280.16
B0.240.84

 其矩阵形式记作矩阵 R \mathbf{R} R。而且这个表往往大且稀疏,因为用户很多,但用户不是常常都会对电影做出评价。潜在因子方法所做的就是将矩阵R分解为潜在因子矩阵P和Q,即 R = P Q \mathbf{R}=\mathbf{P}\mathbf{Q} R=PQ
 首先定义R矩阵在(u,i)位置上的 r u i r_{ui} rui为用户u对电影i的感兴趣程度,而 r ^ u i \hat{r}_{ui} r^ui为预测,我们通过潜在因子做出预测:
r ^ u i = p u T q i = ∑ k K p u k q k i \hat{r}_{ui}=\mathbf{p}_u^T\mathbf{q}_i=\sum\limits_k^Kp_{uk}q_{ki} r^ui=puTqi=kKpukqki
p u \mathbf{p}_u pu q i \mathbf{q}_i qi为潜在因子矩阵P,Q的一行, p u k p_{uk} puk表示用户u对电影分类k的喜欢程度, q k i q_{ki} qki表示电影i对k分类的匹配程度,K为总类数。
 我们希望用户的评价 R \mathbf{R} R和我们的预测 R ^ \mathbf{\hat{R}} R^接近,可以通过最小化损失函数,损失函数L选择均方误差MSE:
min ⁡ P , Q L = ∑ ( u , i ) ( r u i − p u T q i ) 2 \min\limits_{P,Q}L=\sum\limits_{(u,i)}(r_{ui}-\mathbf{p}_u^T\mathbf{q}_i)^2 P,QminL=(u,i)(ruipuTqi)2
 损失函数也可以加入正则化项防止过拟合,加入后如下:
L = ∑ ( u , i ) ( r u i − p u T q i ) 2 + λ ∑ u ∣ ∣ p u ∣ ∣ 2 + λ ∑ i ∣ ∣ q i ∣ ∣ 2 L = \sum\limits_{(u,i)}(r_{ui}-\mathbf{p}_u^T\mathbf{q}_i)^2+\lambda\sum\limits_u||\mathbf{p}_u||^2+\lambda\sum\limits_i||\mathbf{q}_i||^2 L=(u,i)(ruipuTqi)2+λu∣∣pu2+λi∣∣qi2

求解方法

交替最小二乘法

 由于矩阵P和Q都未知,都需要求解,所以我们可以在求解P时固定Q,转换成最小二乘法问题,反之求Q时固定P,交替执行来求解直至误差满足条件或到达迭代上限。
 具体过程如下:
 1.指定 Q \mathbf{Q} Q初值 Q 0 \mathbf{Q}_0 Q0,可以随机生成
 2.固定 Q 0 \mathbf{Q}_0 Q0,求解 P 0 \mathbf{P}_0 P0
 3.固定 P 0 \mathbf{P}_0 P0,求解 Q 1 \mathbf{Q}_1 Q1
 4.固定 Q 1 \mathbf{Q}_1 Q1,求解 P 1 \mathbf{P}_1 P1
 …(不断重复)
 5.满足误差需求或迭代上限,迭代结束。

 具体过程:
 固定Q,求解P时, min ⁡ P , Q L \min\limits_{P,Q}L P,QminL可以转化为:
min ⁡ P [ ∑ u , i ( r u i − p u T q i ) 2 ] + λ ∑ u ∣ ∣ p u ∣ ∣ 2 = ∑ u min ⁡ P [ ∑ i ( r u i − p u T q i ) 2 ] + λ ∣ ∣ p u ∣ ∣ 2 ] \min\limits_P[\sum\limits_{u,i}(r_{ui}-\mathbf{p}_u^T\mathbf{q}_i)^2]+\lambda\sum\limits_{u}||\mathbf{p}_u||^2=\sum\limits_u\min\limits_P[\sum\limits_i(r_{ui}-\mathbf{p}_u^T\mathbf{q}_i)^2]+\lambda||\mathbf{p}_u||^2] Pmin[u,i(ruipuTqi)2]+λu∣∣pu2=uPmin[i(ruipuTqi)2]+λ∣∣pu2]
 令 l u ( p u ) = ∑ i ( r u i − p u T q i ) 2 + λ ∣ ∣ p u ∣ ∣ 2 l_u(\mathbf{p}_u)=\sum\limits_i(r_{ui}-\mathbf{p}_u^T\mathbf{q_i})^2+\lambda||\mathbf{p}_u||^2 lu(pu)=i(ruipuTqi)2+λ∣∣pu2
 问题转化为最小化 l u ( p u ) l_u(\mathbf{p}_u) lu(pu)
 求偏导得:
∂ l u ∂ p u = 2 ( ∑ i p u T q i q i − ∑ i r u i q i + λ p u ) \frac{\partial l_u}{\partial \mathbf{p}_u}=2(\sum\limits_i\mathbf{p}_u^T\mathbf{q}_i\mathbf{q}_i-\sum\limits_ir_{ui}\mathbf{q}_i+\lambda\mathbf{p}_u) pulu=2(ipuTqiqiiruiqi+λpu)
 令偏导值为0,有:
( ∑ i q i q i T + λ I ) p u = ∑ i r u i q i (\sum\limits_i\mathbf{q}_i\mathbf{q}_i^T+\lambda\mathbf{I})\mathbf{p}_u=\sum\limits_ir_{ui}\mathbf{q}_i (iqiqiT+λI)pu=iruiqi
( Q Q T + λ I ) p u = Q r u (\mathbf{Q}\mathbf{Q}^T+\lambda\mathbf{I})\mathbf{p}_u=\mathbf{Q}\mathbf{r}_u (QQT+λI)pu=Qru
p u = ( Q Q T + λ I ) − 1 Q r u \mathbf{p}_u=(\mathbf{Q}\mathbf{Q}^T+\lambda\mathbf{I})^{-1}\mathbf{Q}\mathbf{r}_u pu=(QQT+λI)1Qru
 求出每一行 p u \mathbf{p}_u pu就可以得到 P \mathbf{P} P
 固定P则可以得到:
q i = ( P P T + λ I ) − 1 P r i \mathbf{q}_i=(\mathbf{P}\mathbf{P}^T+\lambda\mathbf{I})^{-1}\mathbf{P}\mathbf{r}_i qi=(PPT+λI)1Pri

梯度下降法

 也可以通过梯度下降法求解。使用梯度下降算法:
 1.求L的偏导
∂ L ∂ p u k = − 2 ( r u i − ∑ k = 1 K p u k q k i ) q k i + 2 λ p u k \frac{\partial L}{\partial p_{uk}}=-2(r_{ui}-\sum\limits_{k=1}^Kp_{uk}q_{ki})q_{ki}+2\lambda p_{uk} pukL=2(ruik=1Kpukqki)qki+2λpuk
∂ L ∂ q k i = − 2 ( r u i − ∑ k = 1 K p u k q k i ) p u k + 2 λ p k i \frac{\partial L}{\partial q_{ki}}=-2(r_{ui}-\sum\limits_{k=1}^Kp_{uk}q_{ki})p_{uk}+2\lambda p_{ki} qkiL=2(ruik=1Kpukqki)puk+2λpki
 转换成对向量求偏导
∂ L ∂ p u = ∑ i 2 ( p u T q i − r u i ) q i + 2 λ p u \frac{\partial L}{\partial \mathbf{p}_u}=\sum\limits_i2(\mathbf{p}_u^T\mathbf{q}_i-r_{ui})\mathbf{q}_i+2\lambda \mathbf{p}_u puL=i2(puTqirui)qi+2λpu
 对 q i \mathbf{q}_i qi类似

 2.迭代更新
p u = p u − α ∂ L ∂ p u \mathbf{p}_u=\mathbf{p}_u-\alpha\frac{\partial L}{\partial \mathbf{p}_u} pu=puαpuL
 对 q i \mathbf{q}_i qi类似
 其中 α \alpha α为学习率, λ \lambda λ为正则化系数。

代码实现
import numpy as np
import pandas as pd
 

# R:评分矩阵
# K:电影种类数
# epochs: 最大迭代次数
# alpha:学习率
# lamda:正则化系数
# P:用户潜在因子矩阵
# Q:电影潜在因子矩阵
# M:用户数
# N:电影数

def LFM( R, K=3, epochs=1000, alpha=0.0001, lamda=0.001 ):
#     初始化
    M = len(R)
    N = len(R[0])
    P = np.random.rand(M, K)
    Q = np.random.rand(K, N)
    
    for epoch in range(epochs):
        for u in range(M):
            for i in range(N):
                if R[u][i] > 0:
                    eui = np.dot( P[u,:], Q[:,i] ) - R[u][i]
                    for k in range(K):
                        P[u][k] = P[u][k] - alpha * ( 2 * eui * Q[k][i] + 2 * lamda * P[u][k] )
                        Q[k][i] = Q[k][i] - alpha * ( 2 * eui * P[u][k] + 2 * lamda * Q[k][i] )

        R_ = np.dot( P, Q )
        
        Loss = 0
        for u in range(M):
            for i in range(N):
                if R[u][i] > 0:
                    Loss += ( np.dot( P[u,:], Q[:,i] ) - R[u][i] ) ** 2
                    # 加上正则化项
                    for k in range(K):
                        Loss += lamda * ( P[u][k] ** 2 + Q[k][i] ** 2 )
        if Loss < 0.0001:
            break
        
    return P, Q.T, Loss

测试:
使用了上课的例子

在这里插入图片描述

R=[[5,4,4,0,5],[0,3,5,3,4],[5,2,0,2,3],
   [0,2,3,1,2],[4,0,5,4,5],[5,3,0,3,5],
   [3,2,3,2,0],[5,3,4,0,5],[4,2,5,4,0],
   [5,0,5,3,4]]
R = np.array(R)

K = 5
epochs = 5000
alpha = 0.0003
lamda = 0.001
P, Q, Loss = LFM(R, K, epochs, alpha, lamda)
 
print(P)
print(Q)
print(Loss)
 
R_ = P.dot(Q.T)
 
print(R)
print(R_)

结果如下:

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值