☰
DeepCTR 快速上手指南:四步构建 DeepFM 点击率预估模型(Keras 与 Estimator 双路线)
2026/9/26 16:31:09 网站建设 项目流程
  • 人工智能
  • 深度学习
  • 机器学习

【免费下载链接】DeepCTR

Easy-to-use,Modular and Extendible package of deep-learning based CTR models .

项目地址:https://gitcode.com/gh_mirrors/de/DeepCTR
点击查看免费下载

本文是 DeepCTR 的实战速通教程,完整对应仓库 docs/source/Quick-Start.md 的官方快速入门路径:先讲清安装与环境兼容性要点,再分别以 Criteo 数据集演示Keras 路线(4 步完成 DeepFM 训练与预测)和Estimator + TFRecord 路线(4 步完成大规模数据训练与评估)。读完本文,你将掌握 DeepCTR 的特征列声明、稀疏/稠密特征预处理、model.fit/model.predict调用规范,以及面向分布式场景的DeepFMEstimator用法,并能结合仓库源码理解 DeepFM 的线性项 + FM 项 + DNN 项的结构化实现。

一、安装与环境兼容性

DeepCTR 定位为易用、模块化、可扩展的深度学习 CTR 模型库(见 README.md),当前仓库setup.py声明版本为0.9.4,要求python_requires=">=3.7"。它不替你锁定或安装 TensorFlow,因此正确顺序是:先安装与你 Python、NumPy、CPU/GPU、操作系统匹配的 TensorFlow,再安装 DeepCTR:

$ pip install tensorflow $ pip install deepctr

官方文档声明 deepctr 支持 Python>=3.7,并在 TensorFlow1.15与2.x上经过测试。以下几点是官方明确提示的兼容性要点,务必遵守:

  • GPU 环境:安装与你的 CUDA、cuDNN、平台组合相匹配的 TensorFlow 构建版本,然后再安装deepctr。
  • Python>=3.9的 h5py:DeepCTR 允许现代 h5py 版本(h5py>=3.7.0)。仓库 setup.py 中通过环境标记实现了自动分流:python_version>="3.9"时安装h5py>=3.7.0,否则安装h5py==2.10.0。
  • NumPy 冲突:若 TensorFlow 报告 NumPy 版本冲突,以所选 TensorFlow 版本的要求为准,例如 TensorFlow 要求时使用numpy<2。
  • Keras API 使用规范:业务代码中一律使用公开的tensorflow.kerasAPI,严禁混用tensorflow.python.keras与tensorflow.keras——tensorflow.python.*属于 TensorFlow 私有 API,混用会破坏跨版本的模型序列化及优化器/指标加载。

从源码安装

若希望基于当前仓库源码安装(便于查看源码或做二次开发):

$ git clone https://github.com/shenweichen/DeepCTR.git $ cd DeepCTR $ pip install .

安装完成后,即可进入下面的四步上手流程。

二、Keras 路线:4 步构建 DeepFM 二分类模型

DeepCTR 提供了类似tf.keras.Model的接口,你只需要把训练数据组织成「特征名 → 数组」的字典,即可用model.fit()、model.predict()完成实验。本路线以 Criteo 展示广告点击率数据(样本见 examples/criteo_sample.txt)为例,完整代码见 examples/run_classification_criteo.py。

数据格式说明:每行包含label(0/1 点击标签)、I1~I13共 13 个整数型稠密特征、C1~C26共 26 个高基数类别型稀疏特征。

Step 1:导入模型与读取数据

import pandas as pd from sklearn.preprocessing import LabelEncoder, MinMaxScaler from sklearn.model_selection import train_test_split from deepctr.models import DeepFM from deepctr.feature_column import SparseFeat, DenseFeat, get_feature_names data = pd.read_csv('./criteo_sample.txt') sparse_features = ['C' + str(i) for i in range(1, 27)] dense_features = ['I' + str(i) for i in range(1, 14)] data[sparse_features] = data[sparse_features].fillna('-1', ) data[dense_features] = data[dense_features].fillna(0, ) target = ['label']

要点说明:

  • 稀疏类别特征用字符串'-1'填充缺失值(Hash 编码与 Label 编码均可处理该哨兵值),稠密数值特征用0填充缺失。
  • sparse_features与dense_features的命名必须与 DataFrame 列名一致,后续特征列与输入字典都会用到。

Step 2:简单的特征预处理

