转自AI Studio,原文链接:PaddleRec SIGN在线运行示例 - 飞桨AI Studio

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

代码请参考:sign 如果我们的代码对您有用,还请点个star啊~

一、模型简介

特征交叉通过将两个或多个特征相乘,来实现样本空间的非线性变换,提高模型的非线性能力,其在推荐系统领域中可以显著提高准确率。以往的研究考虑了所有特征之间的交叉,但是某些特征交叉与推荐结果的相关性不大,其引入的噪声会降低模型的准确率。因此论文《Detecting Beneficial Feature Interactions for Recommender Systems》中提出了一种利用图神经网络自动发现有意义特征交叉的模型L0-SIGN。 作者使用图神经网络建模每个样本的特征,将特征交叉与图中的边相联系,用GNN的关系推理能力对特征交叉进行建模。使用L0正则化的边预测来限制图中检测的边的数量,以此进行有意义特征交叉的检测。 本模型实现了下述论文中的 SIGN 模型:

@inproceedings{su2021detecting,
  title={Detecting Beneficial Feature Interactions for Recommender Systems},
  author={Su, Yixin and Zhang, Rui and Erfani, Sarah and Xu, Zhenghua},
  booktitle={Proceedings of the 34th AAAI Conference on Artificial Intelligence (AAAI)},
  year={2021}
}

二、数据准备

论文使用了4个开源数据集,DBLP_v1frappeml-tagtwitter,这里使用ml-tag验证模型效果,在模型目录的data目录中准备了快速运行的示例数据,若需要使用全量数据可以参考下方效果复现部分。 该数据集专注于电影标签推荐,每个数据实例都代表一个图,数据格式如下:

# 电影标签 用户ID 电影ID 电影ID
0.0 24 25 26
1.0 62 63 64

三、运行环境

PaddlePaddle>=2.0 pgl>=2.2.0 python 3.5/3.6/3.7 os : windows/linux/macos

四、代码结构

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

├── data    # sample数据
    ├── ml-tag-sample.data
├── __init__.py 
├── README.md   # README
├── config.yaml   # sample数据配置
├── config_bigdata.yaml # 全量数据配置
├── sign_reader.py  # 数据读取程序
├── net.py    # 模型核心组网(动静统一)
├── dygraph_model.py # 构建动态图
├── graph.py # 图神经网络框架

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

五、快速开始

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

In [ ]

# 准备环境: 安装pgl
!pip install pgl
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Requirement already satisfied: pgl in /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages (2.2.3.post0)
Requirement already satisfied: cython>=0.25.2 in /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages (from pgl) (0.29)
Requirement already satisfied: numpy<1.20.0,>=1.16.4 in /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages (from pgl) (1.19.5)

In [ ]

cd PaddleRec/models/rank/sign
/home/aistudio/PaddleRec/models/rank/sign

In [ ]

# 进入模型目录
# cd models/rank/sign
# 动态图训练
!python3 -u ../../../tools/trainer.py -m config.yaml # 全量数据运行config_bigdata.yaml
# 动态图预测
!python3 -u ../../../tools/infer.py -m config.yaml
2022-04-29 11:45:41,016 - INFO - **************common.configs**********
2022-04-29 11:45:41,016 - INFO - use_gpu: False, use_xpu: False, use_npu: False, use_visual: False, train_batch_size: 1024, train_data_dir: data, epochs: 10, print_interval: 100, model_save_path: output_model_sign
2022-04-29 11:45:41,016 - INFO - **************common.configs**********
2022-04-29 11:45:41,023 - INFO - read data
2022-04-29 11:45:41,023 - INFO - reader path:sign_reader
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/dygraph/math_op_patch.py:253: UserWarning: The dtype of left and right variables are not the same, left dtype is paddle.int64, but right dtype is paddle.float32, the right dtype will convert to paddle.int64
  format(lhs_dtype, rhs_dtype, lhs_dtype))
