用Python手把手实现矩阵分解推荐算法(附完整代码与数据集)
用Python手把手实现矩阵分解推荐算法(附完整代码与数据集)
推荐系统已经成为现代互联网服务的核心组件之一,从电商平台到流媒体服务,无处不在。在众多推荐算法中,矩阵分解因其简洁性和有效性而备受青睐。本文将带你从零开始,用Python实现两种主流的矩阵分解优化方法——交替最小二乘法(ALS)和随机梯度下降(SGD),并使用MovieLens数据集进行实战验证。
1. 矩阵分解基础与核心概念
矩阵分解(Matrix Factorization, MF)是协同过滤推荐系统中的一种经典技术。它的核心思想是将用户-物品评分矩阵分解为两个低维矩阵的乘积,从而发现用户和物品之间的潜在特征。
关键术语解释:
- 用户矩阵:每行代表一个用户在潜在特征空间中的表示
- 物品矩阵:每列代表一个物品在相同潜在特征空间中的表示
- 潜在因子:隐含的特征维度,通常远小于用户或物品的数量
为什么矩阵分解有效?想象一下电影推荐场景:
用户A: [动作片爱好者]
用户B: [浪漫喜剧爱好者]
电影X: [动作元素强烈]
电影Y: [浪漫元素浓厚]
即使没有明确的标签,矩阵分解也能自动学习到这些隐含特征,并预测用户对未评分电影的偏好。
注意:潜在因子数量(k)是一个超参数,需要根据数据集大小和计算资源合理选择。通常k值在10-200之间。
2. 环境准备与数据加载
在开始实现算法前,我们需要准备Python环境和数据集。以下是所需的工具和库:
# 必需库安装
pip install numpy pandas scikit-learn
我们将使用经典的MovieLens 100K数据集,它包含:
- 100,000条评分(1-5星)
- 943位用户
- 1682部电影
import numpy as np
import pandas as pd
# 加载数据集
ratings = pd.read_csv('ml-100k/u.data', sep='\t',
names=['user_id', 'item_id', 'rating', 'timestamp'])
数据预处理步骤:
- 创建用户-物品评分矩阵
- 处理缺失值(通常用平均分填充)
- 必要时进行归一化处理
# 创建评分矩阵
n_users = ratings['user_id'].nunique()
n_items = ratings['item_id'].nunique()
R = np.zeros((n_users, n_items))
for row in ratings.itertuples():
R[row.user_id-1, row.item_id-1] = row.rating
3. ALS算法实现与优化
交替最小二乘法(ALS)是矩阵分解中最常用的优化方法之一。其核心思想是固定一个矩阵,优化另一个矩阵,交替进行直到收敛。
ALS算法步骤:
- 随机初始化用户矩阵U和物品矩阵V
- 固定V,优化U
- 固定U,优化V
- 重复2-3步直到收敛或达到最大迭代次数
数学推导:
目标是最小化损失函数:
L = Σ(r_ui - u_i·v_j)^2 + λ(||U||^2 + ||V||^2)
其中λ是正则化系数,防止过拟合。
Python实现关键代码:
def als(R, k=20, max_iter=100, lambda_=0.1):
m, n = R.shape
U = np.random.rand(m, k)
V = np.random.rand(n, k)
for iter in range(max_iter):
# 固定V,优化U
for i in range(m):
V_i = V[R[i, :] > 0]
A = V_i.T @ V_i + lambda_ * np.eye(k)
b = V_i.T @ R[i, R[i, :] > 0]
U[i, :] = np.linalg.solve(A, b)
# 固定U,优化V
for j in range(n):
U_j = U[R[:, j] > 0]
A = U_j.T @ U_j + lambda_ * np.eye(k)
b = U_j.T @ R[R[:, j] > 0, j]
V[j, :] = np.linalg.solve(A, b)
# 计算当前损失
error = compute_error(R, U, V, lambda_)
if error < 0.01: # 收敛条件
break
return U, V
ALS的优点:
- 每次迭代都有闭式解,保证收敛
- 适合并行化处理
- 对稀疏矩阵友好
4. SGD算法实现与调优
随机梯度下降(SGD)是另一种常用的优化方法,特别适合大规模数据集。与ALS不同,SGD通过逐个样本更新参数,计算效率更高。
SGD算法步骤:
- 随机初始化U和V
- 随机选择一个评分样本(r_ij)
- 计算预测误差 e_ij = r_ij - u_i·v_j
- 更新u_i和v_j: u_i = u_i + γ(e_ij * v_j - λu_i) v_j = v_j + γ(e_ij * u_i - λv_j)
- 重复2-4步直到收敛
Python实现关键代码:
def sgd(R, k=20, max_iter=100, gamma=0.01, lambda_=0.1):
m, n = R.shape
U = np.random.rand(m, k)
V = np.random.rand(n, k)
# 获取所有已知评分的索引
rows, cols = np.where(R > 0)
indices = list(zip(rows, cols))
for iter in range(max_iter):
np.random.shuffle(indices)
for i, j in indices:
# 计算预测误差
prediction = np.dot(U[i, :], V[j, :])
e_ij = R[i, j] - prediction
# 更新规则
U[i, :] += gamma * (e_ij * V[j, :] - lambda_ * U[i, :])
V[j, :] += gamma * (e_ij * U[i, :] - lambda_ * V[j, :])
# 计算当前损失
error = compute_error(R, U, V, lambda_)
if error < 0.01: # 收敛条件
break
return U, V
SGD参数调优建议:
| 参数 | 推荐范围 | 影响 |
|---|---|---|
| 学习率(γ) | 0.001-0.1 | 太大导致震荡,太小收敛慢 |
| 正则化系数(λ) | 0.01-0.2 | 控制模型复杂度 |
| 潜在因子数(k) | 10-200 | 影响模型表达能力 |
5. 算法评估与实战对比
实现完两种算法后,我们需要评估它们的性能和推荐质量。常用的评估指标包括:
- 均方根误差(RMSE):衡量预测评分与实际评分的差异
- 平均绝对误差(MAE):另一种误差度量方式
- Top-N推荐准确率:评估推荐列表的质量
计算RMSE的函数:
def compute_rmse(R, U, V):
pred = U @ V.T
mask = R > 0
return np.sqrt(np.mean((pred[mask] - R[mask])**2))
在实际项目中,我们还需要考虑:
- 冷启动问题:如何处理新用户或新物品
- 可扩展性:算法在大规模数据上的表现
- 实时性:能否支持实时推荐
ALS与SGD对比实验:
# 运行两种算法
U_als, V_als = als(R, k=50, max_iter=50)
U_sgd, V_sgd = sgd(R, k=50, max_iter=50)
# 计算误差
rmse_als = compute_rmse(R, U_als, V_als)
rmse_sgd = compute_rmse(R, U_sgd, V_sgd)
print(f"ALS RMSE: {rmse_als:.4f}")
print(f"SGD RMSE: {rmse_sgd:.4f}")
典型结果对比:
| 指标 | ALS | SGD |
|---|---|---|
| RMSE | 0.92 | 0.89 |
| 训练时间 | 较长 | 较短 |
| 内存使用 | 较高 | 较低 |
6. 生产环境优化建议
将矩阵分解算法应用到实际生产环境时,还需要考虑以下优化方向:
性能优化技巧:
- 使用稀疏矩阵存储格式(如CSR)处理大型数据集
- 实现增量更新,避免每次全量训练
- 利用GPU加速矩阵运算
# 使用稀疏矩阵示例
from scipy.sparse import csr_matrix
R_sparse = csr_matrix(R)
推荐系统架构设计:
- 离线训练:定期更新用户和物品矩阵
- 近线计算:处理用户实时行为
- 在线服务:快速响应推荐请求
混合推荐策略:
- 结合基于内容的推荐
- 加入时间衰减因子
- 融合多种推荐算法结果
实际部署时,一个常见的架构是将训练好的模型导出为服务:
# 保存模型
np.save('user_matrix.npy', U)
np.save('item_matrix.npy', V)
# 加载模型进行预测
def predict_rating(user_id, item_id):
return np.dot(U[user_id], V[item_id])
7. 进阶方向与扩展阅读
掌握了基础矩阵分解后,你可以进一步探索以下高级技术:
-
带偏置的矩阵分解:
- 考虑用户和物品的偏差项
- 改进的预测公式:r̂_ui = μ + b_i + b_j + u_i·v_j
-
时间敏感的矩阵分解:
- 加入时间衰减因子
- 捕捉用户兴趣随时间的变化
-
深度学习扩展:
- 神经矩阵分解(NeuMF)
- 使用自编码器进行非线性分解
推荐阅读资源:
- Matrix Factorization Techniques for Recommender Systems (Koren et al.)
- Collaborative Filtering for Implicit Feedback Datasets (Hu et al.)
- Surprise库(https://surpriselib.com) - Python推荐系统工具包
实现一个完整的推荐系统需要考虑的远不止算法本身,还包括数据管道、AB测试、监控报警等工程实践。但矩阵分解作为推荐系统的基石之一,掌握它将为你打下坚实的基础。
更多推荐


所有评论(0)