稀疏类别特征在送入 Embedding 之前通常有两种编码方式:

  • Label Encoding(标签编码):把特征值映射为0 ~ len(#unique) - 1的连续整数,适合词表可控的中小规模场景:

    for feat in sparse_features: lbe = LabelEncoder() data[feat] = lbe.fit_transform(data[feat])
  • Hash Encoding(哈希编码):把特征值映射到固定范围(如0 ~ 9999)。它有两种落地方式:

    • 训练前做哈希:直接用HashEncoder转换列值:

      for feat in sparse_features: lbe = HashEncoder() data[feat] = lbe.transform(data[feat])
    • 训练过程中动态哈希:无需改动数据,只需在 Step 3 中为SparseFeat或VarlenSparseFeat设置use_hash=True即可。这是大数据量、高基数特征下最常用的方案。

对于稠密数值特征,工业界通常会离散化(分桶),此处采用最简的归一化处理:

mms = MinMaxScaler(feature_range=(0,1)) data[dense_features] = mms.fit_transform(data[dense_features])

Step 3:生成特征列(Feature Columns)

DeepCTR 的核心抽象是特征列:稀疏特征通过 Embedding 技术映射为稠密向量,稠密数值特征则直接拼接进全连接层的输入张量。可变长(多值)稀疏特征请使用VarlenSparseFeat(参数见 docs/source/Features.md),多值输入的完整示例见 docs/source/Examples.md,序列特征的输入约定见 docs/source/Sequence-Cookbook.md。

  • Label Encoding 配套的特征列(vocabulary_size取每个稀疏字段去重后的最大值 + 1):

    fixlen_feature_columns = [SparseFeat(feat, vocabulary_size=data[feat].max() + 1, embedding_dim=4) for i, feat in enumerate(sparse_features)] + [DenseFeat(feat, 1, ) for feat in dense_features]
  • 训练中动态哈希的特征列(输入保持原始字符串,vocabulary_size即哈希空间大小):

    fixlen_feature_columns = [SparseFeat(feat, vocabulary_size=1e6, embedding_dim=4, use_hash=True, dtype='string') # the input is string for feat in sparse_features] + [DenseFeat(feat, 1, ) for feat in dense_features]
  • 生成最终特征列与特征名列表(Linear 部分与 DNN 部分可以各自指定不同特征集,这里共用):

    dnn_feature_columns = fixlen_feature_columns linear_feature_columns = fixlen_feature_columns feature_names = get_feature_names(linear_feature_columns + dnn_feature_columns)

结合仓库源码 deepctr/feature_column.py,几个关键参数的含义与底层行为值得展开:

  • SparseFeat(name, vocabulary_size, embedding_dim=4, use_hash=False, vocabulary_path=None, dtype="int32", embeddings_initializer=None, embedding_name=None, group_name=DEFAULT_GROUP_NAME, trainable=True):
    • embedding_dim:Embedding 向量维度,默认 4;若传"auto",源码会自动计算为6 * int(pow(vocabulary_size, 0.25))。
    • embeddings_initializer:默认为RandomNormal(mean=0.0, stddev=0.0001, seed=2020)的小标准差正态初始化。
    • use_hash=True时,输入会在 Embedding 查找前被哈希到vocabulary_size大小的空间;同时dtype应设为'string',因为输入是原始字符串。
    • group_name:特征分组名,默认default_group,DeepFM 的fm_group参数会按组做 FM 交互。
    • trainable:Embedding 是否可训练。
    • vocabulary_path:指向tf.lookup.TextFileInitializer使用的 CSV 词表文件;每行两列(逗号分隔),第一列是值、第二列是键,0值被保留用于缺失键,因此哈希值需从1开始。
  • DenseFeat(name, dimension=1, dtype="float32", transform_fn=None):transform_fn可传入一个张量级转换函数,例如lambda x: (x - 3.0) / 4.2,在输入阶段完成标准化/对数变换,省去外部预处理步骤。
  • VarLenSparseFeat(sparsefeat, maxlen, combiner="mean", length_name=None, weight_name=None, weight_norm=True):combiner支持sum/mean/max三种池化;length_name指定长度字段(为None时序列中的 0 视为 padding)。
  • get_feature_names()内部调用build_input_features(),按特征列顺序为每个特征建立tf.keras.layers.Input并返回OrderedDict的 key 列表——这正是后续训练输入字典的键来源。值得注意的是,源码中的_check_sparse_feature_dtype会做一道硬校验:dtype='string'的SparseFeat必须同时use_hash=True,否则直接抛出 ValueError,提醒你先编码为整数或开启哈希。

Step 4:切分数据、训练与预测

train, test = train_test_split(data, test_size=0.2) train_model_input = {name: train[name].values for name in feature_names} test_model_input = {name: test[name].values for name in feature_names} model = DeepFM(linear_feature_columns, dnn_feature_columns, task='binary') model.compile("adam", "binary_crossentropy", metrics=['binary_crossentropy'], ) history = model.fit(train_model_input, train[target].values, batch_size=256, epochs=10, verbose=2, validation_split=0.2, ) pred_ans = model.predict(test_model_input, batch_size=256)

要点说明:

  • 模型输入是「特征名 → 数组」字典,键来自 Step 3 的feature_names,而非 DataFrame 本身。
  • task='binary'指定二分类任务(对数损失);回归场景可改用task='regression'。
  • 完整版示例 examples/run_classification_criteo.py 在预测后还会计算sklearn.metrics.log_loss与roc_auc_score,并打印test LogLoss与test AUC,可用于离线评估。

从源码理解 DeepFM 的结构

查看 deepctr/models/deepfm.py 的实现,可以看到DeepFM的最终 logit 由三部分相加而成:

  1. linear_logit = get_linear_logit(features, linear_feature_columns, ...)——LR/Wide 部分的线性 logit,带l2_reg_linear正则;
  2. fm_logit_list = [FM()(concat_func(v, axis=1)) for k, v in group_embedding_dict.items() if k in fm_group]——FM 二阶交互项,默认对default_group分组内的全部稀疏特征 Embedding 求内积和;
  3. dnn_logit——Embedding 与稠密特征拼接后经DNN(dnn_hidden_units, ...)全连接网络输出。

三者经add_func求和后,再交给PredictionLayer(task)输出最终概率。函数签名中完整暴露了可调参数:dnn_hidden_units=(256, 128, 64)(DNN 各层神经元数,可传空列表关闭 DNN 分支)、l2_reg_linear=0.00001、l2_reg_embedding=0.00001、l2_reg_dnn=0、seed=1024、dnn_dropout=0([0,1) 区间)、dnn_activation='relu'、dnn_use_bn=False(DNN 激活前是否 BatchNormalization)。仓库测试 tests/models/DeepFM_test.py 对上述各参数的组合均有覆盖验证,可作为调参参照。

三、Estimator 路线:4 步用 TFRecord 训练 DeepFM

当数据规模达到 TB 级、需要分布式训练时,Keras 接口不再适用,此时应使用 DeepCTR 提供的TensorFlow Estimator 接口(tensorflow estimator面向大规模数据与分布式训练,README 中已明确说明)。完整代码见 examples/run_estimator_tfrecord_classification.py。

Step 1:导入模型

import tensorflow as tf from deepctr.estimator.inputs import input_fn_tfrecord from deepctr.estimator.models import DeepFMEstimator

Step 2:为 Linear 部分与 DNN 部分生成特征列

Estimator 路线直接使用原生tf.feature_column,不再使用 DeepCTR 的SparseFeat/DenseFeat:

sparse_features = ['C' + str(i) for i in range(1, 27)] dense_features = ['I' + str(i) for i in range(1, 14)] dnn_feature_columns = [] linear_feature_columns = [] for i, feat in enumerate(sparse_features): dnn_feature_columns.append(tf.feature_column.embedding_column( tf.feature_column.categorical_column_with_identity(feat, 1000), 4)) linear_feature_columns.append(tf.feature_column.categorical_column_with_identity(feat, 1000)) for feat in dense_features: dnn_feature_columns.append(tf.feature_column.numeric_column(feat)) linear_feature_columns.append(tf.feature_column.numeric_column(feat))

说明:categorical_column_with_identity(feat, 1000)表示将稀疏特征视为取值在0~999的类别 ID(请确保特征值已编码在该范围内);DNN 侧再包一层embedding_column(..., 4)得到 4 维 Embedding,Linear 侧直接用类别列做线性 logit。

Step 3:用 TFRecord 格式生成训练样本

首先声明每条 TFRecord 样本的字段描述(稀疏特征存 int64、稠密特征与 label 存 float32):

feature_description = {k: tf.io.FixedLenFeature(dtype=tf.int64, shape=1) for k in sparse_features} feature_description.update( {k: tf.io.FixedLenFeature(dtype=tf.float32, shape=1) for k in dense_features}) feature_description['label'] = tf.io.FixedLenFeature(dtype=tf.float32, shape=1) train_model_input = input_fn_tfrecord('./criteo_sample.tr.tfrecords', feature_description, 'label', batch_size=256, num_epochs=1, shuffle_factor=10) test_model_input = input_fn_tfrecord('./criteo_sample.te.tfrecords', feature_description, 'label', batch_size=2 ** 14, num_epochs=1, shuffle_factor=0)

仓库 examples/gen_tfrecords.py 提供了把 DataFrame 写入 TFRecord 的参考实现:稀疏特征写入Int64List、稠密特征与 label 写入FloatList,训练/测试集分别产出criteo_sample.tr.tfrecords与criteo_sample.te.tfrecords(仓库已附带这两个文件)。

input_fn_tfrecord的实现细节(deepctr/estimator/inputs.py)值得关注,它返回一个 Estimator 标准 input_fn,内部基于tf.data管线:

  • 用tf.data.TFRecordDataset读取文件,map(_parse_examples, num_parallel_calls=8)并行解析;
  • shuffle_factor=10时按batch_size * shuffle_factor的缓冲大小打乱(shuffle_factor=0则关闭打乱,测试集即用此法保证顺序确定);
  • repeat(num_epochs).batch(batch_size)控制轮数与批大小;
  • prefetch_factor=1时预取batch_size * prefetch_factor的数据;
  • 兼容层同时处理 TF 1.x 与 2.x 的parse_single_example/make_one_shot_iteratorAPI 差异。

Step 4:训练与评估

model = DeepFMEstimator(linear_feature_columns, dnn_feature_columns, task='binary') model.train(train_model_input) eval_result = model.evaluate(test_model_input) print(eval_result)

DeepFMEstimator的完整签名(deepctr/estimator/models/deepfm.py)在 Keras 版参数之外,还针对分布式训练增加了若干专属参数:

  • model_dir:模型参数、计算图等保存目录,也可用于从已有 checkpoint 断点续训;
  • config:tf.estimator.RunConfig运行时配置(示例中用它设置了tf_random_seed=2021);
  • linear_optimizer='Ftrl':线性部分默认 FTRL 优化器;
  • dnn_optimizer='Adagrad':DNN 部分默认 Adagrad 优化器;
  • training_chief_hooks:chief worker 上执行的tf.train.SessionRunHook列表。

其内部_model_fn结构与 Keras 版一一对应:linear_logits + fm_logit + dnn_logit三路相加,再经deepctr_model_fn封装为标准tf.estimator.Estimator。完整示例 examples/run_estimator_tfrecord_classification.py 中同样以config=tf.estimator.RunConfig(tf_random_seed=2021)固定随机种子保证可复现。

四、两条路线的适用场景对比与延伸

维度Keras 路线Estimator + TFRecord 路线
特征列SparseFeat/DenseFeat/VarLenSparseFeat原生tf.feature_column
数据接入内存中的 dict / DataFrametf.data读取 TFRecord,流式训练
适用规模中小规模快速实验大规模数据、分布式训练
训练/评估model.fit/model.predictmodel.train/model.evaluate

两条路线的完整可运行代码分别位于 examples/run_classification_criteo.py(含 LogLoss/AUC 评估)与 examples/run_estimator_tfrecord_classification.py。Estimator 模型在 Kubernetes 上还可以通过 ElasticDL 框架扩展为分布式训练任务。此外,仓库还提供了 pandas 数据直接训练 Estimator 的入口input_fn_pandas(deepctr/estimator/inputs.py),以及 examples/run_estimator_pandas_classification.py 作为对应示例,可作为 TFRecord 前置处理尚未就绪时的过渡方案。

五、常见问题速查

  • 报错dtype='string' 的 SparseFeat 需要 use_hash=True:按 deepctr/feature_column.py 的校验逻辑,字符串输入必须开哈希,或先自行把特征编码为整数。
  • TensorFlow 与 NumPy 冲突:以所选 TensorFlow 版本的依赖要求为准(如numpy<2)。
  • 模型保存/加载失败:检查代码中是否混用了tensorflow.python.keras,一律改用公开的tensorflow.keras。
  • 想切换模型:把from deepctr.models import DeepFM换成WDL、DCN、xDeepFM等(完整模型清单见 docs/source/Models.rst),特征列与训练代码完全复用;Estimator 同理(如from deepctr.estimator.models import DeepFMEstimator可换为其他 Estimator 模型)。

至此,你已经完成 DeepCTR 两条主流上手指路的完整闭环:从安装兼容性、特征列设计,到 Keras 快速实验与 Estimator 规模化训练,再到对应的源码级原理。后续可继续阅读 docs/source/Features.md(特征列与模型详解)、docs/source/Examples.md(多值输入、序列模型等更多示例)与 docs/source/Sequence-Cookbook.md(序列特征输入约定),逐步上手 DIN、DIEN、BST 等序列 CTR 模型。

  • 人工智能
  • 深度学习
  • 机器学习

【免费下载链接】DeepCTR

Easy-to-use,Modular and Extendible package of deep-learning based CTR models .

项目地址:https://gitcode.com/gh_mirrors/de/DeepCTR
点击查看免费下载

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

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

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

立即咨询