提交 489369a4 编写于 作者: S Superjom

fix PR

上级 a4815f33
...@@ -3,27 +3,27 @@ ...@@ -3,27 +3,27 @@
以下是本例目录包含的文件以及对应说明: 以下是本例目录包含的文件以及对应说明:
``` ```
├── README.md # 本教程markdown 文档 ├── README.md # 本教程markdown 文档
├── dataset.md # 数据集处理教程 ├── dataset.md # 数据集处理教程
├── images # 本教程图片目录 ├── images # 本教程图片目录
│   ├── lr_vs_dnn.jpg │   ├── lr_vs_dnn.jpg
│   └── wide_deep.png │   └── wide_deep.png
├── infer.py # 预测脚本 ├── infer.py # 预测脚本
├── network_conf.py # 模型网络配置 ├── network_conf.py # 模型网络配置
├── reader.py # data provider ├── reader.py # data reader
├── train.py # 训练脚本 ├── train.py # 训练脚本
└── utils.py # helper functions └── utils.py # helper functions
└── avazu_data_processer.py # 示例数据预处理脚本
``` ```
## 背景介绍 ## 背景介绍
CTR(Click-Through Rate,点击率预估)\[[1](https://en.wikipedia.org/wiki/Click-through_rate)\] 是用来表示用户点击一个特定链接的概率, CTR(Click-Through Rate,点击率预估)\[[1](https://en.wikipedia.org/wiki/Click-through_rate)\]
通常被用来衡量一个在线广告系统的有效性 是对用户点击一个特定链接的概率做出预测,是广告投放过程中的一个重要环节。精准的点击率预估对在线广告系统收益最大化具有重要意义
当有多个广告位时,CTR 预估一般会作为排序的基准。 当有多个广告位时,CTR 预估一般会作为排序的基准,比如在搜索引擎的广告系统里,当用户输入一个带商业价值的搜索词(query)时,系统大体上会执行下列步骤来展示广告:
比如在搜索引擎的广告系统里,当用户输入一个带商业价值的搜索词(query)时,系统大体上会执行下列步骤来展示广告:
1. 召回满足 query 的广告集合 1. 获取满足 query 的广告集合
2. 业务规则和相关性过滤 2. 业务规则和相关性过滤
3. 根据拍卖机制和 CTR 排序 3. 根据拍卖机制和 CTR 排序
4. 展出广告 4. 展出广告
...@@ -51,13 +51,11 @@ Figure 1. LR 和 DNN 模型结构对比 ...@@ -51,13 +51,11 @@ Figure 1. LR 和 DNN 模型结构对比
</p> </p>
LR 的蓝色箭头部分可以直接类比到 DNN 中对应的结构,可以看到 LR 和 DNN 有一些共通之处(比如权重累加), LR 的蓝色箭头部分可以直接类比到 DNN 中对应的结构,可以看到 LR 和 DNN 有一些共通之处(比如权重累加),
但前者的模型复杂度在相同输入维度下比后者可能低很多(从某方面讲,模型越复杂,越有潜力学习到更复杂的信息)。 但前者的模型复杂度在相同输入维度下比后者可能低很多(从某方面讲,模型越复杂,越有潜力学习到更复杂的信息);
如果 LR 要达到匹敌 DNN 的学习能力,必须增加输入的维度,也就是增加特征的数量, 如果 LR 要达到匹敌 DNN 的学习能力,必须增加输入的维度,也就是增加特征的数量,
这也就是为何 LR 和大规模的特征工程必须绑定在一起的原因。 这也就是为何 LR 和大规模的特征工程必须绑定在一起的原因。
LR 对于 DNN 模型的优势是对大规模稀疏特征的容纳能力,包括内存和计算量等方面,工业界都有非常成熟的优化方法。 LR 对于 DNN 模型的优势是对大规模稀疏特征的容纳能力,包括内存和计算量等方面,工业界都有非常成熟的优化方法;
而 DNN 模型具有自己学习新特征的能力,一定程度上能够提升特征使用的效率, 而 DNN 模型具有自己学习新特征的能力,一定程度上能够提升特征使用的效率,
这使得 DNN 模型在同样规模特征的情况下,更有可能达到更好的学习效果。 这使得 DNN 模型在同样规模特征的情况下,更有可能达到更好的学习效果。
...@@ -74,7 +72,7 @@ LR 对于 DNN 模型的优势是对大规模稀疏特征的容纳能力,包括 ...@@ -74,7 +72,7 @@ LR 对于 DNN 模型的优势是对大规模稀疏特征的容纳能力,包括
我们直接使用第一种方法做分类任务。 我们直接使用第一种方法做分类任务。
我们使用 Kaggle 上 `Click-through rate prediction` 任务的数据集\[[2](https://www.kaggle.com/c/avazu-ctr-prediction/data)\] 来演示模型。 我们使用 Kaggle 上 `Click-through rate prediction` 任务的数据集\[[2](https://www.kaggle.com/c/avazu-ctr-prediction/data)\] 来演示本例中的模型。
具体的特征处理方法参看 [data process](./dataset.md) 具体的特征处理方法参看 [data process](./dataset.md)
...@@ -86,7 +84,21 @@ LR 对于 DNN 模型的优势是对大规模稀疏特征的容纳能力,包括 ...@@ -86,7 +84,21 @@ LR 对于 DNN 模型的优势是对大规模稀疏特征的容纳能力,包括
23 231 \t 1230:0.12 13421:0.9 \t 1 23 231 \t 1230:0.12 13421:0.9 \t 1
``` ```
演示数据集\[[2](#参考文档)\] 可以使用 `avazu_data_processor.py` 脚本处理,具体使用方法参考如下说明: 详细的格式描述如下:
- `dnn input ids` 采用 one-hot 表示,只需要填写值为1的ID(注意这里不是变长输入)
- `lr input sparse values` 使用了 `ID:VALUE` 的表示,值部分最好规约到值域 `[-1, 1]`
此外,模型训练时需要传入一个文件描述 dnn 和 lr两个子模型的输入维度,文件的格式如下:
```
dnn_input_dim: <int>
lr_input_dim: <int>
```
其中, `<int>` 表示一个整型数值。
本目录下的 `avazu_data_processor.py` 可以对下载的演示数据集\[[2](#参考文档)\] 进行处理,具体使用方法参考如下说明:
``` ```
usage: avazu_data_processer.py [-h] --data_path DATA_PATH --output_dir usage: avazu_data_processer.py [-h] --data_path DATA_PATH --output_dir
...@@ -111,6 +123,12 @@ optional arguments: ...@@ -111,6 +123,12 @@ optional arguments:
size of the trainset (default: 100000) size of the trainset (default: 100000)
``` ```
- `data_path` 是待处理的数据路径
- `output_dir` 生成数据的输出路径
- `num_lines_to_detect` 预先扫描数据生成ID的个数,这里是扫描的文件行数
- `test_set_size` 生成测试集的行数
- `train_size` 生成训练姐的行数
## Wide & Deep Learning Model ## Wide & Deep Learning Model
谷歌在 16 年提出了 Wide & Deep Learning 的模型框架,用于融合适合学习抽象特征的 DNN 和 适用于大规模稀疏特征的 LR 两种模型的优点。 谷歌在 16 年提出了 Wide & Deep Learning 的模型框架,用于融合适合学习抽象特征的 DNN 和 适用于大规模稀疏特征的 LR 两种模型的优点。
...@@ -248,7 +266,7 @@ trainer.train( ...@@ -248,7 +266,7 @@ trainer.train(
## 运行训练和测试 ## 运行训练和测试
训练模型需要如下步骤: 训练模型需要如下步骤:
1. 下载训练数据,可以使用 Kaggle 上 CTR 比赛的数据\[[2](#参考文献)\] 1. 准备训练数据
1.[Kaggle CTR](https://www.kaggle.com/c/avazu-ctr-prediction/data) 下载 train.gz 1.[Kaggle CTR](https://www.kaggle.com/c/avazu-ctr-prediction/data) 下载 train.gz
2. 解压 train.gz 得到 train.txt 2. 解压 train.gz 得到 train.txt
3. `mkdir -p output; python avazu_data_processer.py --data_path train.txt --output_dir output --num_lines_to_detect 1000 --test_set_size 100` 生成演示数据 3. `mkdir -p output; python avazu_data_processer.py --data_path train.txt --output_dir output --num_lines_to_detect 1000 --test_set_size 100` 生成演示数据
...@@ -294,6 +312,8 @@ optional arguments: ...@@ -294,6 +312,8 @@ optional arguments:
23 231 \t 1230:0.12 13421:0.9 23 231 \t 1230:0.12 13421:0.9
``` ```
这里与训练数据的格式唯一不同的地方,就是没有标签,也就是训练数据中第3列 `click` 对应的数值。
`infer.py` 的使用方法如下 `infer.py` 的使用方法如下
``` ```
......
import os #!/usr/bin/env python
# -*- coding: utf-8 -*-import os
import sys import sys
import csv import csv
import cPickle import cPickle
...@@ -217,9 +218,6 @@ def detect_dataset(path, topn, id_fea_space=10000): ...@@ -217,9 +218,6 @@ def detect_dataset(path, topn, id_fea_space=10000):
feature_dims[key] for key in categorial_features + ['hour']) + 1 feature_dims[key] for key in categorial_features + ['hour']) + 1
feature_dims['lr_input'] = np.sum(feature_dims[key] feature_dims['lr_input'] = np.sum(feature_dims[key]
for key in id_features) + 1 for key in id_features) + 1
# logger.warning("dump dataset's meta info to %s" % meta_out_path)
# cPickle.dump([feature_dims, fields], open(meta_out_path, 'wb'))
return feature_dims return feature_dims
......
...@@ -45,27 +45,27 @@ ...@@ -45,27 +45,27 @@
以下是本例目录包含的文件以及对应说明: 以下是本例目录包含的文件以及对应说明:
``` ```
├── README.md # 本教程markdown 文档 ├── README.md # 本教程markdown 文档
├── dataset.md # 数据集处理教程 ├── dataset.md # 数据集处理教程
├── images # 本教程图片目录 ├── images # 本教程图片目录
│   ├── lr_vs_dnn.jpg │   ├── lr_vs_dnn.jpg
│   └── wide_deep.png │   └── wide_deep.png
├── infer.py # 预测脚本 ├── infer.py # 预测脚本
├── network_conf.py # 模型网络配置 ├── network_conf.py # 模型网络配置
├── reader.py # data provider ├── reader.py # data reader
├── train.py # 训练脚本 ├── train.py # 训练脚本
└── utils.py # helper functions └── utils.py # helper functions
└── avazu_data_processer.py # 示例数据预处理脚本
``` ```
## 背景介绍 ## 背景介绍
CTR(Click-Through Rate,点击率预估)\[[1](https://en.wikipedia.org/wiki/Click-through_rate)\] 是用来表示用户点击一个特定链接的概率, CTR(Click-Through Rate,点击率预估)\[[1](https://en.wikipedia.org/wiki/Click-through_rate)\]
通常被用来衡量一个在线广告系统的有效性 是对用户点击一个特定链接的概率做出预测,是广告投放过程中的一个重要环节。精准的点击率预估对在线广告系统收益最大化具有重要意义
当有多个广告位时,CTR 预估一般会作为排序的基准。 当有多个广告位时,CTR 预估一般会作为排序的基准,比如在搜索引擎的广告系统里,当用户输入一个带商业价值的搜索词(query)时,系统大体上会执行下列步骤来展示广告:
比如在搜索引擎的广告系统里,当用户输入一个带商业价值的搜索词(query)时,系统大体上会执行下列步骤来展示广告:
1. 召回满足 query 的广告集合 1. 获取满足 query 的广告集合
2. 业务规则和相关性过滤 2. 业务规则和相关性过滤
3. 根据拍卖机制和 CTR 排序 3. 根据拍卖机制和 CTR 排序
4. 展出广告 4. 展出广告
...@@ -93,13 +93,11 @@ Figure 1. LR 和 DNN 模型结构对比 ...@@ -93,13 +93,11 @@ Figure 1. LR 和 DNN 模型结构对比
</p> </p>
LR 的蓝色箭头部分可以直接类比到 DNN 中对应的结构,可以看到 LR 和 DNN 有一些共通之处(比如权重累加), LR 的蓝色箭头部分可以直接类比到 DNN 中对应的结构,可以看到 LR 和 DNN 有一些共通之处(比如权重累加),
但前者的模型复杂度在相同输入维度下比后者可能低很多(从某方面讲,模型越复杂,越有潜力学习到更复杂的信息)。 但前者的模型复杂度在相同输入维度下比后者可能低很多(从某方面讲,模型越复杂,越有潜力学习到更复杂的信息);
如果 LR 要达到匹敌 DNN 的学习能力,必须增加输入的维度,也就是增加特征的数量, 如果 LR 要达到匹敌 DNN 的学习能力,必须增加输入的维度,也就是增加特征的数量,
这也就是为何 LR 和大规模的特征工程必须绑定在一起的原因。 这也就是为何 LR 和大规模的特征工程必须绑定在一起的原因。
LR 对于 DNN 模型的优势是对大规模稀疏特征的容纳能力,包括内存和计算量等方面,工业界都有非常成熟的优化方法。 LR 对于 DNN 模型的优势是对大规模稀疏特征的容纳能力,包括内存和计算量等方面,工业界都有非常成熟的优化方法;
而 DNN 模型具有自己学习新特征的能力,一定程度上能够提升特征使用的效率, 而 DNN 模型具有自己学习新特征的能力,一定程度上能够提升特征使用的效率,
这使得 DNN 模型在同样规模特征的情况下,更有可能达到更好的学习效果。 这使得 DNN 模型在同样规模特征的情况下,更有可能达到更好的学习效果。
...@@ -116,7 +114,7 @@ LR 对于 DNN 模型的优势是对大规模稀疏特征的容纳能力,包括 ...@@ -116,7 +114,7 @@ LR 对于 DNN 模型的优势是对大规模稀疏特征的容纳能力,包括
我们直接使用第一种方法做分类任务。 我们直接使用第一种方法做分类任务。
我们使用 Kaggle 上 `Click-through rate prediction` 任务的数据集\[[2](https://www.kaggle.com/c/avazu-ctr-prediction/data)\] 来演示模型。 我们使用 Kaggle 上 `Click-through rate prediction` 任务的数据集\[[2](https://www.kaggle.com/c/avazu-ctr-prediction/data)\] 来演示本例中的模型。
具体的特征处理方法参看 [data process](./dataset.md)。 具体的特征处理方法参看 [data process](./dataset.md)。
...@@ -128,7 +126,21 @@ LR 对于 DNN 模型的优势是对大规模稀疏特征的容纳能力,包括 ...@@ -128,7 +126,21 @@ LR 对于 DNN 模型的优势是对大规模稀疏特征的容纳能力,包括
23 231 \t 1230:0.12 13421:0.9 \t 1 23 231 \t 1230:0.12 13421:0.9 \t 1
``` ```
演示数据集\[[2](#参考文档)\] 可以使用 `avazu_data_processor.py` 脚本处理,具体使用方法参考如下说明: 详细的格式描述如下:
- `dnn input ids` 采用 one-hot 表示,只需要填写值为1的ID(注意这里不是变长输入)
- `lr input sparse values` 使用了 `ID:VALUE` 的表示,值部分最好规约到值域 `[-1, 1]`。
此外,模型训练时需要传入一个文件描述 dnn 和 lr两个子模型的输入维度,文件的格式如下:
```
dnn_input_dim: <int>
lr_input_dim: <int>
```
其中, `<int>` 表示一个整型数值。
本目录下的 `avazu_data_processor.py` 可以对下载的演示数据集\[[2](#参考文档)\] 进行处理,具体使用方法参考如下说明:
``` ```
usage: avazu_data_processer.py [-h] --data_path DATA_PATH --output_dir usage: avazu_data_processer.py [-h] --data_path DATA_PATH --output_dir
...@@ -153,6 +165,12 @@ optional arguments: ...@@ -153,6 +165,12 @@ optional arguments:
size of the trainset (default: 100000) size of the trainset (default: 100000)
``` ```
- `data_path` 是待处理的数据路径
- `output_dir` 生成数据的输出路径
- `num_lines_to_detect` 预先扫描数据生成ID的个数,这里是扫描的文件行数
- `test_set_size` 生成测试集的行数
- `train_size` 生成训练姐的行数
## Wide & Deep Learning Model ## Wide & Deep Learning Model
谷歌在 16 年提出了 Wide & Deep Learning 的模型框架,用于融合适合学习抽象特征的 DNN 和 适用于大规模稀疏特征的 LR 两种模型的优点。 谷歌在 16 年提出了 Wide & Deep Learning 的模型框架,用于融合适合学习抽象特征的 DNN 和 适用于大规模稀疏特征的 LR 两种模型的优点。
...@@ -290,7 +308,7 @@ trainer.train( ...@@ -290,7 +308,7 @@ trainer.train(
## 运行训练和测试 ## 运行训练和测试
训练模型需要如下步骤: 训练模型需要如下步骤:
1. 下载训练数据,可以使用 Kaggle 上 CTR 比赛的数据\[[2](#参考文献)\] 1. 准备训练数据
1. 从 [Kaggle CTR](https://www.kaggle.com/c/avazu-ctr-prediction/data) 下载 train.gz 1. 从 [Kaggle CTR](https://www.kaggle.com/c/avazu-ctr-prediction/data) 下载 train.gz
2. 解压 train.gz 得到 train.txt 2. 解压 train.gz 得到 train.txt
3. `mkdir -p output; python avazu_data_processer.py --data_path train.txt --output_dir output --num_lines_to_detect 1000 --test_set_size 100` 生成演示数据 3. `mkdir -p output; python avazu_data_processer.py --data_path train.txt --output_dir output --num_lines_to_detect 1000 --test_set_size 100` 生成演示数据
...@@ -336,6 +354,8 @@ optional arguments: ...@@ -336,6 +354,8 @@ optional arguments:
23 231 \t 1230:0.12 13421:0.9 23 231 \t 1230:0.12 13421:0.9
``` ```
这里与训练数据的格式唯一不同的地方,就是没有标签,也就是训练数据中第3列 `click` 对应的数值。
`infer.py` 的使用方法如下 `infer.py` 的使用方法如下
``` ```
......
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import paddle.v2 as paddle import paddle.v2 as paddle
from paddle.v2 import layer from paddle.v2 import layer
from paddle.v2 import data_type as dtype from paddle.v2 import data_type as dtype
...@@ -80,10 +79,7 @@ class CTRmodel(object): ...@@ -80,10 +79,7 @@ class CTRmodel(object):
config LR submodel config LR submodel
''' '''
fc = layer.fc( fc = layer.fc(
input=self.lr_merged_input, input=self.lr_merged_input, size=1, act=paddle.activation.Relu())
size=1,
name='lr',
act=paddle.activation.Relu())
return fc return fc
def _build_classification_model(self, dnn, lr): def _build_classification_model(self, dnn, lr):
...@@ -91,7 +87,6 @@ class CTRmodel(object): ...@@ -91,7 +87,6 @@ class CTRmodel(object):
self.output = layer.fc( self.output = layer.fc(
input=merge_layer, input=merge_layer,
size=1, size=1,
name='output',
# use sigmoid function to approximate ctr rate, a float value between 0 and 1. # use sigmoid function to approximate ctr rate, a float value between 0 and 1.
act=paddle.activation.Sigmoid()) act=paddle.activation.Sigmoid())
...@@ -103,10 +98,7 @@ class CTRmodel(object): ...@@ -103,10 +98,7 @@ class CTRmodel(object):
def _build_regression_model(self, dnn, lr): def _build_regression_model(self, dnn, lr):
merge_layer = layer.concat(input=[dnn, lr]) merge_layer = layer.concat(input=[dnn, lr])
self.output = layer.fc( self.output = layer.fc(
input=merge_layer, input=merge_layer, size=1, act=paddle.activation.Sigmoid())
size=1,
name='output',
act=paddle.activation.Sigmoid())
if not self.is_infer: if not self.is_infer:
self.train_cost = paddle.layer.mse_cost( self.train_cost = paddle.layer.mse_cost(
input=self.output, label=self.click) input=self.output, label=self.click)
......
#!/usr/bin/env python
# -*- coding: utf-8 -*-import os
import argparse import argparse
import gzip import gzip
...@@ -71,12 +73,6 @@ def train(): ...@@ -71,12 +73,6 @@ def train():
trainer = paddle.trainer.SGD( trainer = paddle.trainer.SGD(
cost=model.train_cost, parameters=params, update_equation=optimizer) cost=model.train_cost, parameters=params, update_equation=optimizer)
# dataset = reader.AvazuDataset(
# args.train_data_path,
# n_records_as_test=args.test_set_size,
# fields=reader.fields,
# feature_dims=reader.feature_dims)
dataset = reader.Dataset() dataset = reader.Dataset()
def __event_handler__(event): def __event_handler__(event):
......
import logging import logging
logging.basicConfig() logging.basicConfig()
logger = logging.getLogger("logger") logger = logging.getLogger("paddle")
logger.setLevel(logging.INFO) logger.setLevel(logging.INFO)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册