
TensorFlow 官方推荐模型实战official/recommendation 中 NCF 框架与 NeuMF 模型的完整解析【免费下载链接】modelsModels and examples built with TensorFlow项目地址: https://gitcode.com/GitHub_Trending/mode/models在推荐系统领域如何用一个神经网络统一地建模用户-物品交互是协同过滤Collaborative Filtering研究的核心问题之一。本文基于当前仓库 official/recommendation/README.md 的完整内容结合 neumf_model.py、movielens.py、ncf_keras_main.py 等源码实现系统讲解 NCFNeural Collaborative Filtering神经协同过滤框架下 NeuMF 模型的架构细节、MovieLens 数据集的下载与预处理流程、训练/评估的完整命令与全部关键超参数以及 Hit RatioHR与 NDCG 评估协议的底层计算逻辑。读完后你可以完整复现从原始数据下载、格式规整化、模型训练到 HR/NDCG 指标评估的全链路。一、NCF 框架与 NeuMF 模型从内积到神经网络的协同过滤1.1 NCF 框架的核心思想如 README 所述该模块实现了论文 Neural Collaborative FilteringarXiv:1708.05031提出的 NCF 框架其中最具代表性的实例化模型是NeuMFNeural Matrix Factorization神经矩阵分解。与传统矩阵分解模型MF不同NCF不使用用户隐特征向量与物品隐特征向量的内积来建模交互而是用一个多层感知机MLP替换内积运算从而能从数据中学习一个任意的用户-物品交互函数。NCF 框架包含两个经典实例化实例建模方式特点GMFGeneralized Matrix Factorization广义矩阵分解线性核element-wise product保留 MF 的线性结构计算高效MLPMulti-Layer Perceptron非线性核从数据中学习交互函数表达力强可拟合任意交互关系NeuMF 是 GMF 与 MLP 的融合模型它让 GMF 和 MLP 各自学习独立的隐嵌入并将两者最后一层的输出拼接起来以同时利用 MF 的线性优势和 MLP 的非线性优势更好地建模复杂的用户-物品交互。代码库中常用缩写与 README 保持一致NCF: Neural Collaborative FilteringNeuMF: Neural Matrix FactorizationGMF: Generalized Matrix FactorizationMLP: Multi-Layer PerceptronHR: Hit Ratio命中率NDCG: Normalized Discounted Cumulative Gain归一化折损累积增益ml-1m / ml-20m: MovieLens 1 百万 / 2 千万评分数据集1.2 源码级模型结构一张共享嵌入表切分出 GMF 与 MLP 两个分支neumf_model.py 中的construct_model函数完整定义了 NeuMF 的网络结构值得逐段精读1共享嵌入表 切片。源码注释指出把 MF 与 MLP 两部分的嵌入存在同一张表里再按需切片实际上显著更高效。因此用户/物品嵌入的维度是mf_dim model_layers[0] // 2随后用两个 Lambda 层切分# 来自 official/recommendation/neumf_model.pyconstruct_model 核心片段 def mf_slice_fn(x): x tf.squeeze(x, [1]) return x[:, :mf_dim] # GMF 分支取前 mf_dim 维 def mlp_slice_fn(x): x tf.squeeze(x, [1]) return x[:, mf_dim:] # MLP 分支取剩余维度 embedding_user tf_keras.layers.Embedding( num_users, mf_dim model_layers[0] // 2, embeddings_initializerglorot_uniform, embeddings_regularizertf_keras.regularizers.l2(mf_regularization), input_length1, nameembedding_user)(user_input)2GMF 分支对用户、物品的 MF 隐向量做逐元素相乘tf_keras.layers.multiply这正是论文中广义矩阵分解的线性核MLP 分支将用户、物品的 MLP 隐向量拼接concatenate后依次过若干带 ReLU 激活的Dense层层宽由--layers指定如默认64,32,16,8每层独立 L2 正则系数由--mlp_regularization指定。3融合与输出两个分支的输出拼接后经最后一个Dense(1, activationNone)层产生 logitpredict_vector tf_keras.layers.concatenate([mf_vector, mlp_vector]) logits tf_keras.layers.Dense(1, activationNone, kernel_initializerlecun_uniform, namemovielens.RATING_COLUMN)(predict_vector)4sigmoid 技巧ncf_common.py 中的convert_to_softmax_logits会把 logits 与一列 0 拼成两列softmax([0, logit])的后一列概率在数学上等价于 sigmoid(logit)。这样即可用一个二分类形式的 softmax 交叉熵SparseCategoricalCrossentropy来训练点预测式的推荐模型这也是 ncf_keras_main.py 中LossLayer采用SparseCategoricalCrossentropy(from_logitsTrue)的原因。5一个工程细节neumf_model.sparse_to_dense_grads会把IndexedSlices稀疏梯度显式转成稠密张量。源码注释解释对 NeuMF 这种小规模的嵌入表Adam 优化器应用稠密梯度比稀疏梯度更快。6训练分支Estimator 形式neumf_model_fn中 TRAIN 模式使用AdamOptimizer(learning_rate, beta1, beta2, epsilon)TPU 场景下用CrossShardOptimizer包装EVAL 模式则走_get_estimator_spec_with_metrics计算 HR/NDCG见第五节。二、数据集MovieLens ml-1m 与 ml-20m2.1 两个数据集的规格模型训练与评估使用 GroupLens 的 MovieLens 数据集具体为ml-1m包含 2000 年加入 MovieLens 的6,040 个用户对约3,706 部电影打出的1,000,209 条匿名评分全部评分存放在无表头文件的ratings.dat中格式为UserID::MovieID::Rating::TimestampUserIDs 范围 1 ~ 6040MovieIDs 范围 1 ~ 3952评分为 5 星制仅整星。ml-20m包含138,493 个用户对26,744 部电影的20,000,263 条评分存放在带表头的ratings.csv中userId,movieId,rating,timestamp文件内先按 userId、再按 movieId 排序评分为 5 星制允许半星0.5 ~ 5.0。两个数据集中timestamp 均为自 1970-01-01 UTC 零点起的秒数每个用户至少有 20 条评分——这一约束正是后面预处理环节保留用户阈值MIN_NUM_RATINGS 20见 constants.py的依据。2.2 下载与格式规整化python movielens.pymovielens.py 负责从 GroupLens 官方站点下载数据集并做格式规整化ml-1m 的::分隔dat文件与 ml-20m 的逗号分隔csv文件会被统一转换为列名一致的ratings.csvuser_id,item_id,rating,timestamp与movies.csvitem_id,titles,genrespython movielens.py参数说明默认值--data_dir下载与保存预处理数据的目录/tmp/movielens-data/--dataset要下载并预处理的数据集名可选ml-1m、ml-20m默认ml-1m在 ncf_common.py 的set_defaults中设定movielens.py本身未指定时会下载全部数据集可使用--help或-h查看完整参数列表。源码实现上_regularize_1m_dataset 与 _regularize_20m_dataset 分别调用_transform_csv完成分隔符转换与表头补齐下载具有幂等性——若目标目录中ml-*.zip、ratings.csv、movies.csv三个文件齐全则直接跳过见 _download_and_clean。注意沿用 README 的提示ml-20m 的评分文件约 500 MB数据预处理大约需要 2 分钟。两个数据集下载后会被强制转换为统一格式后续所有代码只依赖统一格式。movielens.py 还定义了两个数据集的用户/物品规模常量DATASET_TO_NUM_USERS_AND_ITEMS {ml-1m: (6040, 3706), ml-20m: (138493, 26744)}下游预处理会用它们校验 ID 映射的完整性。2.3 训练前预处理过滤、ID 重映射与评估集切分movielens.py 完成格式统一之后真正的训练预处理发生在 data_preprocessing.py。read_dataframe完成三步核心变换用户过滤按MIN_NUM_RATINGS20 条过滤评分数不足的用户ID 零基重映射将原始 user_id / item_id 映射为 0-based 连续索引生成user_map/item_map因为 KerasEmbedding层要求索引从 0 开始排序先按 timestamp、再按 (user_id, timestamp) 用 mergesort 稳定排序——使数据可按用户切片且用户时间上最后一条评分可直接取切片末位。源码注释特别指出这种排序方式与 MLPerf 参考实现的行为一致能获得更好的评估命中率。随后 _filter_index_sort 用groupby(user).tail(1)把每个用户时间上最后一条评分留出作评估集其余作为训练正样本并将全部数组与 ID 映射 pickle 缓存到raw_data_cache_pyX.pickle版本号区分 Python2/3避免跨版本 unicode 差异导致的加载错误缓存键见 constants.py 的RAW_CACHE_FILE。负样本的生成则由 data_pipeline.py 的异步数据生产者BaseDataConstructor在后台线程中完成支持bisection二分查找随机采负与materialized预物化构建慢但每 epoch 更快两种策略可通过--constructor_type切换默认bisection。三、训练与评估ncf_keras_main.py完整指南3.1 训练命令与参数ncf_keras_main.py 是支持 TensorFlow 2.x 特性的 Keras 训练器可在 GPU 和 TPU 上训练模型python ncf_keras_main.pyREADME 列出的核心参数参数说明默认值--model_dir保存训练 checkpoint 的目录/tmp/ncf/--data_dir必须与movielens.py即 README 所指的data_download的data_dir保持一致/tmp/movielens-data/--dataset数据集名ml-1m--num_gpus训练/评估使用的 GPU 数量设为 0 表示使用 CPU13.2 模型与训练超参数全景README 提示还有其它关于模型和训练过程的参数可参考 Flags 包文档或使用--helpful查看完整列表。这些参数在 ncf_common.py 的define_ncf_flags中统一定义结合源码可得完整清单模型结构参数参数默认值源码语义--num_factors8MF 分支的嵌入维度mf_dim--layers64,32,16,8MLP 隐层宽度列表第一层宽度必须为偶数construct_model中model_layers[0] % 2 ! 0会抛ValueError因为它要与mf_dim共享一张嵌入表并按// 2平分--mf_regularization0.MF 嵌入表的 L2 正则系数--mlp_regularization0.,0.,0.,0.各 MLP 层的 L2 正则系数列表与--layers对应优化器与训练参数参数默认值说明--batch_size99000训练 batch size对应num_neg4时 19800 个正样本--eval_batch_size同 batch_size评估 batch size源码校验器要求必须 999即至少 1000 1 NUM_EVAL_NEGATIVES且必须整除设备数 × (1 999)见 ncf_input_pipeline.py--num_neg4每个正样本配对的负样本数训练期--learning_rate0.001Adam 学习率--beta1/--beta2/--epsilon0.9 / 0.999 / 1e-8Adam 超参--train_epochs2训练轮数--constructor_typebisection负样本生成策略bisection或materialized--seedNone同时给 NumPy 与 TensorFlow 设置随机种子--download_if_missingTrue数据缺失时自动调用movielens.download下载--tpuNone指定 TPUTPU 模式下必须使用自定义训练循环--keras_use_ctl且必须使用离线预生成的 TFRecord 数据在线数据生产者不支持 TPU见 ncf_input_pipeline.py 的报错逻辑评估与早停参数参数默认值说明--hr_threshold1.0配合--early_stopping使用评估 HR ≥ 阈值时停止训练。README 与源码给出的参考阈值ml-1m 论文结果为 0.68ml-20m 的 MLPerf 实现可达 0.95--early_stoppingFalse开启基于 HR 阈值的早停CustomEarlyStopping--keras_use_ctlFalse使用 Keras 自定义训练循环TPU 场景强制--ml_perfFalse切换 HR/NDCG 计算与排序行为以对齐 MLPerf 参考实现详见第五节此外还有 flags_core 提供的基础与性能类参数--model_dir、--clean、--dtype、--enable_xla等。3.3 训练流程源码剖析run_ncf 的执行链路值得梳理它能解释 README 中支持 GPU 与 TPU这句话的落地方式分布式策略distribute_utils.get_distribution_strategy(distribution_strategy, num_gpus, tpu_address)依据--distribution_strategy/--num_gpus/--tpu选择单卡、多卡或 TPU 策略输入构建若未指定--train_dataset_path走在线模式——ncf_common.get_inputs启动后台数据生产者线程并注册IncrementEpochCallback每个 epoch 结束时向前推进数据生产者的移动窗口边界因为只缓冲有限量数据若指定了预生成 TFRecord 路径则离线读文件input_meta_data提供num_users/num_items/步数模型组装_get_keras_model在neumf_model.construct_model基础上将[zeros, logits]拼成 softmax logits并按需串接两个自定义层——MetricLayer评估时调用compute_top_k_and_ndcg计算 HR与LossLayerSparseCategoricalCrossentropy以valid_point_mask为样本权重、按 batch_size 归一。注意LossLayer显式使用 float32防止 float16 下 loss 溢出两种训练路径默认路径model.compilemodel.fit配 TensorBoard 与 ModelCheckpoint 回调评估走model.evaluate命中率由返回的[eval_loss, hr_sum, hr_count]中的后两项相除得到--keras_use_ctl路径run_ncf_custom_training 用tf.function手写train_step/eval_step通过strategy.experimental_distribute_datasetstrategy.run做每副本计算与ReduceOp.SUM归约梯度同样经sparse_to_dense_grads稠密化并支持 mixed-precision 的 loss scaling。这是 TPU 的唯一可用路径源码在--tpu且未开keras_use_ctl时直接报错返回。四、负样本策略与 batch 约束NCF 采用采样式负例训练/评估相关常量集中定义在 constants.py训练每个正样本配--num_neg默认 4个随机负例样本总量 正样本数 × (1 num_neg)评估每个用户的正样本与NUM_EVAL_NEGATIVES 999个随机未交互物品一起参与排序batch 约束评估批次必须能被设备数 × 1000整除eval_batch_size % (num_devices * (1 NUM_EVAL_NEGATIVES))需为 0因为评估指标按每个用户一组 1000 个 logitreshape 计算compute_top_k_and_ndcg中tf.reshape(logits, (-1, NUM_EVAL_NEGATIVES 1))。这也是为什么--eval_batch_size的校验器下限是 1000。五、评估协议HR 与 NDCG 的精确计算compute_eval_loss_and_metrics_helper 的 docstring 完整定义了评估协议对每个测试用户将其真实交互过的物品truth item与随机抽取的 999 个未交互物品一起排序两个指标都截断到top-10TOP_K 10。HR直观衡量测试物品是否出现在 top-10 列表中NDCG通过位置折损给靠前命中更高分数。两指标逐用户计算后取平均跳过填充行。具体实现上排序用tf.argsort(..., directionDESCENDING)真实物品位置通过 one-hot 与位置向量做矩阵乘法取出——源码注释说明选择矩阵乘法而非逐元素查找是因为GPU 与 TPU 上矩阵乘法极快ndcg log(2)/log(position 2)仅命中时非零in_top_k为位置 10 的指示函数--ml_perf的去重语义开启后评估负例中的重复物品被视为只出现一次——对同一行内的重复项除一个外其余 logit 被置为 dtype 最小值logits_by_user * (1 - duplicate_mask); logits_by_user duplicate_mask * dtype.min效果等同于 MLPerf 参考实现评估时先 dedupe的行为通常得到更高的 HR/NDCG评估 loss 会按训练期的负正比num_neg4vs 评估期 999:1重加权样本保证训练/评估 loss 可比apples-to-apples comparison。评估 loss 同样用sparse_softmax_cross_entropy配合前缀 0 列的 softmax logits与训练一致。六、进阶MLPerf 基准脚本 run.shrun.sh 展示了该模块面向 MLPerf 基准的完整跑法以ml-20m为例给出了论文之外一组调优后的超参数可直接作为大规模复现的参考配置python movielens.py --data_dir ${DATA_DIR} --dataset ml-20m python ncf_keras_main.py \ --model_dir ${MODEL_DIR} \ --data_dir ${DATA_DIR} \ --dataset ml-20m \ --num_gpus 1 \ --clean \ --train_epochs 14 \ --batch_size 99000 \ --eval_batch_size 160000 \ --learning_rate 0.00382059 \ --beta1 0.783529 \ --beta2 0.909003 \ --epsilon 1.45439e-07 \ --layers 256,256,128,64 --num_factors 64 \ --hr_threshold 0.635 \ --ml_perf可以看到MLPerf 模式将 MLP 加宽为256,256,128,64、num_factors提到 64学习率与 Adam 系数均做专门调整评估 batch 提到 160000并用--hr_threshold 0.635作为早停目标脚本还演示了 GPU/TPU 设备切换--num_gpus -1/--tpu $TPU --num_gpus 0、按时间戳组织model_dir/日志、以及--seed控制随机性。该脚本默认入口为 estimator 版本传参keras时切换到ncf_keras_main.py当前仓库保留的 Keras 实现入口。七、小结与关键文件索引本节模块以 README 描述的 NCF/NeuMF 为主线完整链路为下载规整化movielens.py→预处理与负样本生产data_preprocessing.py、data_pipeline.py→模型定义neumf_model.py→Keras 训练/评估ncf_keras_main.py、ncf_input_pipeline.py→HR/NDCG 评估neumf_model.py 的compute_top_k_and_ndcg。常量集中于 constants.py基准脚本见 run.sh单测见 ncf_test.py 与 data_test.py。复现时的适用前提与限制运行入口为official/recommendation/下的 Python 脚本依赖 Pandas下载预处理与 TensorFlow 2.x tf_keras建议从仓库根目录运行以正确解析official.*包导入run.sh 中即用PYTHONPATH指回仓库根默认参数面向 ml-1m 的低成本快速验证2 个 epoch、batch 99000要逼近论文/MLPerf 指标需参考第三节完整参数表与 run.sh 的调优配置TPU 训练必须--keras_use_ctl且使用离线预生成 TFRecord 数据评估 batch size 需满足第五节给出的整除约束同目录下的 ranking/ 与 uplift/ 子模块分别面向 Criteo 点击率排序与 uplift 建模与本文 NCF/NeuMF 主题相互独立不在本文范围内。【免费下载链接】modelsModels and examples built with TensorFlow项目地址: https://gitcode.com/GitHub_Trending/mode/models创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考