基于DPIN模型的点击率预估模型

代码请参考:dpin
如果我们的代码对您有用,还请点个star啊~
在这里插入图片描述

一、模型简介

位置偏差是推荐系统有偏数据中的一个典型偏差类型,主要表现在列表中靠前的商品更容易被用户点击,而不是因为用户喜欢。传统方法认为点击率等于检查概率和关联概率的乘积,这种假设太多简单,不足以模拟位置和其他信息之间的交互。因此论文《Deep Position-wise Interaction Network for CTR Prediction》综合考虑位置、用户、上下文之间的非线性交互,提出 DPIN 模型。

本模型实现了下述论文中的 DPIN 模型:

@inproceedings{su2021detecting,
  title={Deep Position-wise Interaction Network for CTR Prediction},
  author={Jianqiang Huang, Ke Hu, Qingtao Tang, Mingjian Chen, Yi Qi, Jia Cheng, Jun Lei},
  booktitle={Proceedings of the 44th International ACM SIGIR Conference on Research and Development in Information Retrieval (SIGIR ’21)},
  year={2021}
}

二、数据准备

原文并未提供开源数据集,因此我们使用KDD Cup 2012,Track2的赛题数据,该数据集用于搜索广告系统中的CTR预估,提供了用户在腾讯搜索中的查询词、广告信息、广告相对位置、用户点击情况、用户属性信息等。与本论文所描述的场景以及试图解决的问题相吻合。

用户可以从Kaggle上获取所使用的数据集,地址如下:https://www.kaggle.com/competitions/kddcup2012-track2/data

这里我们只使用到了training.txt文件,文件大小9.87GB。总共有149639106条数据,每条数据包含如下信息:click、impression、displayURL、adID、advertiseID、depth、position、queryID、keywordID、titleID、descriptionID、userID。这里我们只选择使用如下信息:click、adID、advertiseID、position、userID。

为了与DIN模型进行对比,这里还需要为DIN模型生成相应的训练数据。DIN模型并未将广告的位置信息引入模型,因此除去position字段信息即可。具体训练数据生成方法详见datasets/preprocess.py

下面给出了一条数据的样例,并附上了介绍

# 历史浏览商品ID;历史浏览商品分类ID;历史浏览商品位置;目标商品ID;目标商品分类ID;目标商品位置;是否点击
80 71;17 50;1 1;82;56;3;0

三、运行环境

PaddlePaddle>=2.2
python 3.5/3.6/3.7
os : windows/linux/macos

四、代码结构

以下是本例的简要目录结构及说明:

├── data    # sample数据
    ├── dpin_sample.data
├── __init__.py 
├── README.md   # README
├── config.yaml   # sample数据配置
├── config_bigdata.yaml # 全量数据配置
├── dpin_reader.py  # 数据读取程序
├── net.py    # 模型核心组网(动静统一)
├── dygraph_model.py # 构建动态图

注:在阅读该示例前,建议您先了解以下内容:
paddlerec入门教程

五、快速开始

本文提供了样例数据可以供您快速体验,在任意目录下均可执行。在sign模型目录的快速执行命令如下:

