《动手学深度学习》AutoRec 实战:用自动编码器构建非线性协同过滤评分预测模型
人工智能深度学习机器学习教程【免费下载链接】d2l-zh《动手学深度学习》面向中文读者、能运行、可讨论。中英文版被70多个国家的500多所大学用于教学。项目地址https://gitcode.com/GitHub_Trending/d2/d2l-zh点击查看免费下载导读AutoRec 是《动手学深度学习》d2l-zh推荐系统章节中用于评分预测的经典深度协同过滤模型。它把自动编码器AutoEncoder的编码—重构范式引入协同过滤直接用交互矩阵的行或列作为输入将非线性变换集成进评分预测流程从而弥补矩阵分解Matrix FactorizationMF这类线性模型无法刻画用户偏好中复杂非线性关系的不足。读完本文你将掌握 AutoRec 的数学模型与目标函数、基于 Gluon 的完整实现编码器/解码器/dropout/梯度掩码、适配重构任务的 RMSE 评估器重写方法以及如何在 MovieLens-100K 数据集上端到端训练并评估该模型。从矩阵分解到 AutoRec为什么需要非线性协同过滤在推荐系统章节的姊妹篇 矩阵分解 中我们把用户-物品交互矩阵 $\mathbf{R} \in \mathbb{R}^{m \times n}$ 分解为低秩的用户潜矩阵与物品潜矩阵用 $\hat{\mathbf{R}}_{ui} \mathbf{p}_u \mathbf{q}^\top_i b_u b_i$ 预测评分。这一范式在评分预测任务上表现良好但本质上仍是一个线性模型——预测分数被建模为潜因子向量的内积加偏置无法描述能够预测用户偏好的非线性复杂关系。AutoRec原论文引用自Sedhain.Menon.Sanner.ea.2015正是为解决这一缺陷而提出的基于显式评分和自动编码器架构的协同过滤模型。它利用神经网络已被证明能够逼近任意连续函数这一性质将非线性变换集成进协同过滤collaborative filteringCF增强矩阵分解的表示能力。在本仓库的推荐系统目录 contrib/chapter_recommender-systems/ 中AutoRec 与矩阵分解同属评分预测路线的经典模型两者共用同一套 MovieLens 数据加载工具与训练框架便于读者直接对比线性与非线性模型的效果差异。模型AutoRec 与标准自动编码器的异同与自动编码器相同之处AutoRec 拥有和自动编码器一样的架构输入层、隐含层、重构层输出层。自动编码器是一种可以将输入复制到输出的神经网络它能够将输入编码成隐含层通常维度更低表示。AutoRec 没有显式地将用户和物品嵌入到低维空间而是使用交互矩阵的行或列作为输入然后在输出层重构交互矩阵——这一设计使其无需nn.Embedding这类嵌入表网络结构更加简洁。与自动编码器不同之处AutoRec 专注于学习重构层的输出而不是隐含层表示。它使用一个只有部分数据的交互矩阵作为输入试图重构出完整的评分矩阵同时出于推荐的目的重构过程会在输出层中将输入层中缺失的条目补齐——这正是用自动编码器做评分预测的关键缺失评分在输出层被自动填充为预测值。AutoRec 有基于用户和基于物品两种变体。本仓库文档只详细介绍基于物品的 AutoRec输入为评分矩阵的列 $\mathbf{R}_{*i}$基于用户的 AutoRec 可以据此对称导出只需将输入换为矩阵的行。数学定义与目标函数设 $\mathbf{R}_{*i}$ 表示评分矩阵的第 $i$ 列未知评分在默认情况下设置为 0。神经网络定义如下$$ h(\mathbf{R}{*i}) f(\mathbf{W} \cdot g(\mathbf{V} \mathbf{R}{*i} \mu) b) $$其中$f(\cdot)$ 和 $g(\cdot)$ 表示激活函数$\mathbf{W}$ 和 $\mathbf{V}$ 表示权重矩阵$\mu$ 和 $b$ 表示偏置。使用 $h(\cdot)$ 表示 AutoRec 的整个网络因此 $h(\mathbf{R}_{*i})$ 表示评分矩阵第 $i$ 列的重构结果。训练目标是降低重构误差目标函数如下$$ \underset{\mathbf{W},\mathbf{V},\mu, b}{\mathrm{argmin}} \sum_{i1}^M{\parallel \mathbf{R}{*i} - h(\mathbf{R}{*i})\parallel_{\mathcal{O}}^2} \lambda(| \mathbf{W} |_F^2 | \mathbf{V}|_F^2) $$其中$| \cdot |_{\mathcal{O}}$ 表示在训练过程中只考虑已知评分。这也就是说只有和已知输入相关联的权重矩阵才会在反向传播的过程中得到更新第二项 $\lambda(| \mathbf{W} |_F^2 | \mathbf{V}|_F^2)$ 为 Frobenius 范数形式的权重衰减正则项用于抑制过拟合。导入本节所需的依赖from d2l import mxnet as d2l from mxnet import autograd, gluon, np, npx from mxnet.gluon import nn import mxnet as mx import sys npx.set_np()模型实现编码器 dropout 解码器一个典型的自动编码器由编码器和解码器两部分组成编码器将输入映射为隐含层表示解码器则将隐含层表示映射到重构层。按照这一做法我们使用全连接层构建编码器和解码器。在默认情况下编码器的激活函数为sigmoid而解码器不使用激活函数对应公式中的 $f$ 为恒等映射$g$ 为 sigmoid。为了减轻过拟合在编码器后添加了 dropout 层同时通过掩码屏蔽未定输入值的梯度使得只有已确定的评分才能帮助模型学习。class AutoRec(nn.Block): def __init__(self, num_hidden, num_users, dropout0.05): super(AutoRec, self).__init__() self.encoder nn.Dense(num_hidden, activationsigmoid, use_biasTrue) self.decoder nn.Dense(num_users, use_biasTrue) self.dropout nn.Dropout(dropout) def forward(self, input): hidden self.dropout(self.encoder(input)) pred self.decoder(hidden) if autograd.is_training(): # Mask the gradient during training return pred * np.sign(input) else: return pred几个实现细节值得展开说明输入即列向量由于本文采用基于物品的变体输入是交互矩阵的一列某个物品在所有用户上的评分向量因此解码器的输出维度为num_users与输入形状一致。梯度掩码Mask the gradient在训练阶段pred * np.sign(input)将输入为 0 的位置未知评分对应的输出强制置零。这样反向传播时这些位置的梯度为 0只有已知评分对应的权重会被更新精确对应公式中 $| \cdot |_{\mathcal{O}}$ 的含义在预测非训练阶段则直接返回完整重构输出缺失条目被补齐为预测评分。dropout 位置dropout 加在编码器输出与解码器输入之间是抑制过拟合的常用正则手段默认概率dropout0.05。重新实现评估器面向重构任务的 RMSE由于 AutoRec 的输入和输出形态都与矩阵分解不同矩阵分解按用户-物品对逐条预测AutoRec 则一次重构整列评分为了继续使用 RMSE 作为评估指标需要重新实现评估函数先在测试交互矩阵上跑出全部重构结果再与真实评分比较且只统计已知评分位置。def evaluator(network, inter_matrix, test_data, ctx): scores [] for values in inter_matrix: feat gluon.utils.split_and_load(values, ctx, even_splitFalse) scores.extend([network(i).asnumpy() for i in feat]) recons np.array([item for sublist in scores for item in sublist]) # Calculate the test RMSE rmse np.sqrt(np.sum(np.square(test_data - np.sign(test_data) * recons)) / np.sum(np.sign(test_data))) return float(rmse)要点gluon.utils.split_and_load(values, ctx, even_splitFalse)将数据按可用设备CPU/GPU切分实现多设备推理预测时网络返回完整重构未掩码用np.sign(test_data)提取已知评分的位置参与误差计算分母np.sum(np.sign(test_data))即已知评分的个数从而得到仅在已知评分上统计的测试 RMSE与训练目标 $| \cdot |_{\mathcal{O}}$ 保持一致。训练和评估模型MovieLens-100K 端到端实战数据准备链路AutoRec 复用了推荐系统章节统一的数据工具链定义详见 movielens.md通用工具函数位于 d2l/mxnet.pyd2l.read_data_ml100k()通过d2l.download_extract(ml-100k)下载并解压 MovieLens-100K 数据集读取u.data制表符分隔的user_id / item_id / rating / timestamp四列返回 DataFrame 以及去重后的用户数、物品数d2l.split_data_ml100k(df, num_users, num_items)默认以随机模式按 9:1 切分训练/测试集d2l.load_data_ml100k(...)在feedbackexplicit模式下构建形状为(num_items, num_users)的显式评分矩阵inter行索引为物品、列索引为用户未知评分置 0——这正是 AutoRec 列输入的来源。ctx d2l.try_all_gpus() # Load the MovieLens 100K dataset df, num_users, num_items d2l.read_data_ml100k() train_data, test_data d2l.split_data_ml100k(df, num_users, num_items) _, _, _, train_inter_mat d2l.load_data_ml100k(train_data, num_users, num_items) _, _, _, test_inter_mat d2l.load_data_ml100k(test_data, num_users, num_items) train_iter gluon.data.DataLoader(train_inter_mat, shuffleTrue, last_batchrollover, batch_size256, num_workersd2l.get_dataloader_workers()) test_iter gluon.data.DataLoader(np.array(train_inter_mat), shuffleFalse, last_batchkeep, batch_size1024, num_workersd2l.get_dataloader_workers())训练配置与循环# Model initialization, training, and evaluation net AutoRec(500, num_users) net.initialize(ctxctx, force_reinitTrue, initmx.init.Normal(0.01)) lr, num_epochs, wd, optimizer 0.002, 25, 1e-5, adam loss gluon.loss.L2Loss() trainer gluon.Trainer(net.collect_params(), optimizer, {learning_rate: lr, wd: wd}) d2l.train_recsys_rating(net, train_iter, test_iter, loss, trainer, num_epochs, ctx, evaluator, inter_mattest_inter_mat)关键配置与它们背后的工程含义配置项取值作用说明num_hidden500隐含层维度控制编码表示容量对应公式中的编码矩阵 $\mathbf{V}$ 的输出维度dropout0.05类默认值编码器输出处的随机丢弃概率配合wd1e-5双重抗过拟合lr/optimizer0.002 /adamAdam 优化器学习率Adam 适合稀疏、带噪声的评分数据num_epochs25训练轮数动画曲线会同时绘制训练损失与测试 RMSEwd1e-5权重衰减系数对应目标函数中的 $\lambda$lossgluon.loss.L2Loss()均方误差损失对应重构误差项 $| \mathbf{R}{*i} - h(\mathbf{R}{*i})|^2$last_batch训练rollover/ 测试keep训练时不足一批的样本滚动到下一个 epoch测试时保留剩余批次不丢弃这里调用的训练循环d2l.train_recsys_rating定义在 mf.md矩阵分解一节其签名支持**kwargs透传当传入inter_mat时会以evaluator(net, test_iter, kwargs[inter_mat], ctx_list)的形式调用本节重写的评估器从而自动适配 AutoRec 的整矩阵重构评估方式内部采用autograd.record()记录计算图、按批累加损失并通过trainer.step()更新参数同时用动画实时展示训练损失与测试 RMSE 的收敛曲线。实验结果结论文档明确记载在该训练流程下AutoRec 在测试集上的 RMSE 低于矩阵分解模型这直接验证了神经网络非线性在评分预测任务上的有效性。作为对照矩阵分解模型在相同数据上的训练配置为潜因子维度 30、num_epochs20详见 mf.md读者可据此复现两者并自行对比。小结我们可以使用自动编码器构建矩阵分解算法同时还可以在其中整合非线性层和 dropout 正则化层——非线性变换显著增强了模型对复杂用户偏好的表示能力。MovieLens-100K 数据集上的实验表明自动编码器AutoRec的性能优于矩阵分解模型。工程上AutoRec 的实现有三处关键设计编码器/解码器全连接架构、编码器后的 dropout 正则、训练期梯度掩码pred * np.sign(input)三者共同保证了模型在稀疏评分矩阵上稳定收敛。练习修改自动编码器的隐含层维度如 500 → 100 / 1000观察模型性能的变化思考隐含层容量与过拟合的关系。尝试添加更多的隐含层如将单层编码器改为两层。这对提高模型的性能有帮助吗可以找到更好的编码器激活函数和解码器激活函数吗例如将编码器换为tanh、relu或为解码器引入激活注意与损失函数的匹配。延伸阅读数据加载与分割的完整实现movielens.md线性基线模型与统一训练循环train_recsys_ratingmf.md推荐系统章节总览contrib/chapter_recommender-systems/index.md通用工具函数download_extract、try_all_gpus、get_dataloader_workers等d2l/mxnet.py赞分享人工智能深度学习机器学习教程【免费下载链接】d2l-zh《动手学深度学习》面向中文读者、能运行、可讨论。中英文版被70多个国家的500多所大学用于教学。项目地址https://gitcode.com/GitHub_Trending/d2/d2l-zh点击查看免费下载相关推荐如何私有化部署HabiticaDocker Compose与Kubernetes完整上线指南如何私有化部署HabiticaDocker Compose与Kubernetes完整上线指南 Habitica 是一款把目标管理做成角色扮演游戏的开源习惯追踪后端前端《动手学深度学习》序列到序列学习seq2seq实战RNN 编码器—解码器的原理、实现与 BLEU 评估《动手学深度学习》序列到序列学习seq2seq实战RNN 编码器—解码器的原理、实现与 BLEU 评估 序列到序列sequence to sequenc人工智能深度学习机器学习教程合规内置:DeskcommCRM如何把LGPD巴西数据保护要求写进产品设计合规内置:DeskcommCRM如何把LGPD巴西数据保护要求写进产品设计 DeskcommCRM 是一款开源、可自托管的 AI 销售操作系统CRM内置后端前端企业应用人工智能AI 应用AI AgentRAG即时通讯上一篇Dendron 递归笔记引用Recursive Note Refs深度解析从自引用语法到三层嵌套限制的源码实现下一篇go-echarts与Beego框架结合企业级应用开发创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →