SVD++算法

1. SVD++ 是什么?

一句话概括 :SVD++ 是 Yehuda Koren 在 Netflix Prize 竞赛中提出的矩阵分解推荐算法。它在基础 SVD(FunkSVD)的基础上,逐步引入了偏置信息隐式反馈用户属性时间因素,最终形成一个能够充分利用各种信号的强大推荐模型。

重要澄清 :推荐系统中所说的"SVD"并不是线性代数中的正统奇异值分解 ,而是一种基于梯度下降的矩阵分解方法(本质是 FunkSVD / Regularized SVD)。正统 SVD 要求矩阵是稠密的,而推荐场景下的评分矩阵极度稀疏,无法直接做 SVD。因此,推荐领域的"SVD"是伪 SVD,通过优化损失函数来学习隐向量。


2. SVD++ 在推荐系统中的作用

SVD++ 的核心作用是将用户和物品映射到一个 k 维隐空间中,通过用户隐向量和物品隐向量的点积来预测评分或推荐分数。

它的演进过程如下:

版本 公式 核心改进
基础 SVD r^ui=pu⋅qiT\hat{r}_{ui} = p_u \cdot q_i^Tr^ui=pu⋅qiT 学习用户和物品隐向量
SVD + 偏置 r^ui=μ+bi+bu+pu⋅qiT\hat{r}_{ui} = \mu + b_i + b_u + p_u \cdot q_i^Tr^ui=μ+bi+bu+pu⋅qiT 引入全局均值、物品偏置、用户偏置
SVD++ r^ui=μ+bi+bu+(pu+∣N(u)∣−0.5∑j∈N(u)xj+∑a∈Auya)⋅qiT\hat{r}{ui} = \mu + b_i + b_u + \left(p_u + |N(u)|^{-0.5} \sum{j \in N(u)} x_j + \sum_{a \in A_u} y_a\right) \cdot q_i^Tr^ui=μ+bi+bu+(pu+∣N(u)∣−0.5∑j∈N(u)xj+∑a∈Auya)⋅qiT 引入隐式反馈和用户属性
SVD++ + 时间 在各项中加入时间衰减或时间区间参数 引入时间因素,捕捉用户兴趣漂移

3. 增加偏置信息有什么作用?

核心问题:在真实场景中,评分的绝对值受到三类系统性偏差的影响:

  1. 全局平均分 μ\muμ:整个平台的平均评分水平。
  2. 物品偏置 bib_ibi:某些物品天生评分高(如经典电影《肖申克的救赎》),某些物品天生评分低。
  3. 用户偏置 bub_ubu:某些用户打分宽松(总是给高分),某些用户打分严格(总是给低分)。

举例说明

  • 全局平均分 μ=3.0\mu = 3.0μ=3.0
  • 《肖申克的救赎》平均比全局高 1 分 → bi=+1.0b_i = +1.0bi=+1.0
  • 用户小明比平均严格 0.5 分 → bu=−0.5b_u = -0.5bu=−0.5
  • 那么,仅靠偏置预测小明对《肖申克》的评分:3.0+1.0+(−0.5)=3.53.0 + 1.0 + (-0.5) = 3.53.0+1.0+(−0.5)=3.5

作用 :将评分分解为"系统性偏差 + 个性化偏好",让隐向量 pu⋅qiTp_u \cdot q_i^Tpu⋅qiT 只需专注于捕捉用户与物品之间真正的个性化交互,而不是被评分尺度差异干扰。


4. 增加历史行为(隐式反馈)有什么作用?

核心问题 :显式反馈(评分)非常稀疏,大多数用户只看不评。但用户的浏览、点击、收藏等隐式行为却大量存在。

SVD++ 的解决方案

  • 用户有过行为的物品集合 N(u)N(u)N(u),每个物品 jjj 都有一个隐因子向量 xjx_jxj。
  • 将这些隐因子向量求和并归一化 ,作为用户兴趣的补充表示:
    隐式反馈贡献=∣N(u)∣−0.5∑j∈N(u)xj \text{隐式反馈贡献} = |N(u)|^{-0.5} \sum_{j \in N(u)} x_j 隐式反馈贡献=∣N(u)∣−0.5j∈N(u)∑xj
  • 同样,用户属性(性别、年龄等)也各有一个隐因子向量 yay_aya,求和后加入用户表示。