cd PaddleRec/models/rank/dpin
/home/aistudio/PaddleRec/models/rank/dpin
# 进入模型目录
# cd models/rank/dpin
# 动态图训练
!python3 -u ../../../tools/trainer.py -m config.yaml
# !python3 -u ../../../tools/trainer.py -m config_bigdata.yaml # 全量数据运行config_bigdata.yaml
# 动态图预测
!python3 -u ../../../tools/infer.py -m config.yaml
# !python3 -u ../../../tools/infer.py -m config_bigdata.yaml # 全量数据运行config_bigdata.yaml
2022-09-22 15:51:32,444 - INFO - **************common.configs**********
2022-09-22 15:51:32,444 - INFO - use_gpu: False, use_xpu: False, use_npu: False, use_visual: False, train_batch_size: 32, train_data_dir: data, epochs: 5, print_interval: 100, model_save_path: output_model_dpin
2022-09-22 15:51:32,444 - INFO - **************common.configs**********
2022-09-22 15:51:32,514 - INFO - read data
2022-09-22 15:51:32,514 - INFO - reader path:dpin_reader
2022-09-22 15:51:32,636 - INFO - epoch: 0, batch_id: 0, AUC:0.425287, PAUC:0.296591, loss:0.6635903, avg_reader_cost: 0.00013 sec, avg_batch_cost: 0.00113 sec, avg_samples: 0.32000, ips: 282.07194 ins/s
2022-09-22 15:51:33,096 - INFO - epoch: 0 done, AUC: 0.450931,PAUC: 0.470497,loss:0.6540427, epoch time: 0.58 s
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/framework/io.py:729: UserWarning: The input state dict is empty, no need to save.
  warnings.warn("The input state dict is empty, no need to save.")