2022-04-29 11:45:41,426 - INFO - epoch: 0, batch_id: 0, AUC:0.498519, ACC:0.657227, loss:0.5004248, avg_reader_cost: 0.00059 sec, avg_batch_cost: 0.00345 sec, avg_samples: 10.24000, ips: 2968.72912 ins/s
2022-04-29 11:45:41,432 - INFO - epoch: 0 done, AUC: 0.498519,ACC: 0.657227,loss:0.5004248, epoch time: 0.36 s
2022-04-29 11:45:41,434 - INFO - Already save model in output_model_sign/0
2022-04-29 11:45:41,753 - INFO - epoch: 1, batch_id: 0, AUC:0.499362, ACC:0.665039, loss:0.71449375, avg_reader_cost: 0.00064 sec, avg_batch_cost: 0.00313 sec, avg_samples: 10.24000, ips: 3271.06755 ins/s
2022-04-29 11:45:41,759 - INFO - epoch: 1 done, AUC: 0.499362,ACC: 0.665039,loss:0.71449375, epoch time: 0.32 s
2022-04-29 11:45:41,761 - INFO - Already save model in output_model_sign/1
2022-04-29 11:45:42,073 - INFO - epoch: 2, batch_id: 0, AUC:0.638148, ACC:0.514648, loss:0.4272459, avg_reader_cost: 0.00062 sec, avg_batch_cost: 0.00306 sec, avg_samples: 10.24000, ips: 3345.79007 ins/s
2022-04-29 11:45:42,079 - INFO - epoch: 2 done, AUC: 0.638148,ACC: 0.514648,loss:0.4272459, epoch time: 0.32 s
2022-04-29 11:45:42,081 - INFO - Already save model in output_model_sign/2
2022-04-29 11:45:42,396 - INFO - epoch: 3, batch_id: 0, AUC:0.497667, ACC:0.638672, loss:0.36929712, avg_reader_cost: 0.00060 sec, avg_batch_cost: 0.00308 sec, avg_samples: 10.24000, ips: 3319.93545 ins/s
2022-04-29 11:45:42,402 - INFO - epoch: 3 done, AUC: 0.497667,ACC: 0.638672,loss:0.36929712, epoch time: 0.32 s
2022-04-29 11:45:42,404 - INFO - Already save model in output_model_sign/3
2022-04-29 11:45:42,722 - INFO - epoch: 4, batch_id: 0, AUC:0.506672, ACC:0.654297, loss:0.3425751, avg_reader_cost: 0.00061 sec, avg_batch_cost: 0.00312 sec, avg_samples: 10.24000, ips: 3278.37075 ins/s
2022-04-29 11:45:42,728 - INFO - epoch: 4 done, AUC: 0.506672,ACC: 0.654297,loss:0.3425751, epoch time: 0.32 s
2022-04-29 11:45:42,729 - INFO - Already save model in output_model_sign/4
2022-04-29 11:45:43,092 - INFO - epoch: 5, batch_id: 0, AUC:0.536325, ACC:0.664062, loss:0.32712212, avg_reader_cost: 0.00069 sec, avg_batch_cost: 0.00356 sec, avg_samples: 10.24000, ips: 2875.53832 ins/s
2022-04-29 11:45:43,097 - INFO - epoch: 5 done, AUC: 0.536325,ACC: 0.664062,loss:0.32712212, epoch time: 0.37 s
2022-04-29 11:45:43,099 - INFO - Already save model in output_model_sign/5
2022-04-29 11:45:43,418 - INFO - epoch: 6, batch_id: 0, AUC:0.550335, ACC:0.666992, loss:0.31464067, avg_reader_cost: 0.00063 sec, avg_batch_cost: 0.00313 sec, avg_samples: 10.24000, ips: 3269.97674 ins/s
2022-04-29 11:45:43,424 - INFO - epoch: 6 done, AUC: 0.550335,ACC: 0.666992,loss:0.31464067, epoch time: 0.32 s
2022-04-29 11:45:43,426 - INFO - Already save model in output_model_sign/6
2022-04-29 11:45:43,751 - INFO - epoch: 7, batch_id: 0, AUC:0.556710, ACC:0.669922, loss:0.3053843, avg_reader_cost: 0.00068 sec, avg_batch_cost: 0.00319 sec, avg_samples: 10.24000, ips: 3210.33361 ins/s
2022-04-29 11:45:43,756 - INFO - epoch: 7 done, AUC: 0.556710,ACC: 0.669922,loss:0.3053843, epoch time: 0.33 s
2022-04-29 11:45:43,758 - INFO - Already save model in output_model_sign/7
2022-04-29 11:45:44,076 - INFO - epoch: 8, batch_id: 0, AUC:0.595947, ACC:0.664062, loss:0.29662904, avg_reader_cost: 0.00065 sec, avg_batch_cost: 0.00312 sec, avg_samples: 10.24000, ips: 3277.92038 ins/s
2022-04-29 11:45:44,082 - INFO - epoch: 8 done, AUC: 0.595947,ACC: 0.664062,loss:0.29662904, epoch time: 0.32 s
2022-04-29 11:45:44,084 - INFO - Already save model in output_model_sign/8
2022-04-29 11:45:44,397 - INFO - epoch: 9, batch_id: 0, AUC:0.636517, ACC:0.667969, loss:0.28801075, avg_reader_cost: 0.00062 sec, avg_batch_cost: 0.00307 sec, avg_samples: 10.24000, ips: 3337.24479 ins/s
2022-04-29 11:45:44,402 - INFO - epoch: 9 done, AUC: 0.636517,ACC: 0.667969,loss:0.28801075, epoch time: 0.32 s
2022-04-29 11:45:44,404 - INFO - Already save model in output_model_sign/9
2022-04-29 11:45:46,238 - INFO - **************common.configs**********
2022-04-29 11:45:46,238 - INFO - use_gpu: False, use_xpu: False, use_npu: False, use_visual: False, infer_batch_size: 1024, test_data_dir: data, start_epoch: 9, end_epoch: 10, print_interval: 100, model_load_path: output_model_sign
2022-04-29 11:45:46,238 - INFO - **************common.configs**********
2022-04-29 11:45:46,246 - INFO - read data
2022-04-29 11:45:46,246 - INFO - reader path:sign_reader
2022-04-29 11:45:46,298 - INFO - load model epoch 9
2022-04-29 11:45:46,298 - INFO - start load model from output_model_sign/9
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/dygraph/math_op_patch.py:253: UserWarning: The dtype of left and right variables are not the same, left dtype is paddle.int64, but right dtype is paddle.float32, the right dtype will convert to paddle.int64
  format(lhs_dtype, rhs_dtype, lhs_dtype))
