《推荐系统笔记(十四)》矩阵分解(MF)以及基于矩阵分解的topN推荐

前言

用户评分矩阵往往十分稀疏,为了对这种稀疏矩阵进行补全,充分利用已有数据,我们可以采用矩阵分解办法。实际上,一旦矩阵补全,相当于预测出用户对未购买物品的评分,基于这些评分,我们就可以对任何用户进行推荐。

本篇博客将对矩阵分解进行介绍,同时介绍两种常用的用来解决矩阵分解问题的算法SGD(随机梯度下降)和ALS(交叉最小二乘)。这两种优化方法还能用来解决两种简单的推荐算法。

我们都将利用movielens数据集,对这些方法进行简单的实战演示。

MF

给定用户评分矩阵 R m × n R_{m\times n} Rm×n,有 m m m个用户给 n n n个物品进行打分。通常,我们遇到的评分矩阵是这样的,

电影1电影2电影3
用户15
用户23
用户34

可以看到,评分矩阵往往很稀疏,这是因为物品太多,用户不可能购买或者观看所有的物品,只会挑选他最感兴趣的进行消费。

面对这样的评分矩阵 R m × n R_{m\times n} Rm×n,我们用矩阵分解,也就是说,

  • 对于每一个用户和物品,我们都会给予一个 k k k维隐向量,这种隐向量代表着用户或者物品在 k k k个隐特征上的取值
  • 矩阵分解就是分解出这些 k k k维隐向量的过程

还是用上面的例子,我们假设,对每一个用户和电影,我们给予一个 2 2 2维隐向量,这个维度我们猜测为 动作,爱情。我们将用户的隐向量拼在一起,将电影的矩阵拼在一起,就可以分别得到用户矩阵和电影矩阵,即

  • 用户矩阵 P m × k P_{m\times k} Pm×k,对于第一列,我们可以解释为,用户1对于动作这个元素的喜爱为2,对爱情这个元素的喜爱为1
用户1用户2用户3
动作245
爱情153
  • 电影矩阵 Q n × k Q_{n\times k} Qn×k,对于第一列,我们可以解释为,电影1对于动作这个元素的倾向为4,对于爱情这个元素的倾向为1
电影1电影2电影3
动作441
爱情153

有了上面的用户矩阵 P P P和物品矩阵 Q Q Q,我们期望能将评分矩阵 R R R分解成用户矩阵和物品矩阵的乘积,即下式成立 R = P T Q R=P^TQ R=PTQ 这也是矩阵分解名字的由来。

为了求出这样的 P P P Q Q Q(严格等号成立几乎不可能,我们只能尽量让其近似),我们将误差最小
min ⁡ P i , Q j E r r o r = 1 2 ∑ ( i , j ) ∈ { R i j 非 空 } ( R i j − P i T Q j ) 2 + λ 2 ∑ i , j ( ∣ P i ∣ 2 + ∣ Q j ∣ 2 ) \min_{P_i, Q_j}Error=\frac{1}{2}\sum_{(i,j)\in\{R_{ij}非空\}} (R_{ij}-P_i^TQ_j)^2+\frac{\lambda}{2}\sum_{i,j}(|P_i|^2+|Q_j|^2) Pi,QjminError=21(i,j){Rij}(RijPiTQj)2+2λi,j(Pi2+Qj2)

其中, P i P_i Pi为用户 i i i k k k维隐列向量, Q j Q_j Qj为电影 j j j k k k维隐列向量。

对于上述问题,我们有两种方法解决,分别是随机梯度下降(SGD)和交替最小二乘(ALS)。

1. SGD

对误差函数关于 P i P_i Pi Q j Q_j Qj求导,我们有
∂ E r r o r ∂ P i = ∑ j ∈ { R i j 非 空 } ( P i T Q j − R i j ) Q j + λ P i \frac{\partial Error}{\partial P_i}=\sum_{j\in\{R_{ij}非空\}}(P_i^TQ_j-R_{ij})Q_j+\lambda P_i PiError=j{Rij}(PiTQjRij)Qj+λPi


∂ E r r o r ∂ Q j = ∑ i ∈ { R i j 非 空 } ( P i T Q j − R i j ) P i + λ Q j \frac{\partial Error}{\partial Q_j}=\sum_{i\in\{R_{ij}非空\}}(P_i^TQ_j-R_{ij})P_i+\lambda Q_j QjError=i{Rij}(PiTQjRij)Pi+λQj

这样,我们的更新策略为
P i ← P i − α ∂ E r r o r ∂ P i P_i\leftarrow P_i-\alpha \frac{\partial Error}{\partial P_i} PiPiαPiError


Q j ← Q j − α ∂ E r r o r ∂ Q j Q_j\leftarrow Q_j-\alpha \frac{\partial Error}{\partial Q_j} QjQjαQjError

2. ALS

ALS的思想是,固定其中一个变量,将另一个变量求出来,再固定另一个变量,将开始的那个变量求出来,如此反复迭代,直至满足条件终止。

我们首先固定 Q Q Q,对误差函数关于 P i P_i Pi求导,有
∂ E r r o r ∂ P i = ∑ j ∈ { R i j 非 空 } ( P i T Q j − R i j ) Q j + λ P i = ∑ j ∈ { R i j 非 空 } Q j Q j T P i + λ P i − ∑ j ∈ { R i j 非 空 } R i j Q j = ( ∑ j ∈ { R i j 非 空 } Q j Q j T + λ I ) P i − ∑ j ∈ { R i j 非 空 } R i j Q j \begin{array}{lll} \frac{\partial Error}{\partial P_i}&=&\sum_{j\in\{R_{ij}非空\}}(P_i^TQ_j-R_{ij})Q_j+\lambda P_i\\ &=&\sum_{j\in\{R_{ij}非空\}}Q_jQ_j^TP_i+\lambda P_i-\sum_{j\in\{R_{ij}非空\}}R_{ij}Q_j\\ &=& (\sum_{j\in\{R_{ij}非空\}}Q_jQ_j^T+\lambda I)P_i-\sum_{j\in\{R_{ij}非空\}}R_{ij}Q_j \end{array} PiError===j{Rij}(PiTQjRij)Qj+λPij{Rij}QjQjTPi+λPij{Rij}RijQj(j{Rij}QjQjT+λI)Pij{Rij}RijQj

∂ E r r o r ∂ P i = 0 \frac{\partial Error}{\partial P_i}=0 PiError=0,可以得到
P i = ( ∑ j ∈ { R i j 非 空 } Q j Q j T + λ I ) − 1 ∑ j ∈ { R i j 非 空 } R i j Q j P_i=(\sum_{j\in\{R_{ij}非空\}}Q_jQ_j^T+\lambda I)^{-1}\sum_{j\in\{R_{ij}非空\}}R_{ij}Q_j Pi=(j{Rij}QjQjT+λI)1j{Rij}RijQj

同理,我们固定 P i P_i Pi,计算 Q j Q_j Qj如下,
∂ E r r o r ∂ Q j = ∑ i ∈ { R i j 非 空 } ( P i T Q j − R i j ) P i + λ Q j = 0 \frac{\partial Error}{\partial Q_j}=\sum_{i\in\{R_{ij}非空\}}(P_i^TQ_j-R_{ij})P_i+\lambda Q_j=0 QjError=i{Rij}(PiTQjRij)Pi+λQj=0
得到
Q j = ( ∑ i ∈ { R i j 非 空 } P i P i T + λ I ) − 1 ∑ i ∈ { R i j 非 空 } R i j P i Q_j=(\sum_{i\in\{R_{ij}非空\}}P_iP_i^T+\lambda I)^{-1}\sum_{i\in\{R_{ij}非空\}}R_{ij}P_i Qj=(i{Rij}PiPiT+λI)1i{Rij}RijPi

3. 优化方法的应用

对于上面的SGD和ALS方法,我们还可以用来计算其他推荐算法,比如Baseline算法和Slopeone算法。

3.1 Baseline算法

Baseline算法是基于统计的一种算法,它同样利用用户评分矩阵,预测用户对于未购买产品的评分。