2022-09-22 15:51:33,118 - INFO - Already save model in output_model_dpin/0
2022-09-22 15:51:33,211 - INFO - epoch: 1, batch_id: 0, AUC:0.603448, PAUC:0.559943, loss:0.4554775, avg_reader_cost: 0.00011 sec, avg_batch_cost: 0.00085 sec, avg_samples: 0.32000, ips: 375.09636 ins/s
2022-09-22 15:51:33,663 - INFO - epoch: 1 done, AUC: 0.495775,PAUC: 0.525877,loss:0.6171015, epoch time: 0.54 s
2022-09-22 15:51:33,686 - INFO - Already save model in output_model_dpin/1
2022-09-22 15:51:33,781 - INFO - epoch: 2, batch_id: 0, AUC:0.718391, PAUC:0.612784, loss:0.42101654, avg_reader_cost: 0.00011 sec, avg_batch_cost: 0.00087 sec, avg_samples: 0.32000, ips: 367.61707 ins/s
2022-09-22 15:51:34,230 - INFO - epoch: 2 done, AUC: 0.521837,PAUC: 0.601961,loss:0.6113055, epoch time: 0.54 s
2022-09-22 15:51:34,251 - INFO - Already save model in output_model_dpin/2
2022-09-22 15:51:34,344 - INFO - epoch: 3, batch_id: 0, AUC:0.741379, PAUC:0.657955, loss:0.40957665, avg_reader_cost: 0.00011 sec, avg_batch_cost: 0.00086 sec, avg_samples: 0.32000, ips: 373.14316 ins/s
2022-09-22 15:51:34,787 - INFO - epoch: 3 done, AUC: 0.536903,PAUC: 0.629862,loss:0.60733676, epoch time: 0.54 s
2022-09-22 15:51:34,808 - INFO - Already save model in output_model_dpin/3
2022-09-22 15:51:34,903 - INFO - epoch: 4, batch_id: 0, AUC:0.758621, PAUC:0.675000, loss:0.40090746, avg_reader_cost: 0.00013 sec, avg_batch_cost: 0.00088 sec, avg_samples: 0.32000, ips: 364.97201 ins/s
2022-09-22 15:51:35,350 - INFO - epoch: 4 done, AUC: 0.550137,PAUC: 0.658018,loss:0.6044919, epoch time: 0.54 s
2022-09-22 15:51:35,370 - INFO - Already save model in output_model_dpin/4
2022-09-22 15:51:37,264 - INFO - **************common.configs**********
2022-09-22 15:51:37,264 - INFO - use_gpu: False, use_xpu: False, use_npu: False, use_visual: False, infer_batch_size: 32, test_data_dir: data, start_epoch: 0, end_epoch: 5, print_interval: 100, model_load_path: output_model_dpin
2022-09-22 15:51:37,264 - INFO - **************common.configs**********
2022-09-22 15:51:37,333 - INFO - read data
2022-09-22 15:51:37,334 - INFO - reader path:dpin_reader
2022-09-22 15:51:37,334 - INFO - load model epoch 0
2022-09-22 15:51:37,334 - INFO - start load model from output_model_dpin/0
2022-09-22 15:51:37,432 - INFO - epoch: 0, batch_id: 0, AUC: 0.603448,PAUC: 0.559943, avg_reader_cost: 0.00012 sec, avg_batch_cost: 0.00067 sec, avg_samples: 32.00000, ips: 32826.18 ins/s
2022-09-22 15:51:37,686 - INFO - epoch: 0 done, AUC: 0.624453,PAUC: 0.559585, epoch time: 0.35 s
2022-09-22 15:51:37,686 - INFO - load model epoch 1
2022-09-22 15:51:37,686 - INFO - start load model from output_model_dpin/1
2022-09-22 15:51:37,769 - INFO - epoch: 1, batch_id: 0, AUC: 0.718391,PAUC: 0.612784, avg_reader_cost: 0.00011 sec, avg_batch_cost: 0.00058 sec, avg_samples: 32.00000, ips: 9503.53 ins/s
2022-09-22 15:51:38,018 - INFO - epoch: 1 done, AUC: 0.647409,PAUC: 0.588100, epoch time: 0.33 s
2022-09-22 15:51:38,018 - INFO - load model epoch 2
2022-09-22 15:51:38,019 - INFO - start load model from output_model_dpin/2
2022-09-22 15:51:38,101 - INFO - epoch: 2, batch_id: 0, AUC: 0.741379,PAUC: 0.657955, avg_reader_cost: 0.00008 sec, avg_batch_cost: 0.00059 sec, avg_samples: 32.00000, ips: 9655.43 ins/s
2022-09-22 15:51:38,357 - INFO - epoch: 2 done, AUC: 0.664512,PAUC: 0.645197, epoch time: 0.34 s
2022-09-22 15:51:38,357 - INFO - load model epoch 3
2022-09-22 15:51:38,357 - INFO - start load model from output_model_dpin/3
2022-09-22 15:51:38,443 - INFO - epoch: 3, batch_id: 0, AUC: 0.758621,PAUC: 0.675000, avg_reader_cost: 0.00013 sec, avg_batch_cost: 0.00062 sec, avg_samples: 32.00000, ips: 9357.27 ins/s
2022-09-22 15:51:38,698 - INFO - epoch: 3 done, AUC: 0.674845,PAUC: 0.674162, epoch time: 0.34 s
2022-09-22 15:51:38,698 - INFO - load model epoch 4
2022-09-22 15:51:38,699 - INFO - start load model from output_model_dpin/4
2022-09-22 15:51:38,789 - INFO - epoch: 4, batch_id: 0, AUC: 0.781609,PAUC: 0.712500, avg_reader_cost: 0.00015 sec, avg_batch_cost: 0.00064 sec, avg_samples: 32.00000, ips: 9270.74 ins/s
2022-09-22 15:51:39,049 - INFO - epoch: 4 done, AUC: 0.681818,PAUC: 0.691691, epoch time: 0.35 s

六、模型组网

相较于传统的 CTR 模型只有一个 Base Module 模块,本模型有三个模块组成:Base Module、Combination Module、Interaction Module。将位置信息的建模从 Base Module 中抽离,成为新的 Interaction Module。

Base Module与传统方法一致,是一个简单的 MLP 结构,用于将用户特征、商品特征和上下文特征融合。

Interaction Module 用于生成与商品内容无关的位置特征,其中使用到了Attention与Tramsformer机制,可以更好的发掘出位置的特征。

而 Combination Module 将交互后的物品特征与每个位置特征交互,生成每个商品在每个位置的CTR。

七、效果复现

为了方便使用者能够快速的跑通每一个模型,我们在每个模型下都提供了样例数据。如果需要复现readme中的效果,请按如下步骤依次操作即可。全量训练和预测的日志文件请见 train.log。
在全量数据下模型的指标如下:

模型aucpaucbatch_sizeepoch_numTime of each epoch
DPIN0.680.6710242019min
DIN0.630.6210242013min

我们选择了数据集中的前 5000w 条记录训练模型,对 DIN 和 DPIN 模型分别训练 20 轮左右。我们发现 DPIN 相较于 DIN 模型可以更快的收敛并且在训练集上取得 0.76 左右的 AUC 分数。在测试集中,作者提出的模型最好成绩中 AUC 为 0.68,PAUC 为 0.67,而对于用于比较的 DIN 模型来说,最好成绩的 AUC 为 0.63,PAUC 为 0.62。虽然使用的数据集不一样,但是可以证明模型的有效性。AUC、PAUC 和 Loss 曲线如下图所示,发现 DPIN 模型可以快速收敛并稳定。

具体流程如下:

cd /home/aistudio/PaddleRec/datasets/KDD2012_track2
# 准备数据
!bash run.sh
cd /home/aistudio/PaddleRec/models/rank/dpin
# 动态图训练
!python3 -u ../../../tools/trainer.py -m config_bigdata.yaml # 全量数据运行
# 动态图预测
!python3 -u .././../tools/infer.py -m config_bigdata.yaml # 全量数据预测

八、进阶使用

本模型支持飞桨训推一体认证 (Training and Inference Pipeline Certification(TIPC)) 信息和测试工具,方便用户查阅每种模型的训练推理部署打通情况,并可以进行一键测试。

使用本工具,可以测试不同功能的支持情况,以及预测结果是否对齐,测试流程概括如下:

  1. 运行prepare.sh准备测试所需数据和模型;
  2. 运行测试脚本test_train_inference_python.sh,产出log,由log可以看到不同配置是否运行成功;

测试单项功能仅需两行命令,命令格式如下:

# 功能:准备数据
# 格式:bash + 运行脚本 + 参数1: 配置文件选择 + 参数2: 模式选择
# 模式选择 [Mode] = 'lite_train_lite_infer' | 'whole_train_whole_infer' | 'whole_infer' | 'lite_train_whole_infer'
bash test_tipc/prepare.sh configs/[model_name]/[params_file_name] [Mode]

# 功能:运行测试
# 格式:bash + 运行脚本 + 参数1: 配置文件选择 + 参数2: 模式选择
bash test_tipc/test_train_inference_python.sh configs/[model_name]/[params_file_name]  [Mode]

例如,测试基本训练预测功能的lite_train_lite_infer模式,运行:

cd /home/aistudio/PaddleRec
# 准备数据
!bash test_tipc/prepare.sh ./test_tipc/configs/dpin/train_infer_python.txt 'lite_train_lite_infer'
# 运行测试
nfer'
# 运行测试
!bash test_tipc/test_train_inference_python.sh ./test_tipc/configs/dpin/train_infer_python.txt 'lite_train_lite_infer'

九、复现心得

本项目在复现时的主要工作包括:

  • 论文作者并未提供参考代码以及开源数据集,因此本项目一大难点就是寻找合适的数据集,并根据模型构建图设计模型原型
  • 确定模型训练的超参,由于和原论文使用数据集不一样,需要适当修改超参
  • 在原有基础上合入PaddleRec套件和TEST_TIPC开发

有了之前复现的经验,进行模型的组网相对而言容易一点。主要难点在于数据集的选择和训练数据的构建。在试验阶段,选择了多个开源数据集比如亚马逊评价数据,音乐推荐数据等等,由于需要用户历史浏览商品的位置信息,因此选择了KDD Cup 2012 Task 2的参赛数据集。虽然其中的位置数据只有3个,相比较于作者使用的数据集有12个位置有点少,但实验最终也体现出了模型的有效性。

一次完全的从零开始选择数据集和设计组网,可以跟深入的了解模型的设计和实现。

此文章为搬运
原项目链接

Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