2022-04-29 11:45:46,643 - INFO - epoch: 9, batch_id: 0, AUC: 0.689603,ACC: 0.671875, avg_reader_cost: 0.00060 sec, avg_batch_cost: 0.00337 sec, avg_samples: 1024.00000, ips: 297251.79 ins/s
2022-04-29 11:45:46,649 - INFO - epoch: 9 done, AUC: 0.689603,ACC: 0.671875, epoch time: 0.35 s

六、模型组网

L0-SIGN模型有两个模块,一个是L0边预估模块,通过矩阵分解图的邻接矩阵进行边的预估,一个是图分类SIGN模块。模型的主要组网结构如图1所示,与 net.py 中的代码一一对应 :

七、效果复现

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

模型aucaccbatch_sizeepoch_numTime of each epoch
SIGN0.94180.8927102440约18分钟

具体流程如下:

In [ ]

cd /home/aistudio/PaddleRec/datasets/sign
/home/aistudio/PaddleRec/datasets/sign

In [ ]

# 准备数据
!bash run.sh

# 安装依赖
!pip install pgl

In [ ]

cd /home/aistudio/PaddleRec/models/rank/sign

In [ ]

# 动态图训练
!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模式,运行:

In [ ]

cd /home/aistudio/PaddleRec

In [14]

# 准备数据
!bash test_tipc/prepare.sh ./test_tipc/configs/sign/train_infer_python.txt 'lite_train_lite_infer'
# 运行测试
!bash test_tipc/test_train_inference_python.sh ./test_tipc/configs/sign/train_infer_python.txt 'lite_train_lite_infer'

九、复现心得

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

  • 论文作者的代码使用的Pytorch框架更换为PaddlePaddle框架
  • 在原有基础上合入PaddleRec套件和TEST_TIPC开发
  • 将torch中图神经网络相关的部分替换为PaddlePaddle/PGL
  • 将输入数据封装为graph图数据结构

其中,最重要的部分就是实现图神经网络的输入和消息传递。原作者代码中使用torch_geometric库进行消息传递,然而PaddlePaddle默认库中并不存在对应的方法。当时一度想放弃,觉得需要自己实现一个图神经网络框架,然后一次偶然发现了PaddlePaddle/PGL库,属于柳暗花明又一村了。该库中定义了graph数据结构来存储图网络,通过自定义send_funcrecv_fun来自定义消息传递机制。使用PaddlePaddle/PGL进行图神经网络的开发,相比于torch_geometric来说,代码更具有可解释性,并且配套有graph数据结构,其可以高效的实现子图合并成大图的功能。不过该数据结构只接受numpy格式的数据,因此如果需要存储dict就需要斟酌一下。

除此之外,也发现了PaddlePaddle与Pytorch中一些相同方法的小差异。在修改框架过程中,需要细致的比较一种方法在两种框架中的不同输入和输出,并适当的添加一些tensor操作。在进行TEST_TIPC开发中,也发现了pgl框架中一些方法在自动to_static时会存在问题。此时,又需要去查看pgl的源码,进行适当的覆盖修改。

总的说来,是一次不错体验,可以深入的了解两种框架以及图神经网络的架构,并对原作者的模型设计有了更进一步的了解。

Logo

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

更多推荐