作用

  1. 缓解冷启动:即使新用户没有评分,也可以通过他的浏览行为预测偏好。
  2. 增强表达能力:隐式反馈提供了比评分更丰富的用户兴趣信号。
  3. 提高预测精度:Netflix Prize 中,SVD++ 比基础 SVD 的 RMSE 降低了约 5%。

5. SVD++ 时间因素有什么作用?

核心问题:用户的兴趣和物品的受欢迎程度都随时间变化。

三种时间建模方式

方式 做法 作用
时间加权 对久远的评分赋予更低权重,使其趋近平均值 让模型更关注近期行为
时间区间 将时间划分为多个区间,每个区间学习独立的隐因子向量 捕捉用户兴趣的阶段变化
特殊时段 对节日、周末等特殊时段单独训练隐因子 捕捉周期性模式

作用:解决"人是善变的"问题,让推荐更贴近用户当前的真实兴趣。


6. SVD++ 损失函数的作用

完整损失函数

L=∑(u,i)∈K(rui−r^ui)2+λ(bu2+bi2+∥pu∥2+∥qi∥2+∥xj∥2+∥ya∥2) L = \sum_{(u,i) \in \mathcal{K}} \left( r_{ui} - \hat{r}_{ui} \right)^2 + \lambda \left( b_u^2 + b_i^2 + \|p_u\|^2 + \|q_i\|^2 + \|x_j\|^2 + \|y_a\|^2 \right) L=(u,i)∈K∑(rui−r^ui)2+λ(bu2+bi2+∥pu∥2+∥qi∥2+∥xj∥2+∥ya∥2)

两部分的作用

  1. 预测误差项:控制模型偏差,让预测值尽可能接近真实评分。
  2. 正则化项:控制模型方差,防止隐向量过大导致过拟合。

正则化系数 λ\lambdaλ 的作用 :λ\lambdaλ 越大,模型越保守(隐向量被压小),泛化能力越强,但可能欠拟合;λ\lambdaλ 越小,模型越激进,拟合能力越强,但可能过拟合。


7. SVD++ 的梯度下降流程

  1. 准备评分矩阵,每条评分作为训练样本

  2. 随机初始化所有参数:pu, qi, bu, bi, xj, yap_u,\ q_i,\ b_u,\ b_i,\ x_j,\ y_apu, qi, bu, bi, xj, ya

  3. 对每条已知评分 (u,i)(u, i)(u,i):

    a. 计算预测值:

    r^ui=μ+bu+bi+(pu+∣N(u)∣−0.5∑xj+∑ya)⋅qiT \hat{r}_{ui} = \mu + b_u + b_i + \left(p_u + |N(u)|^{-0.5}\sum x_j + \sum y_a\right)\cdot q_i^T r^ui=μ+bu+bi+(pu+∣N(u)∣−0.5∑xj+∑ya)⋅qiT

    b. 计算误差:

    eui=rui−r^ui e_{ui} = r_{ui} - \hat{r}_{ui} eui=rui−r^ui

    c. 计算梯度:

    ∂L∂bu=−2eui+2λbu∂L∂bi=−2eui+2λbi∂L∂pu=−2euiqi+2λpu∂L∂qi=−2eui(pu+∣N(u)∣−0.5∑xj+∑ya)+2λqi∂L∂xj=−2eui ∣N(u)∣−0.5 qi+2λxj∂L∂ya=−2eui qi+2λya \begin{aligned} \frac{\partial L}{\partial b_u} &= -2e_{ui} + 2\lambda b_u \\ \frac{\partial L}{\partial b_i} &= -2e_{ui} + 2\lambda b_i \\ \frac{\partial L}{\partial p_u} &= -2e_{ui} q_i + 2\lambda p_u \\ \frac{\partial L}{\partial q_i} &= -2e_{ui}\left(p_u + |N(u)|^{-0.5}\sum x_j + \sum y_a\right) + 2\lambda q_i \\ \frac{\partial L}{\partial x_j} &= -2e_{ui}\ |N(u)|^{-0.5}\ q_i + 2\lambda x_j \\ \frac{\partial L}{\partial y_a} &= -2e_{ui}\ q_i + 2\lambda y_a \end{aligned} ∂bu∂L∂bi∂L∂pu∂L∂qi∂L∂xj∂L∂ya∂L=−2eui+2λbu=−2eui+2λbi=−2euiqi+2λpu=−2eui(pu+∣N(u)∣−0.5∑xj+∑ya)+2λqi=−2eui ∣N(u)∣−0.5 qi+2λxj=−2eui qi+2λya

    d. 沿负梯度方向更新参数


