Dot vs Learned Similarity 复现指南:从矩阵分解到 MLP 学习点积的实证研究
2026/9/20 14:46:03 网站建设 项目流程
  • 人工智能
  • 深度学习
  • NLP
  • 计算机视觉
  • 强化学习

【免费下载链接】google-research

Google Research

项目地址:https://gitcode.com/gh_mirrors/go/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.1keras>=2.3.1numpy>=1.16.4

注意仓库仅提供代码;两个实验所需的数据集(如 MovieLens 1M)与 NCF 参考实现需要按下文说明自行准备。


二、实验一:Revisiting NCF Experiments

2.1 实验目标与依赖

实验一实现了一个带偏置的简单矩阵分解模型,直接使用 NCF 论文(He et al., WWW 2017)的数据集格式与评估协议,用于验证"MF 基线在 NCF 协议下究竟能达到多好的效果"。

运行前提:

  1. 需要 NCF 论文的官方参考实现代码及其数据集(公开仓库名为neural_collaborative_filtering,该参考实现假定运行在 Python 2 运行时下),下载后将其中的数据集目录(如Data/ml-1mData/pinterest-20)与Dataset.pyevaluate.py等模块就位;
  2. 将本仓库的 mf_simple.py 复制到与Datasetevaluate模块相同的目录下(脚本通过from Dataset import Datasetfrom 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@10NDCG@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.1

Pinterest-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 中全部命令行参数及其默认值,便于自定义实验:

参数类型默认值含义
--datastrData/ml-1m数据集路径(NCF 仓库的 Data 目录)
--epochsint128训练轮数
--embedding_dimint8嵌入维度,第 1 维用作偏置,实际模型维度为embedding_dim - 1
--regularizationfloat0.0用户/物品嵌入的 L2 正则系数
--negativesint8每个正样本对应的随机负样本数
--learning_ratefloat0.001SGD 步长
--stddevfloat0.1嵌入初始化的标准差

脚本在每个 epoch 结束后都会打印HRNDCG(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 个样本),用于检验模型的外推能力——这是本实验最关键的部分,因为真实推荐系统会遇到训练中未见过的新用户/新物品;
  • 主流程按"每个用户平均 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_dimfirst_layer_mult * emb_dimfirst_layer_mult * emb_dim / 2,激活函数为 ReLU(论文建议的设定);
  • 输出层为 1 个线性单元;
  • 损失为均方误差(MSE),优化器为 Adam,学习率取--learning_ratelr=learning_rate是 Keras 2.x 的 API 写法,复现时建议使用与论文时代一致的 Keras 2.3.x 及以上版本)。

3.4 命令行参数一览

下表整理了 approx_dot.py 的全部参数:

参数类型默认值含义
--embedding_dimint64嵌入维度
--num_usersint100000用户数
--num_itemsint100000物品数
--first_layer_multint1首层宽度倍数,首层尺寸为2 * emb_dim * first_layer_mult
--epochsint32训练轮数
--batch_sizeint256批大小
--learning_ratefloat0.001Adam 学习率

脚本结束时会输出一行以制表符分隔的汇总统计(embedding_dimnum_usersnum_items及三组数据集上 MLP/平凡模型/点积模型的 RMSE,见 approx_dot.py),便于批量实验后直接收集数据绘图。


四、复现环境与注意事项

  • 依赖安装:按 requirements.txt 安装即可,核心依赖为argparsekeras>=2.3.1numpy>=1.16.4;实验二的approx_dot.py依赖 TensorFlow/Keras 2.x,其Adam(lr=...)写法与新版 Keras 3 不兼容,请按脚本年代选择环境;
  • 实验一的数据与模块mf_simple.py直接 import NCF 参考实现中的Datasetevaluate_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

项目地址:https://gitcode.com/gh_mirrors/go/google-research
点击查看免费下载

相关推荐

上一篇:social-auto-upload单元测试编写:如何为上传器编写测试用例
下一篇:Serialize-Error 项目常见问题解答

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询