前言:我在github上创建了一个新的repo:PaddleAI, 准备用Paddle做的一系列有趣又实用的案例,所有的案例都会上传数据代码和预训练模型,下载后可以在30s内上手,跑demo出结果,让大家尽快看到训练结果,用小批量数据调试,再用全量数据跑模型,当然,也可以基于我上传的预训练模型进行迁移学习,如果大家有需要的话。今天刚写好第一个项目,用Paddle做广告CTR预估,来源于Kaggle的比赛Display Advertising Challenge, 感兴趣的读者往下看~(也可以留言期待的todo案例)

  github:https://github.com/huxiaoman7/PaddleAI

  Paddle models:https://github.com/PaddlePaddle/models

  欢迎大家star、fork、提issue和贡献新案例~


数据准备

数据说明

  • 数据来源:Kaggle公司举办的展示广告竞赛中所使用的Criteo数据集。该数据包含数百万展示广告的特征值和点击反馈,目的是对点击率(CTR)的预测做基准预测。

  • 数据背景:Criteo是在线效果类数字营销厂商,于2005年在法国巴黎成立,目前的核心业务是重定向广告(retargeting)。Criteo在全球范围内共有31间办事处,有6间位于欧洲,有5间位于北美,有1间在巴西,在亚太地区总共有5间办事处。Criteo是在线效果类展示广告厂商于2014年5月13日宣布启动在中国的业务和运营,并将北京设为中国区总部所在地。Criteo的核心产品主要包括访客广告、流失客户广告、移动应用内效果型广告和AD-X 移动广告跟踪分析产品等。Criteo拥有世界领先的自主学习式推荐引擎和预测引擎,能够通过其对于市场的洞察提供可评估的结果,因而能够在正确的时间通过推送广告,将对的产品推荐给对的用户。并且,随着每一条广告的交付,Criteo的引擎在预测和推荐方面的精确性也不断提高。

  • 数据格式:

    • 格式:… 。共计39个特征,13个数值特征(int),26个类别特征。若value为空值,则为空白
  • 训练数据:train.txt:Criteo 公司在七天内的部分流量。每行对应的是Critio的展示广告,第一列代表该广告是否被点击。我们对正样本(已点击)的和负样本(未点击)均做了子采样来减少数据量。类别特征的值已经过哈希处理为64位来进行脱敏。特征的语义没有公开,并且有些特征有缺失值。行按照时间排序。

    • 示例(只显示了前20列)

  • 测试数据:test.txt:测试集于训练集的计算方式相同,但对应的是训练集时间段的后一天的事件。并且第一列(label)已被移除。

    • 示例(只显示了前20列)

数据处理

  • 下载数据

    cd data && ./download.sh && cd .. 
  • 数据读取

  • code:reader.py

  • 原始数据中前13个feature为int型,通过reader.py将其做了数据归一化处理为float型,避免过大和过小的数据在模型训练中的影响。

    .── CriteoDataset

    ├── train

    ├── test

    ├── infer
  • 具体代码:

 class CriteoDataset(Dataset):