8. 完整数值推导案例

8.1 数据准备

用户 \ 物品 I1 I2 I3
U1 5 3 ?
U2 4 ? 2
  • 已知评分 :r11=5r_{11}=5r11=5,r12=3r_{12}=3r12=3,r21=4r_{21}=4r21=4,r23=2r_{23}=2r23=2
  • 隐向量维度 :k=1k=1k=1(标量,方便手算)
  • 学习率 :η=0.01\eta=0.01η=0.01
  • 正则化系数 :λ=0.1\lambda=0.1λ=0.1
  • 全局平均分 :μ=(5+3+4+2)/4=3.5\mu = (5+3+4+2)/4 = 3.5μ=(5+3+4+2)/4=3.5

隐式反馈设定

  • 用户 U1 有过行为的物品集合 N(U1)={I1,I2}N(U1) = \{I1, I2\}N(U1)={I1,I2}(已评分的物品)
  • 用户 U2 有过行为的物品集合 N(U2)={I1,I3}N(U2) = \{I1, I3\}N(U2)={I1,I3}
  • ∣N(U1)∣=2|N(U1)| = 2∣N(U1)∣=2,∣N(U2)∣=2|N(U2)| = 2∣N(U2)∣=2,归一化因子 ∣N(u)∣−0.5=0.707|N(u)|^{-0.5} = 0.707∣N(u)∣−0.5=0.707

8.2 随机初始化

参数 初始值
bU1b_{U1}bU1 0.0
bU2b_{U2}bU2 0.0
bI1b_{I1}bI1 0.0
bI2b_{I2}bI2 0.0
bI3b_{I3}bI3 0.0
pU1p_{U1}pU1 0.1
pU2p_{U2}pU2 0.2
qI1q_{I1}qI1 0.3
qI2q_{I2}qI2 0.4
qI3q_{I3}qI3 0.5
xI1x_{I1}xI1 0.1
xI2x_{I2}xI2 0.2
xI3x_{I3}xI3 0.1

注意 :为了简化,这里假设没有用户属性 yay_aya(即 Au=∅A_u = \emptysetAu=∅)。

8.3 第 1 步:计算用户 U1 对物品 I1 的预测值

用户 U1 的隐式反馈贡献

Imp(U1)=∣N(U1)∣−0.5∑j∈N(U1)xj=0.707×(xI1+xI2)=0.707×(0.1+0.2)=0.2121 \text{Imp}(U1) = |N(U1)|^{-0.5} \sum_{j \in N(U1)} x_j = 0.707 \times (x_{I1} + x_{I2}) = 0.707 \times (0.1 + 0.2) = 0.2121 Imp(U1)=∣N(U1)∣−0.5j∈N(U1)∑xj=0.707×(xI1+xI2)=0.707×(0.1+0.2)=0.2121

用户 U1 的完整隐向量

p~U1=pU1+Imp(U1)=0.1+0.2121=0.3121 \tilde{p}{U1} = p{U1} + \text{Imp}(U1) = 0.1 + 0.2121 = 0.3121 p~U1=pU1+Imp(U1)=0.1+0.2121=0.3121

预测值

r^11=μ+bU1+bI1+p~U1⋅qI1=3.5+0+0+0.3121×0.3=3.5+0.0936=3.5936 \hat{r}{11} = \mu + b{U1} + b_{I1} + \tilde{p}{U1} \cdot q{I1} = 3.5 + 0 + 0 + 0.3121 \times 0.3 = 3.5 + 0.0936 = 3.5936 r^11=μ+bU1+bI1+p~U1⋅qI1=3.5+0+0+0.3121×0.3=3.5+0.0936=3.5936

误差

e11=r11−r^11=5−3.5936=1.4064 e_{11} = r_{11} - \hat{r}_{11} = 5 - 3.5936 = 1.4064 e11=r11−r^11=5−3.5936=1.4064

8.4 第 2 步:计算梯度并更新参数

更新偏置 bU1b_{U1}bU1

bU1←bU1+η(e11−λbU1)=0+0.01×(1.4064−0)=0.014064 b_{U1} \leftarrow b_{U1} + \eta (e_{11} - \lambda b_{U1}) = 0 + 0.01 \times (1.4064 - 0) = 0.014064 bU1←bU1+η(e11−λbU1)=0+0.01×(1.4064−0)=0.014064

更新偏置 bI1b_{I1}bI1

bI1←0+0.01×(1.4064−0)=0.014064 b_{I1} \leftarrow 0 + 0.01 \times (1.4064 - 0) = 0.014064 bI1←0+0.01×(1.4064−0)=0.014064

更新用户隐向量 pU1p_{U1}pU1

pU1←pU1+η(e11qI1−λpU1)=0.1+0.01×(1.4064×0.3−0.1×0.1) p_{U1} \leftarrow p_{U1} + \eta (e_{11} q_{I1} - \lambda p_{U1}) = 0.1 + 0.01 \times (1.4064 \times 0.3 - 0.1 \times 0.1) pU1←pU1+η(e11qI1−λpU1)=0.1+0.01×(1.4064×0.3−0.1×0.1)

=0.1+0.01×(0.42192−0.01)=0.1+0.004119=0.104119 = 0.1 + 0.01 \times (0.42192 - 0.01) = 0.1 + 0.004119 = 0.104119 =0.1+0.01×(0.42192−0.01)=0.1+0.004119=0.104119

更新物品隐向量 qI1q_{I1}qI1

qI1←qI1+η(e11p~U1−λqI1)=0.3+0.01×(1.4064×0.3121−0.1×0.3) q_{I1} \leftarrow q_{I1} + \eta (e_{11} \tilde{p}{U1} - \lambda q{I1}) = 0.3 + 0.01 \times (1.4064 \times 0.3121 - 0.1 \times 0.3) qI1←qI1+η(e11p~U1−λqI1)=0.3+0.01×(1.4064×0.3121−0.1×0.3)

=0.3+0.01×(0.4389−0.03)=0.3+0.004089=0.304089 = 0.3 + 0.01 \times (0.4389 - 0.03) = 0.3 + 0.004089 = 0.304089 =0.3+0.01×(0.4389−0.03)=0.3+0.004089=0.304089

更新隐式反馈向量 xI1x_{I1}xI1 (因为 I1 在 N(U1)N(U1)N(U1) 中):

xI1←xI1+η(e11⋅∣N(U1)∣−0.5⋅qI1−λxI1) x_{I1} \leftarrow x_{I1} + \eta \left( e_{11} \cdot |N(U1)|^{-0.5} \cdot q_{I1} - \lambda x_{I1} \right) xI1←xI1+η(e11⋅∣N(U1)∣−0.5⋅qI1−λxI1)

=0.1+0.01×(1.4064×0.707×0.3−0.1×0.1) = 0.1 + 0.01 \times (1.4064 \times 0.707 \times 0.3 - 0.1 \times 0.1) =0.1+0.01×(1.4064×0.707×0.3−0.1×0.1)

=0.1+0.01×(0.2983−0.01)=0.1+0.002883=0.102883 = 0.1 + 0.01 \times (0.2983 - 0.01) = 0.1 + 0.002883 = 0.102883 =0.1+0.01×(0.2983−0.01)=0.1+0.002883=0.102883

更新隐式反馈向量 xI2x_{I2}xI2 (同样在 N(U1)N(U1)N(U1) 中,梯度按相同方式传播):

xI2←0.2+0.01×(1.4064×0.707×0.3−0.1×0.2) x_{I2} \leftarrow 0.2 + 0.01 \times (1.4064 \times 0.707 \times 0.3 - 0.1 \times 0.2) xI2←0.2+0.01×(1.4064×0.707×0.3−0.1×0.2)

=0.2+0.01×(0.2983−0.02)=0.2+0.002783=0.202783 = 0.2 + 0.01 \times (0.2983 - 0.02) = 0.2 + 0.002783 = 0.202783 =0.2+0.01×(0.2983−0.02)=0.2+0.002783=0.202783

注意 :xI3x_{I3}xI3 不在 N(U1)N(U1)N(U1) 中,因此本次更新不涉及 xI3x_{I3}xI3。

8.5 第 3 步:对下一条评分重复更新

