基于creme-ml的推荐系统矩阵分解技术详解(第一部分)
river 项目地址: https://gitcode.com/gh_mirrors/river12/river
推荐系统与矩阵分解概述
推荐系统是现代互联网应用中不可或缺的核心组件,它通过分析用户历史行为数据,预测用户可能感兴趣的物品或内容。典型的应用场景包括电商平台的产品推荐、音乐服务的歌曲推荐以及社交媒体的内容推荐等。
在推荐系统领域,**矩阵分解(Matrix Factorization, MF)**是一类经典的协同过滤算法,它源于奇异值分解(SVD)技术。矩阵分解的强大之处在于它能够高效地建模高基数分类变量之间的交互关系。这项技术在2006年Netflix推荐系统竞赛中大放异彩,随后衍生出多种改进版本。
用户-物品矩阵表示
推荐系统的核心问题可以抽象为一个用户-物品矩阵:
$$ \begin{matrix} & \begin{matrix} _1 & _\cdots & _\cdots & _\cdots & _I \end{matrix} \ \begin{matrix} _1 \ _\vdots \ _\vdots \ _\vdots \ _U \end{matrix} & \begin{bmatrix} {\color{Red} ?} & 2 & \cdots & {\color{Red} ?} & {\color{Red} ?} \ {\color{Red} ?} & {\color{Red} ?} & \cdots & {\color{Red} ?} & 4.5 \ \vdots & \ddots & \ddots & \ddots & \vdots \ 3 & {\color{Red} ?} & \cdots & {\color{Red} ?} & {\color{Red} ?} \ {\color{Red} ?} & {\color{Red} ?} & \cdots & 5 & {\color{Red} ?} \end{bmatrix} \end{matrix} $$
其中U和I分别表示系统中的用户数和物品数,矩阵中的每个元素代表用户对物品的偏好程度(如评分、点赞等)。由于用户和物品数量庞大而观测数据有限,这类矩阵通常非常稀疏(填充率通常不到1%)。
矩阵分解核心思想
矩阵分解的基本假设是:用户和物品都可以被表示为低维潜在空间中的向量(称为潜在因子),用户对物品的偏好可以通过这些向量的点积来预测:
$$ \langle \mathbf{v}u, \mathbf{v}i \rangle = \sum{f=1}^{k} \mathbf{v}{u, f} \cdot \mathbf{v}_{i, f} $$
其中k是潜在因子的数量,且k << U, I。这些潜在因子可以理解为物品的各种特征维度,以及用户对这些特征的偏好程度。
实践案例:MovieLens电影推荐
我们将使用creme-ml库在MovieLens 100K数据集上实现不同的矩阵分解算法。该数据集包含用户对电影的1-5星评分,以及用户和电影的各种元数据。
1. 朴素预测基准
作为基准,我们首先实现一个简单的均值预测器:
from river import dummy
from river import stats
model = dummy.StatisticRegressor(stats.Mean())
评估结果显示MAE约为0.942,这将成为我们改进的基准。
2. 基线模型(Baseline Model)
基线模型在全局均值的基础上增加了用户偏置和物品偏置项:
$$ \hat{y}(x) = \bar{y} + bu_{u} + bi_{i} $$
实现代码如下:
from river import preprocessing
from river import optim
from river import reco
baseline_params = {
'optimizer': optim.SGD(0.025),
'l2': 0.,
'initializer': optim.initializers.Zeros()
}
model = preprocessing.PredClipper(
regressor=reco.Baseline(**baseline_params),
y_min=1,
y_max=5
)
该模型将MAE降低到了0.754,显著优于朴素预测。
3. Funk矩阵分解(FunkMF)
FunkMF是矩阵分解的最基本形式,仅学习用户和物品的潜在表示:
$$ \hat{y}(x) = \langle \mathbf{v}_u, \mathbf{v}_i \rangle $$
实现代码:
funk_mf_params = {
'n_factors': 10,
'optimizer': optim.SGD(0.05),
'l2': 0.1,
'initializer': optim.initializers.Normal(mu=0., sigma=0.1, seed=73)
}
model = preprocessing.PredClipper(
regressor=reco.FunkMF(**funk_mf_params),
y_min=1,
y_max=5
)
单独使用时,FunkMF表现与朴素预测相当(MAE≈0.944),但它为更复杂的模型提供了基础组件。
4. 带偏置的矩阵分解(BiasedMF)
BiasedMF结合了基线模型和FunkMF的优点:
$$ \hat{y}(x) = \bar{y} + bu_{u} + bi_{i} + \langle \mathbf{v}_u, \mathbf{v}_i \rangle $$
实现代码:
biased_mf_params = {
'n_factors': 10,
'bias_optimizer': optim.SGD(0.025),
'latent_optimizer': optim.SGD(0.05),
'weight_initializer': optim.initializers.Zeros(),
'latent_initializer': optim.initializers.Normal(mu=0., sigma=0.1, seed=73),
'l2_bias': 0.,
'l2_latent': 0.
}
model = preprocessing.PredClipper(
regressor=reco.BiasedMF(**biased_mf_params),
y_min=1,
y_max=5
)
这是目前表现最好的模型,MAE降至0.748,证明了潜在因子确实能带来额外的信息增益。
关键参数调优指南
在使用矩阵分解模型时,有几个关键参数需要特别注意:
- 潜在因子数量(n_factors): 控制模型的表达能力,值越大模型越复杂但也更容易过拟合
- 学习率(optimizer): 影响模型收敛速度和稳定性
- 正则化系数(l2): 防止过拟合的重要参数
- 初始化策略(initializer): 影响模型训练的起点和收敛性
在实际应用中,需要通过交叉验证等方法仔细调整这些参数以获得最佳性能。
总结与展望
本部分介绍了推荐系统中矩阵分解技术的基本原理和在creme-ml中的实现方法。我们看到了从简单预测到复杂模型的逐步改进过程。在后续部分中,我们将探讨更高级的因子分解机(Factorization Machines)技术,以及如何通过多轮学习提升模型性能。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考