- 人工智能
- 深度学习
- NLP
- 计算机视觉
- 强化学习
【免费下载链接】google-research
Google Research
导读
本指南围绕 Google Research 开源仓库dot_vs_learned_similarity目录展开,它是论文Neural Collaborative Filtering vs. Matrix Factorization Revisited(Rendle, Krichene, Zhang, Anderson, 2020)的官方复现代码。文章将带你完整走通两个核心实验:一是用 NCF 论文的数据集与评估协议复现经典矩阵分解(MF)基线,二是用多层感知机(MLP)逼近点积函数、检验神经网络是否真能"学到"内积式相似度。读完本文,你将掌握两个可运行的实验脚本的完整参数体系、数据生成与评测原理,以及如何用仓库自带的 Perl 工具构造超参数调优所需的留出集。
一、论文背景与仓库结构
Neural Collaborative Filtering vs. Matrix Factorization Revisited的核心论点是:此前 NCF 论文(He et al., WWW 2017)中神经协同过滤模型相对矩阵分解的显著优势,很大程度上来自不公平的实验设置——例如 MF 基线未充分调参、负采样数量不同等。该论文通过更严谨的复现表明,经过合理调参的 MF 可以达到与 NCF 相当的效果,并进一步从"表达能力"角度发问:MLP 到底能否逼近一个点积?本仓库正是这两组实验的可运行代码。
仓库目录结构如下:
- README.md:实验说明与超参数汇总(本文的骨架文档)
- mf_simple.py:实验一的 MF 模型实现
- approx_dot.py:实验二的"MLP 学习点积"实现
- create_hold_out.pl:为超参数调优构造留出集的数据切分工具
- requirements.txt:依赖声明(
argparse>=1.1、keras>=2.3.1、numpy>=1.16.4)
注意仓库仅提供代码;两个实验所需的数据集(如 MovieLens 1M)与 NCF 参考实现需要按下文说明自行准备。
二、实验一:Revisiting NCF Experiments
2.1 实验目标与依赖
实验一实现了一个带偏置的简单矩阵分解模型,直接使用 NCF 论文(He et al., WWW 2017)的数据集格式与评估协议,用于验证"MF 基线在 NCF 协议下究竟能达到多好的效果"。
运行前提:
- 需要 NCF 论文的官方参考实现代码及其数据集(公开仓库名为
neural_collaborative_filtering,该参考实现假定运行在 Python 2 运行时下),下载后将其中的数据集目录(如Data/ml-1m、Data/pinterest-20)与Dataset.py、evaluate.py等模块就位; - 将本仓库的 mf_simple.py 复制到与
Dataset、evaluate模块相同的目录下(脚本通过from Dataset import Dataset与from evaluate import evaluate_model直接复用 NCF 的加载与评测代码,见 mf_simple.py)。
2.2 模型与优化细节(源码解读)
从 mf_simple.py 的模块说明可以看出模型设计的关键点:
- 模型形式:带偏置的矩阵分解
y(u,i) = b + v_{u,1} + v_{i,1} + Σ_{f=2}^{d} v_{u,f} · v_{i,f}即全局偏置 + 用户偏置 + 物品偏置 + 高维向量的点积(第 1 维专门留给偏置,见 mf_simple.py 中embedding_dim - 1的传参); - 损失函数:Logistic 损失(隐式反馈的二分类视角);
- 优化算法:随机梯度下降(SGD),每个样本执行一步更新(见 mf_simple.py);
- 负采样:训练中为每个正样本随机采样
--negatives个负样本(见 mf_simple.py,负样本是均匀随机抽取的物品,不强制排除已出现在训练集中的物品,注释明确说明这种情况"应该是无害的"); - 目标函数(与 NCF 论文一致):
argmin_V Σ_{(u,i)∈S} [ ln(1+exp(-y(u,i))) + #neg/|I| · Σ_{j∈I} ln(1+exp(y(u,j))) + reg · ||V||₂² ] - 参数初始化:嵌入向量按均值为 0、标准差为
--stddev的正态分布初始化; - 评估协议:完全沿用 He et al. WWW 2017 的协议——对每个测试用户,从其测试正样本与 100 个负样本(
testNegatives)中计算HR@10与NDCG@10(见 mf_simple.py 的evaluate封装)。
2.3 最终实验的运行命令
README 中给出图 2 各曲线所用的最终超参数,可直接复现:
MovieLens 1M:
python mf_simple.py --data Data/ml-1m --epochs 256 --embedding_dim 16 \ --regularization 0.005 --negatives 8 --learning_rate 0.002 --stddev 0.1Pinterest-20:
python mf_simple.py --data Data/pinterest-20 --epochs 256 --embedding_dim 16 \ --regularization 0.01 --negatives 10 --learning_rate 0.007 --stddev 0.1关于实验设置的几个事实(来自 README):
- 论文将嵌入维度从 16 变化到 192 以绘制学习曲线,维度越大训练越久,但效果越好;
- 每个配置重复 8 次实验,报告的是平均值;
- 代码刻意不追求运行速度而是追求简单可读,因此不适合直接用于大规模生产训练。
2.4 命令行参数一览
下表整理了 mf_simple.py 中全部命令行参数及其默认值,便于自定义实验:
| 参数 | 类型 | 默认值 | 含义 |
|---|---|---|---|
--data | str | Data/ml-1m | 数据集路径(NCF 仓库的 Data 目录) |
--epochs | int | 128 | 训练轮数 |
--embedding_dim | int | 8 | 嵌入维度,第 1 维用作偏置,实际模型维度为embedding_dim - 1 |
--regularization | float | 0.0 | 用户/物品嵌入的 L2 正则系数 |
--negatives | int | 8 | 每个正样本对应的随机负样本数 |
--learning_rate | float | 0.001 | SGD 步长 |
--stddev | float | 0.1 | 嵌入初始化的标准差 |
脚本在每个 epoch 结束后都会打印HR与NDCG(K=10),训练曲线可以方便地观察收敛情况(见 mf_simple.py)。
2.5 超参数调优:构造留出集
README 强调:上述最终超参数是在**留出集(holdout set)**上调优得到的。留出集可以通过仓库自带的 Perl 脚本 create_hold_out.pl 构造:
./create_hold_out.pl --in Data/ml-1m.train.rating \ --out_train Data/ml-1m.holdout.train.rating \ --out_test Data/ml-1m.holdout.test.rating \ --out_test_neg Data/ml-1m.holdout.test.negative该脚本的工作机制(见 create_hold_out.pl 的头部注释):
- 输入数据格式为每行一条评分记录
<userid> <itemid> [...],且按用户排序;脚本为每个用户取出第一条记录放入测试集(因数据集按时间逆序排列,文件中的第一条记录即该用户最近的一次交互,模拟"预测下一次交互"的时序语义); - 生成三个输出文件:
--out_train:从原数据中剔除每个用户首条记录后的训练集;--out_test:每个用户的首条记录,格式与训练集相同;--out_test_neg:为每个测试样本生成100 个负样本,每行格式为(<userid>, <itemid>)后跟制表符分隔的负物品 id 列表;负样本从全部物品中均匀采样,且排除该用户在训练集与测试集中出现过的物品(见 create_hold_out.pl);
- 输出数据格式与 He et al. WWW 2017 论文完全一致,可直接被 NCF 的评测代码读取。
更多实验细节见论文附录 A。
三、实验二:Learning a Dot Product with MLP
3.1 实验动机与运行命令
第二个实验直接回答论文的核心理论问题:一个多层感知机能否学会用点积来度量两个嵌入向量的相似度?论文通过构造"标签由真实点积 + 噪声"构成的合成数据,训练 MLP 拟合点积,并对比其 RMSE 与真实点积模型、平凡模型(恒预测 0)的差距。
图 3 各曲线由以下命令生成(README 原文):
python approx_dot.py --embedding_dim {16,32,64,128} \ --num_users {4000,8000,16000,32000,64000,128000} \ --num_items {4000,8000,16000,32000,64000,128000} \ --first_layer_mult {1,2,4} --learning_rate 0.001实验设置要点:
- 图 3 的三张子图分别对应
first_layer_mult取{1,2,4}; - 纵轴为用户数
{4000,8000,16000,32000,64000,128000},且设置num_items = num_users; - 每个配置重复 5 次实验,报告平均值。
3.2 合成数据生成机制(源码解读)
approx_dot.py 的GenerateData函数按如下方式构造数据:
- 每个样本
x是维度为2 * embedding_dim的实值向量,即用户嵌入与物品嵌入的拼接,标签y为该对的相似度; - 数据生成时保证两类基线 RMSE 已知(见 approx_dot.py 的常量):完美模型(真实点积)的 RMSE 为
rmse_best = 0.85,恒预测 0 的平凡模型 RMSE 为rmse_naive = 1.13; - 噪声标准差直接取
sd_noise = rmse_best,嵌入分布标准差则按sd_emb = sqrt(sqrt((rmse_naive² - rmse_best²) / emb_dim))反推(见 approx_dot.py),从而让数据在统计意义上精确匹配上述两个 RMSE 目标; - 生成三份数据集:
- train:从固定的
num_users × num_items嵌入集合中采样用户-物品对; - test:与 train 同分布,但样本与训练集互不重叠;
- fresh:使用全新生成的嵌入(不受 train/test 固定嵌入集合限制,默认 100000 个样本),用于检验模型的外推能力——这是本实验最关键的部分,因为真实推荐系统会遇到训练中未见过的新用户/新物品;
- train:从固定的
- 主流程按"每个用户平均 100 个物品交互"估计总样本量,并按 90%/10% 切分 train/test(见 approx_dot.py)。
3.3 基线评测与 MLP 训练
ComputeRMSE(见 approx_dot.py)在同一批数据上计算两个基线 RMSE:恒预测 0 的平凡模型 RMSE、真实点积模型的 RMSE。脚本运行时会先打印这两组基线,再打印 MLP 的 train/test/fresh RMSE,三者的差距直接回答了"MLP 离点积有多远"。
MLP 架构由TrainMLP实现(见 approx_dot.py):
- 输入先经过
Flatten(形状(2, embedding_dim))展平; - 三个隐藏层,宽度分别为
first_layer_mult * 2*emb_dim、first_layer_mult * emb_dim、first_layer_mult * emb_dim / 2,激活函数为 ReLU(论文建议的设定); - 输出层为 1 个线性单元;
- 损失为均方误差(MSE),优化器为 Adam,学习率取
--learning_rate(lr=learning_rate是 Keras 2.x 的 API 写法,复现时建议使用与论文时代一致的 Keras 2.3.x 及以上版本)。
3.4 命令行参数一览
下表整理了 approx_dot.py 的全部参数:
| 参数 | 类型 | 默认值 | 含义 |
|---|---|---|---|
--embedding_dim | int | 64 | 嵌入维度 |
--num_users | int | 100000 | 用户数 |
--num_items | int | 100000 | 物品数 |
--first_layer_mult | int | 1 | 首层宽度倍数,首层尺寸为2 * emb_dim * first_layer_mult |
--epochs | int | 32 | 训练轮数 |
--batch_size | int | 256 | 批大小 |
--learning_rate | float | 0.001 | Adam 学习率 |
脚本结束时会输出一行以制表符分隔的汇总统计(embedding_dim、num_users、num_items及三组数据集上 MLP/平凡模型/点积模型的 RMSE,见 approx_dot.py),便于批量实验后直接收集数据绘图。
四、复现环境与注意事项
- 依赖安装:按 requirements.txt 安装即可,核心依赖为
argparse、keras>=2.3.1、numpy>=1.16.4;实验二的approx_dot.py依赖 TensorFlow/Keras 2.x,其Adam(lr=...)写法与新版 Keras 3 不兼容,请按脚本年代选择环境; - 实验一的数据与模块:
mf_simple.py直接 import NCF 参考实现中的Dataset与evaluate_model,请确保这些模块与数据集位于同一搜索路径,且 Python 运行时与 NCF 参考实现兼容(README 注明其假定为 Python 2 运行时,复现时需据此搭建环境); - 实验成本:README 明确说明实验一代码以简洁为目标、未经速度优化,嵌入维度较大(如 192)或数据规模较大时训练耗时较长,建议先在较小配置上验证脚本可运行,再扩展到论文规模;
- 结果统计口径:两组的论文结果均为多次重复(8 次 / 5 次)的均值,单次运行存在随机波动,复现时建议保持相同的重复次数并取平均。
五、总结
dot_vs_learned_similarity为"神经协同过滤 vs 矩阵分解"之争提供了一个严谨、可运行的实证工具链:mf_simple.py让你在 NCF 完全一致的协议下重新审视 MF 基线的真实水平,approx_dot.py则把问题抽象为"MLP 能否逼近点积"这一可量化的合成任务,并用 train/test/fresh 三组 RMSE 清晰刻画了神经网络的拟合与外推能力。结合 create_hold_out.pl 的留出集构造工具,这套代码既可用于复现论文图 2、图 3 的关键结论,也可作为后续推荐模型对比实验的标准化基线。
- 人工智能
- 深度学习
- NLP
- 计算机视觉
- 强化学习
【免费下载链接】google-research
Google Research
相关推荐
矩阵力量Book4_Power-of-Matrix:从矩阵分解到深度学习优化
矩阵力量Book4_Power of Matrix:从矩阵分解到深度学习优化 你是否还在为高维数据处理烦恼?是否想知道机器学习模型如何高效提取特征?本文将带你通
文档教程机器学习学术论文复现终极指南:从Jupyter Notebook到研究论文
机器学习学术论文复现终极指南:从Jupyter Notebook到研究论文 在机器学习领域,学术论文的复现是验证研究成果、推动技术进步的关键环节。GitHub
教程机器学习Caffe 卷积实现解析:从 im2col 归约到 BLAS/GPU 矩阵乘法
Caffe 卷积实现解析:从 im2col 归约到 BLAS/GPU 矩阵乘法 Caffe 处理卷积的核心策略,是把卷积运算整体"归约"为一次矩阵 矩阵乘法(G
深度学习计算机视觉
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考