对 r12=3r_{12}=3r12=3,r21=4r_{21}=4r21=4,r23=2r_{23}=2r23=2 依次执行相同的预测、误差计算、梯度更新过程。每一轮(epoch)遍历所有已知评分后,参数会逐渐收敛。

8.6 预测问号:U1 对 I3 的评分

假设经过 500 轮迭代后,参数收敛为:

参数 收敛值
bU1b_{U1}bU1 0.8
bI3b_{I3}bI3 -0.3
pU1p_{U1}pU1 0.5
qI3q_{I3}qI3 0.4
xI1x_{I1}xI1 0.3
xI2x_{I2}xI2 0.4

用户 U1 的隐式反馈贡献

Imp(U1)=0.707×(xI1+xI2)=0.707×(0.3+0.4)=0.495 \text{Imp}(U1) = 0.707 \times (x_{I1} + x_{I2}) = 0.707 \times (0.3 + 0.4) = 0.495 Imp(U1)=0.707×(xI1+xI2)=0.707×(0.3+0.4)=0.495

完整用户向量

p~U1=0.5+0.495=0.995 \tilde{p}_{U1} = 0.5 + 0.495 = 0.995 p~U1=0.5+0.495=0.995

预测 U1 对 I3 的评分

r^13=μ+bU1+bI3+p~U1⋅qI3=3.5+0.8+(−0.3)+0.995×0.4 \hat{r}{13} = \mu + b{U1} + b_{I3} + \tilde{p}{U1} \cdot q{I3} = 3.5 + 0.8 + (-0.3) + 0.995 \times 0.4 r^13=μ+bU1+bI3+p~U1⋅qI3=3.5+0.8+(−0.3)+0.995×0.4

=4.0+0.398=4.398 = 4.0 + 0.398 = 4.398 =4.0+0.398=4.398

所以,U1 对 I3 的预测评分为 4.4,可以推荐给 U1。


9. 总结:SVD++ 各组件的作用

组件 作用 在案例中的体现
基础 SVD 学习用户和物品隐向量 pU1⋅qI1p_{U1} \cdot q_{I1}pU1⋅qI1
偏置信息 捕捉评分尺度差异 μ+bU1+bI1\mu + b_{U1} + b_{I1}μ+bU1+bI1
隐式反馈 利用浏览/点击行为补充用户兴趣 0.707×(xI1+xI2)0.707 \times (x_{I1} + x_{I2})0.707×(xI1+xI2)
用户属性 缓解冷启动 yay_aya(本例省略)
时间因素 捕捉兴趣漂移 本例未涉及,但可通过时间区间实现
损失函数 平衡拟合能力与泛化能力 预测误差 + L2 正则化
梯度下降 迭代优化所有参数 逐样本更新 b,p,q,x,yb, p, q, x, yb,p,q,x,y

一句话记住 SVD++

SVD++ = 基础矩阵分解 + 偏置信息 + 隐式反馈 + 用户属性 + 时间因素。它把能利用的信号全部融入一个统一的梯度下降框架中,是 Netflix Prize 时代最强大的推荐算法之一。

相关推荐
是翎2 小时前
深度长文|2026产品经理AI实践手册
人工智能·深度学习·学习·自然语言处理·数据挖掘
qq_2518364572 小时前
springboot vue3 开发实现 拼豆管理系统
java·开发语言·ai编程
caoerzhong2 小时前
JeeWMS 开源仓库管理系统全景解读:一套 Java WMS 如何把 WMS/OMS/BMS/TMS 装进同一个系统
java·开源
曹牧2 小时前
Java集合框架:List、ArrayList、Map 和 HashMap
java
顾城猿2 小时前
STOMP 协议
java
宿州派大星2 小时前
[NLP实战] 基于PyTorch实现N-gram词嵌入模型:输入4个词预测第5个词
人工智能·pytorch·深度学习·nlp
骇客野人3 小时前
测试环境MySQL迁移Vastbase(海量数据库)完整改造与落地实施方案
运维·服务器
+VX:Fegn08953 小时前
计算机毕业设计|基于springboot + vue旅游管理系统(源码+数据库+文档)
java·开发语言·vue.js·spring boot·课程设计
迪康Defender3 小时前
终端安全实战:如何高效解决企业U盘泄密与管控难题
运维·网络·安全·web安全·终端安全管理