评分预测与模型融合
评分预测(Rating Prediction)是推荐系统的经典研究问题,核心任务是根据用户的历史评分记录,预测用户对未评分物品的评分。Netflix Prize 大赛(2006-2009)是该领域最重要的推动力,最终获胜队伍通过融合上百个模型达到将预测误差降低 10% 的目标。
SVD 系列模型演进
评分预测问题定义
数据集 :用户评分三元组 (u, i, r),表示用户 u 给物品 i 评分 r。由于用户不会对所有物品评分,评分矩阵 R 中存在大量缺失值(Missing Value),评分预测本质上是填空问题。
评测指标 :
均方根误差 RMSE(Netflix Prize 采用):
RMSE = sqrt(Σ (r_{ui} - r̂_{ui})² / |Test|)
平均绝对误差 MAE:
MAE = Σ |r_{ui} - r̂_{ui}| / |Test|
RMSE 对预测偏差更严格(平方项惩罚),研究表明若评分系统基于整数,对预测结果取整可以降低 MAE。
实验设置 :
- 一般按时间划分:Netflix 的做法是每个用户最早 90% 的评分为训练集,最近 10% 为测试集
- 与时间无关的任务:按均匀分布随机划分
TopN 推荐 vs 评分预测
亚马逊前科学家 Greg Linden 指出评分预测的局限性:电影推荐的目的是找到用户最可能感兴趣 的电影,而非预测他看后会给的分数。某部电影用户看后会给高分,但用户选择看它的可能性可能很低。因此 TopN 推荐更贴近实际系统需求,本书主体内容讨论 TopN 推荐(见 协同过滤算法),本章专注于评分预测。
评分预测算法
1. 平均值方法
最简单的基准算法,不同维度的平均值性能差异显著。
全局平均值 :
r̂_{ui} = μ = (1/|Train|) * Σ r_{ui}
物品平均值 (性能优于全局平均值):
r̂_{ui} = μ_i = (1/|N(i)|) * Σ_{u∈N(i)} r_{ui}
用户评分平均值 :
r̂_{ui} = μ_u = (1/|N(u)|) * Σ_{i∈N(u)} r_{ui}
类类平均值 (最强的平均值基准):
将用户和物品各自分类,对同类用户给同类物品的评分取平均。分类维度包括:
- 用户活跃度(评分物品数量)
- 物品流行度(评过分的用户数量)
- 用户平均分(UserVoteCluster)
- 物品平均分(ItemVoteCluster)
MovieLens 实验结果(Test RMSE):
| UserGroup | ItemGroup | Test RMSE |
|---|---|---|
| Cluster(全局) | Cluster | 1.1167 |
| IdCluster | Cluster | 1.0351 |
| Cluster | IdCluster | 0.9779 |
| UserVoteCluster | IdCluster | 0.9441 |
| IdCluster | ItemVoteCluster | 0.9449 |
| UserVoteCluster | ** ItemVoteCluster** | ** 0.9342** |
结论:对用户按评分习惯分类(UserVoteCluster)、对物品按平均质量分类(ItemVoteCluster)效果最好。
2. 基于邻域的评分预测
UserCF 评分预测(皮尔逊系数相似度):
r̂_{ui} = μ_u + Σ_{v∈S(u,K)∩N(i)} w_{uv} * (r_{vi} - μ_v) / Σ|w_{uv}|
使用皮尔逊系数而非余弦相似度,因为它消除了不同用户评分尺度的差异:
w_{uv} = Σ_i (r_{ui}-μ_u)(r_{vi}-μ_v) / sqrt(Σ(r_{ui}-μ_u)² * Σ(r_{vi}-μ_v)²)
ItemCF 评分预测 :
r̂_{ui} = μ_i + Σ_{j∈S(i,K)∩N(u)} w_{ij} * (r_{uj} - μ_j) / Σ|w_{ij}|
物品相似度计算的三种方式(Sarwar 等比较):
- 普通余弦相似度
- 皮尔逊系数
- 修正余弦相似度 (Adjusted Cosine):减去用户的评分均值再计算,效果最优
w_{ij} = Σ_u (r_{ui}-μ_u)(r_{uj}-μ_u) / sqrt(Σ_u(r_{ui}-μ_u)² * Σ_u(r_{uj}-μ_u)²)
3. 矩阵分解模型(LFM/SVD)
传统 SVD 分解
对评分矩阵 R 先用均值补全缺失值得 R',再做 SVD 分解:
R' = U * S * V^T → R̂ ≈ U_f * S_f * V_f^T
缺点 :需要先将稀疏矩阵补全为稠密矩阵(空间和计算代价极大),实际无法用于百万级用户/物品。
Funk-SVD(Simon Funk,2006)
Simon Funk 在博客上提出直接从观察值学习低维矩阵,引爆了学术界对矩阵分解的关注:
将 R 分解为两个低维矩阵:
R ≈ P * Q^T,即 r̂_{ui} = p_u · q_i = Σ_k p_{uk} * q_{ik}
损失函数(加 L2 正则化):
L = Σ_{(u,i)∈Train} (r_{ui} - p_u·q_i)² + λ(‖p_u‖² + ‖q_i‖²)
随机梯度下降迭代更新:
e_{ui} = r_{ui} - p_u · q_i
p_{uk} ← p_{uk} + α * (e_{ui} * q_{ik} - λ * p_{uk})
q_{ik} ← q_{ik} + α * (e_{ui} * p_{uk} - λ * q_{ik})
# 每轮衰减学习率:α *= 0.9
def LearningLFM(train, F, n, alpha, lambda_):
p, q = InitLFM(train, F)
for step in range(n):
for u, i, rui in train.items():
pui = sum(p[u][f] * q[i][f] for f in range(F))
eui = rui - pui
for f in range(F):
p[u][f] += alpha * (q[i][f] * eui - lambda_ * p[u][f])
q[i][f] += alpha * (p[u][f] * eui - lambda_ * q[i][f])
alpha *= 0.9
return p, q
初始化:矩阵元素用随机数填充,大小与 1/sqrt(F) 成正比。
BiasSVD(加入偏置项)
引入三个偏置项消除与用户/物品无关的系统性偏差:
r̂_{ui} = μ + b_u + b_i + p_u · q_i
- μ :全局平均分(网站整体评分倾向)
- b_u (用户偏置):该用户是否比较苛刻或宽松
- b_i (物品偏置):该物品本身质量高低
偏置项通过同样的梯度下降学习,初始化为全 0。
SVD++(加入邻域影响)
Koren 在 Netflix Prize 中提出,将用户历史评分行为(隐式反馈)融入矩阵分解模型:
r̂_{ui} = μ + b_u + b_i + (p_u + |N(u)|^{-1/2} * Σ_{j∈N(u)} y_j) · q_i
其中 y_j 是物品 j 的隐式反馈向量(与 q_j 共享,令 x = q)。引入用户历史行为 N(u) 使预测更准确。
Netflix Prize 中 SVD++(F=50)的 RMSE = 0.8952,显著优于基础 LFM(RMSE = 0.9094)。
4. 加入时间信息的模型
TItemCF(时间衰减邻域模型)
BigChaos 提出:用户对近期评分物品的兴趣权重更高:
r̂_{ui}(t) = Σ_{j∈S(i,K)∩N(u)} w_{ij}(t) * (r_{uj} - μ_j)
w_{ij}(t) = w_{ij} * e^{-λ * |t_{ui} - t_{uj}|}
其中 t_{ui} - t_{uj} 是用户 u 对物品 i 和 j 的评分时间差,差值越大权重越小。
SVD 系列模型对比
| 模型 | 公式核心 | 改进点 | RMSE提升 |
|---|---|---|---|
| Funk-SVD | r̂ = p_u · q_i | 矩阵分解基础 | — |
| BiasSVD | r̂ = μ + b_u + b_i + p_u · q_i | 加入用户/物品偏置 | ~5% |
| SVD++ | 加入隐式反馈集合N(u) | 利用点击/购买等行为 | ~5% |
| TimeSVD++ | b_u(t), b_i(t) 随时间变化 | 用户兴趣漂移建模 | ~2% |
| Ensemble | 加权/Stacking融合 | Netflix Prize核心武器 | ~10%+ |
TSVD(三维矩阵分解)
对用户—物品—时间三维矩阵分解,将 BiasSVD 中的偏置项改为时间依赖:
r̂_{ui}(t) = μ(t) + b_u(t) + b_i(t) + p_u(t) · q_i
- μ(t) :全局平均分随时间的变化
- b_u(t) :用户偏置随时间的变化(反映用户评分习惯的演变)
- b_i(t) :物品偏置随时间的变化(反映物品口碑随时间的变化)
TimeSVD++(Koren,2009)
在 SVD++ 基础上引入时间效应:
r̂_{ui}(t) = μ + b_u(t) + b_i(t) + p_u(t) · q_i + 季节效应项
季节效应:以时刻 t 所在的月份建模。
TimeSVD++(F=50)的 Netflix RMSE = 0.8824 ,是所有单模型中效果最好的。
Netflix Prize 各算法 RMSE 对比
| 方法 | 参数 | RMSE |
|---|---|---|
| Global Average | — | 1.1296 |
| Item Average | — | 1.0526 |
| ItemCF | K=25 | 0.9496 |
| RSVD(Funk-SVD) | F=96 | 0.9094 |
| BiasSVD | F=96 | 0.9039 |
| SVD++ | F=50 | 0.8952 |
| TimeSVD++ | ** F=50** | ** 0.8824** |
Netflix Prize 目标 RMSE ≤ 0.8563(比基准算法 Cinematch 的 0.9525 降低 10%),最终获奖队通过模型融合达到目标。
模型融合(Ensemble)
单个模型的性能提升空间有限,模型融合是进一步降低 RMSE 的关键手段。
级联融合(Cascade)
类似 AdaBoost:在现有预测器的基础上,训练下一个预测器来最小化残差:
r̂^{(t)}_{ui} = r̂^{(t-1)}_{ui} + Δ^{(t)}_{ui}
每一轮新预测器学习之前预测器的残差:
def Predict(train, test, alpha):
total, count = {}, {}
for record in train:
gu = GetUserGroup(record.user)
gi = GetItemGroup(record.item)
# 学习残差(真实值 - 当前预测值)
AddToMat(total, gu, gi, record.vote - record.predict)
AddToMat(count, gu, gi, 1)
for record in test:
gu = GetUserGroup(record.user)
gi = GetItemGroup(record.item)
average = total[gu][gi] / (1.0 * count[gu][gi] + alpha)
record.predict += average # 累加残差预测
MovieLens 实验:对均值方法采用级联融合后,Test RMSE 从 0.9342 降至 0.9202 。
加权融合(Linear Blending)
将 K 个预测器的输出线性加权:
r̂_{ui} = Σ_k w_k * r̂^{(k)}_{ui}
为避免在同一训练集上学习权重造成过拟合,采用以下流程:
- 将训练集 A 分为 A1(大)和 A2(小,与测试集 B 生成方式一致)
- 在 A1 上分别训练 K 个预测器
- 在 A2 上用最小二乘法 学习线性融合权重 w_k
- 在完整训练集 A 上重新训练 K 个预测器,用学到的 w_k 融合,在 B 上预测
更复杂的融合方式包括神经网络融合(本质是回归问题,所有回归算法均可用)。
Netflix Prize 的模型融合经验
- 最终获奖队(AT&T 研究人员)融合了上百个不同模型
- 单模型 RMSE 最低可达约 0.88,融合后可降至 0.8563
- 不同类型模型(邻域方法 + 矩阵分解 + 时间模型)互补性强,融合收益更大
- 模型差异性(Diversity)是融合效果的关键,两个高度相似的模型融合收益有限
实践建议
- 先建立简单基准(全局均值、物品均值),逐步增加复杂度
- 矩阵分解(Funk-SVD → BiasSVD → SVD++)是单模型性能提升的主线
- 加入时间信息(TimeSVD++)通常能带来显著提升
- 模型融合是取得比赛名次的关键,但工程实现复杂度高
- 实际工业系统中,TopN 推荐比评分预测更重要(见 推荐系统概论)
详细的 TopN 推荐算法(UserCF、ItemCF、LFM)见 协同过滤算法;实时推荐的工程架构见 推荐系统工程实践。