def __init__(self, sparse_feature_dim):
self.cont_min_ = [0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
self.cont_max_ = [20, 600, 100, 50, 64000, 500, 100, 50, 500, 10, 10, 10, 50]
self.cont_diff_ = [20, 603, 100, 50, 64000, 500, 100, 50, 500, 10, 10, 10, 50]
self.hash_dim_ = sparse_feature_dim
# here, training data are lines with line_index < train_idx_
self.train_idx_ = 41256555
self.continuous_range_ = range(1, 14)
self.categorical_range_ = range(14, 40) def _reader_creator(self, file_list, is_train, trainer_num, trainer_id):
def reader():
for file in file_list:
with open(file, 'r') as f:
line_idx = 0
for line in f:
line_idx += 1
if is_train and line_idx > self.train_idx_:
break
elif not is_train and line_idx <= self.train_idx_:
continue
if line_idx % trainer_num != trainer_id:
continue
features = line.rstrip('\n').split('\t')
dense_feature = []
sparse_feature = []
for idx in self.continuous_range_:
if features[idx] == '':
dense_feature.append(0.0)
else:
dense_feature.append((float(features[idx]) - self.cont_min_[idx - 1]) / self.cont_diff_[idx - 1])
for idx in self.categorical_range_:
sparse_feature.append([hash(str(idx) + features[idx]) % self.hash_dim_]) label = [int(features[0])]
yield [dense_feature] + sparse_feature + [label] return reader
 

模型训练

网络结构

  • code: network_conf.py (只用到ctr_dnn_model) 详细讲解

训练方式

单机训练

python train.py \
--train_data_path data/raw/train.txt \
>& | tee train.log

分布式训练

运行方式

sh cluster_train.sh
 

调用接口

 pe = fluid.ParallelExecutor(
use_cuda=False,
loss_name=loss.name,
main_program=train_program,
build_strategy=build_strategy,
exec_strategy=exec_strategy)
logger.info("run dist training")
t = fluid.DistributeTranspiler()
t.transpile(args.trainer_id, pservers=args.endpoints, trainers=args.trainers)
if args.role == "pserver" or args.role == "PSERVER":
logger.info("run pserver")
prog = t.get_pserver_program(args.current_endpoint)
startup = t.get_startup_program(args.current_endpoint, pserver_program=prog)
exe = fluid.Executor(fluid.CPUPlace())
exe.run(startup)
exe.run(prog)
elif args.role == "trainer" or args.role == "TRAINER":
logger.info("run trainer")
train_prog = t.get_trainer_program()
train_loop(args, train_prog, py_reader, loss, auc_var, batch_auc_var,
args.trainers, args.trainer_id)
 

注:batch_size由默认的1000修改为64,可提高auc

训练结果

  • 单机训练

    • 速度太慢,迭代到第1轮batch= 4919时就停住了
  • 分布式训练

    • 设置:2pserver、2trainer

    • 训练日志:alldata/log/trainer0.log 、alldata/log/trainer1.log

    • 训练结果:  

-- ::,-INFO: TRAIN --> pass:  batch:  loss: 0.467225006104 auc: 0.787909292672, batch_auc: 0.797377570934
pass_id: , pass_time_cost: 3150.447569
pass_id: , pass_time_cost: 3177.322331
pass_id: , pass_time_cost: 3174.676812
pass_id: , pass_time_cost: 3209.558880
pass_id: , pass_time_cost: 3134.910369
pass_id: , pass_time_cost: 3202.956675
pass_id: , pass_time_cost: 3169.575809
pass_id: , pass_time_cost: 3210.294044
pass_id: , pass_time_cost: 3039.102302
pass_id: , pass_time_cost: 3036.933163

模型预测

预测方式

python infer.py \
--model_path models/pass-/ \
--data_path data/raw/valid.txt

预测结果:

  • log:alldata/log/infer.txt
-- ::,-INFO: TEST --> batch:  loss: [0.46127334] auc: [0.78797872]
 

实验对比

原始数据情况

  label 数量 比例
负样本 0 34095179 0.74377662
正样本 1 11745438 0.25622338

实验数据:

  • mini-demo:1%的全量数据
  • demo:10%的全量数据
  • raw:全量数据

BaseLine实验

  • 数据说明: mini-data(1%全量数据)

  • 网络配置:一层网络,batch_size =1000

  • 修改方式:

    • 在network_conf.py 第151行修改,如下如所示,将input=fc3 修改为input=fc1

    • 在cluster_train.sh 里第35行和第47行将batch_size=64 修改为batch_size=1000

  • 运行方式:

    • 修改完以上两个文件后,执行:sh cluster_train.sh
  • 输出日志:

    • pserver:pserver0.log、pserver1.log 参数服务器的输出日志
    • trainer:trainer0.log、trainer1.log 每个trainer的输出日志 可以通过 tail -f trainer0.log -n 999 查看输出结果
  • 实验效果

    • 训练时间:33s(一轮迭代)
    • auc:0.50234167

优化实验(一):优化网络层

  • 数据说明: mini-data(1%全量数据)

  • 网络配置:三层网络,batch_size =1000

  • 修改方式:

    • 在network_conf.py 第151行修改,如下如所示,将input=fc1 修改为input=fc3

    • 在cluster_train.sh 里第35行和第47行将batch_size=64 修改为batch_size=1000

  • 运行方式:

    • 修改完以上两个文件后,执行:sh cluster_train.sh
  • 输出日志:

    • pserver:pserver0.log、pserver1.log 参数服务器的输出日志
    • trainer:trainer0.log、trainer1.log 每个trainer的输出日志 可以通过 tail -f trainer0.log -n 999 查看输出结果
  • 实验效果

    • 训练时间:35s(一轮迭代)
    • auc:0.54893279

优化实验(二):调整batch_size

  • 数据说明: mini-data(1%全量数据)

  • 网络配置:三层网络,batch_size =64

  • 修改方式:

    • 在network_conf.py 第151行修改,如下如所示,将input=fc1 修改为input=fc3

    • 在cluster_train.sh 里第35行和第47行将batch_size=1000 修改为batch_size=64

  • 运行方式:

    • 修改完以上两个文件后,执行:sh cluster_train.sh
  • 输出日志:

    • pserver:pserver0.log、pserver1.log 参数服务器的输出日志
    • trainer:trainer0.log、trainer1.log 每个trainer的输出日志 可以通过 tail -f trainer0.log -n 999 查看输出结果
  • 实验效果

    • 训练时间:103s(一轮迭代)
    • auc:0.74322927

优化实验(三):增加数据集

  • 数据说明: 全量数据

  • 网络配置:三层网络,batch_size =64,数据量由10%数据(demo_data)扩充到全量数据

  • 修改方式:

    • 在network_conf.py 第151行修改,如下如所示,将input=fc1 修改为input=fc3

    • 在cluster_train.sh 里第35行和第47行将batch_size=1000 修改为batch_size=64

    • 在cluster_train.sh 里将连个pserver和两个trainer的train_data_path地址修改为raw_data的地址,如下图所示,注意:一共需要修改四个地址

  • 运行方式:

    • 修改完以上两个文件后,执行:sh cluster_train.sh
  • 输出日志:

    • pserver:pserver0.log、pserver1.log 参数服务器的输出日志
    • trainer:trainer0.log、trainer1.log 每个trainer的输出日志 可以通过 tail -f trainer0.log -n 999 查看输出结果
  • 实验效果

    • 训练时间:3150s(一轮迭代)
    • auc:0.81093872

优化实验对比结果

  • 表格1:对mini_demo(1%全量数据)做训练,采取不同的优化方式,得到最后的优化方案的实验结果
评估 batch_size batch_1000 batch_1000 batch_64 batch_64
优化方式 评估 一层网络 三层网络 一层网络 三层网络
mini_demo time 33s 35s 97s 103s
  auc 0.50234167 0.54893279 0.721332392 0.74322927
  • 表格2: 增加数据集对模型精度的提升
  batch_size time auc
demo 64 1133s 0.73777626
全量 64 3150s 0.81093872

优化方案总结

由以上两个表格可知:

  • batch 大小的改变:在数据集和其他参数不变的情况下,batch_size由1000变为64.可以提升20%的模型精度
  • 网络结构的改变:在数据集和batch_size等参数不变的情况,由一层网络变为三层网络结构,大约可提升2~4%的模型精度
  • 数据集的改变:由demo数据(10%全量数据)扩充到全量数据,采用同样的batch_size,同样的迭代次数和其他超参数,大约可提升7%的精度

PaddlePaddle分布式训练及CTR预估模型应用的更多相关文章

  1. 主流CTR预估模型的演化及对比

    https://zhuanlan.zhihu.com/p/35465875 学习和预测用户的反馈对于个性化推荐.信息检索和在线广告等领域都有着极其重要的作用.在这些领域,用户的反馈行为包括点击.收藏. ...

  2. 闲聊DNN CTR预估模型

    原文:http://www.52cs.org/?p=1046 闲聊DNN CTR预估模型 Written by b manongb 作者:Kintocai, 北京大学硕士, 现就职于腾讯. 伦敦大学张 ...

  3. 深度CTR预估模型中的特征自动组合机制演化简史 zz

    众所周知,深度学习在计算机视觉.语音识别.自然语言处理等领域最先取得突破并成为主流方法.但是,深度学习为什么是在这些领域而不是其他领域最先成功呢?我想一个原因就是图像.语音.文本数据在空间和时间上具有 ...

  4. CTR预估模型演变及学习笔记

    [说在前面]本人博客新手一枚,象牙塔的老白,职业场的小白.以下内容仅为个人见解,欢迎批评指正,不喜勿喷![握手][握手] [再啰嗦一下]如果你对智能推荐感兴趣,欢迎先浏览我的另一篇随笔:智能推荐算法演 ...

  5. 【转】- 从FM推演各深度CTR预估模型(附代码)

    从FM推演各深度CTR预估模型(附代码) 2018年07月13日 15:04:34 阅读数:584 作者: 龙心尘 && 寒小阳 时间:2018年7月 出处: 龙心尘 寒小阳

  6. 几句话总结一个算法之CTR预估模型

    背景 假设现在有个商品点击预测的任务,有用户端特征性别.年龄.消费力等,商品侧特征价格.销量等,样本为0或者1,现在对特征进行one hot encode,如性别特征用二维表示,男为[1,0],女为[ ...

  7. ctr预估模型

    http://wenku.baidu.com/course/view/1488bfd5b9f3f90f76c61b8d

  8. CTR预估经典模型总结

    计算广告领域中数据特点:    1 正负样本不平衡    2 大量id类特征,高维,多领域(一个类别型特征就是一个field,比如上面的Weekday.Gender.City这是三个field),稀疏 ...

  9. 计算广告CTR预估系列(七)--Facebook经典模型LR+GBDT理论与实践

    计算广告CTR预估系列(七)--Facebook经典模型LR+GBDT理论与实践 2018年06月13日 16:38:11 轻春 阅读数 6004更多 分类专栏: 机器学习 机器学习荐货情报局   版 ...

随机推荐

  1. php pack()函数详解与示例

    pack和unpack在一般的程序中还真的不容易见到,但是如果你用过很久以前的php生成excel你就会知道了.他的excel的头就是pack出来的最近在尝试与C交互的时候又用上了这玩意,所以不得不再 ...

  2. SQL Cursor生命周期

      阅读导航 1 Cursor Step 1.1 Create cursor 1.2 Parse statement 1.3 descript and define 1.4 Bind variable ...

  3. C++基本数据类型及类型转换

    http://blog.csdn.net/pipisorry/article/details/25346379 c++基本数据类型 什么样的数据算是byte类型,int类型,float类型,doubl ...

  4. Leetcode 001-twosum

    #Given an array of integers, return indices of the two numbers such that they add up to a specific t ...

  5. Java面向对象编程(一)

    由于常常将Java和C++面向对象编程的原则搞乱,所以这次把相关要点分别总结一下,本文主要总结Java面向对象编程. 面向对象编程的三大特性是:继承性(inheritance), 多态性(polymo ...

  6. ffmpeg ffplay播放延时大问题:播放延时参数设置

    使用ffplay播放视频源时,rtsp/rtmp等,会有一定的延时,这里我们可以通过设置ffplay播放参数将延时控制到最小. ffplay.exe -i rtmp://xxxxxxx -fflags ...

  7. ASP.NET MVC EXTJS 通用主菜单框架

    一.说明 首先我不知道定义的文章标题是不是准确,我这篇博文介绍的是一个通用的软件主菜单框架,界面布局用的是extjs,还是先上一个图吧. 软件主界面左侧菜单采用的风格是extjs的手风琴模式,需要注意 ...

  8. [haoi2008]玩具命名

    某人有一套玩具,并想法给玩具命名.首先他选择WING四个字母中的任意一个字母作为玩具的基本名字.然后他会根据自己的喜好,将名字中任意一个字母用“WING”中任意两个字母代替,使得自己的名字能够扩充得很 ...

  9. APP测试走过的那些坑

    我现在的工作有一大部分也是app测试,虽然自己是app开发出身,但是在测试上还是跌入了很多大坑,毕竟二者还是有很大不同,所处的角度也是不一样的.而开发转测试中,我认为较难的也是一个角度的转换,以一个开 ...

  10. XML与TreeView

    1.treeview代码书写 private void Form1_Load(object sender, EventArgs e) { //代码为TreeView添加子项 treeView1.Con ...