已知用户 u u u对于物品 i i i的评分 R u i R_{ui} Rui,我们假设

  • 全体用户有一个评分均值,记为 μ \mu μ
  • 用户 u u u的评分偏好 b u b_u bu,意思是,如果 b u > 0 b_u>0 bu>0,则用户 u u u习惯于打高分,比平均分高 b u b_u bu;如果 b u < 0 b_u<0 bu<0,则用户 u u u习惯于打低分,比平均分低 ∣ b u ∣ |b_u| bu
  • 物品 i i i的评分偏好 b i b_i bi,意思是,如果 b i > 0 b_i>0 bi>0,则这个物品收到的评分偏高,比平均分高 b i b_i bi

这样,我们的误差函数为
min ⁡ b u , b i E r r o r = ∑ R u , i 非 空 ( R u , i − μ − b u − b i ) 2 + λ ( ∑ u ∣ b u ∣ 2 + ∑ i ∣ b i ∣ 2 ) \min_{b_u, b_i}Error=\sum_{R_{u,i}非空}(R_{u, i}-\mu-b_u-b_i)^2+\lambda(\sum_{u}|b_u|^2+\sum_{i}|b_i|^2) bu,biminError=Ru,i(Ru,iμbubi)2+λ(ubu2+ibi2)

3.2 Slopeone算法

对于slopeone算法,我们有以下步骤:

  • 计算出任意两个物品 i i i j j j之间的平均评分差 d e v i , j dev_{i, j} devi,j,或者说,物品 i i i的评分比物品 j j j平均要高多少,即 d e v i , j = 1 ∣ N ( i ) ∩ N ( j ) ∣ ∑ u ∈ N ( i ) ∩ N ( j ) ( R u , i − R u , j ) dev_{i,j}=\frac{1}{|N(i)\cap N(j)|}\sum_{u\in{N(i)\cap N(j)}}(R_{u,i}-R_{u,j}) devi,j=N(i)N(j)1uN(i)N(j)(Ru,iRu,j)
    其中, N ( i ) N(i) N(i)表示给物品 i i i打过分的用户集合
  • 对于用户 u u u和物品 i i i,利用用户打过分的所有物品与物品 i i i的评分差,计算用户 u u u对物品 i i i的评分 p ( u , i ) p(u, i) p(u,i),如下
    p u , i = 1 ∣ N ( u ) ∣ ∑ j ∈ N ( u ) ( d e v i , j + u j ) p_{u, i}=\frac{1}{|N(u)|}\sum_{j\in N(u)}(dev_{i, j}+u_j) pu,i=N(u)1jN(u)(devi,j+uj)

基于surprise库的简单实战

基于surprise库,我们对movielens数据集进行topN预测。

movielens数据集已经上传,各位可以免费下载。

# 第三方库
import numpy as np
import pandas as pd
from surprise import SVD
from surprise import Reader
from surprise import Dataset
# 导入数据
data = pd.read_csv(r'D:\myfile\开课吧\推荐系统\第五节\movielens\ratings.csv')
data.head()

在这里插入图片描述

# 丢掉timestampe列
data.drop('timestamp', axis=1, inplace=True)
data.head()
# 将data读入surprise中

# 定义阅读器,给定文本格式
reader = Reader(line_format='user item rating', sep=',')
# 按照阅读器格式读取数据
raw_data = Dataset.load_from_df(data, reader=reader)
# 将这个数据转化为可用数据集
my_data = raw_data.build_full_trainset()
# 用MF进行预测
algo = SVD(biased=False)
algo.fit(my_data)
# 遍历整个数据集
# 创建user_items字典,存储用户购买过的物品集合
# 创建items集合,存储所有的物品集合
user_items = {}
items = set()

for user, item, rating in data.values:
    user_items.setdefault(user, set())
    user_items[user].add(item)
    
    items.add(item)
# 给定用户u,期望能给他从没有购买的物品中推荐N个物品
def topN(u, N=4):
    scores = {}
    
    for i in items:
        if i not in user_items[u]:
            scores[i] = algo.predict(u, i).est
    
    # 对评分排序
    ans = sorted(scores.items(), key=lambda x: x[1], reverse=True)[:N]
    return ans  
# 测试
topN(1)
# 测试结果
[(94466.0, 4.578501891615852),
 (26587.0, 4.507607235916675),
 (77658.0, 4.500811875576563),
 (7502.0, 4.500239302579578)]
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值