From b3e717beab3dbd8c8d3442c05fa39109c41c95b6 Mon Sep 17 00:00:00 2001 From: Superjom Date: Thu, 25 May 2017 10:37:28 +0800 Subject: [PATCH] finish first version --- ctr/dataset.md | 373 ++++++++++++++++++++++++++++++++++++++++++++++++ ctr/dataset.org | 209 +++++++++++++++++++++++++++ 2 files changed, 582 insertions(+) create mode 100644 ctr/dataset.md create mode 100644 ctr/dataset.org diff --git a/ctr/dataset.md b/ctr/dataset.md new file mode 100644 index 00000000..6c437434 --- /dev/null +++ b/ctr/dataset.md @@ -0,0 +1,373 @@ +
+

Table of Contents

+ +
+ + + + +# 数据集介绍 + +数据集使用 \`csv\` 格式存储,其中各个字段内容如下: + +- id: ad identifier +- click: 0/1 for non-click/click +- hour: format is YYMMDDHH, so 14091123 means 23:00 on Sept. 11, 2014 UTC. +- C1 – anonymized categorical variable +- bannerpos +- siteid +- sitedomain +- sitecategory +- appid +- appdomain +- appcategory +- deviceid +- deviceip +- devicemodel +- devicetype +- deviceconntype +- C14-C21 – anonymized categorical variables + + + + +# 特征提取 + +下面我们会简单演示几种特征的提取方式。 + +原始数据中的特征可以分为以下几类: + +1. ID 类特征(稀疏,数量多) + - id + - siteid + - appid + - deviceid + +2. 类别类特征(稀疏,但数量有限) + - C1 + - sitecategory + - devicetype + - C14-C21 + +3. 数值型特征转化为类别型特征 + - hour (可以转化成数值,也可以按小时为单位转化为类别) + + + + +## 类别类特征 + +类别类特征的提取方法有以下两种: + +1. One-hot 表示作为特征 +2. 类似词向量,用一个 Embedding Table 将每个类别映射到对应的向量 + + + + +## ID 类特征 + +ID 类特征的特点是稀疏数据,但量比较大,直接使用 One-hot 表示时维度过大。 + +一般会作如下处理: + +1. 确定表示的最大维度 N +2. newid = id % N +3. 用 newid 作为类别类特征使用 + +上面的方法尽管存在一定的碰撞概率,但能够处理任意数量的 ID 特征,并保留一定的效果[2]。 + + + + +## 数值型特征 + +一般会做如下处理: + +- 归一化,直接作为特征输入模型 +- 用区间分割处理成类别类特征,稀疏化表示,模糊细微上的差别 + + + + +## 特征处理方法 + +具体特征处理方法参看 [data process](./dataset.md) + + + + +# 特征处理 + + + + +## 类别型特征 + +类别型特征有有限多种值,在模型中,我们一般使用 embedding table 将每种值映射为连续值的向量。 + +这种特征在输入到模型时,一般使用 One-hot 表示,相关处理方法如下: + + class CategoryFeatureGenerator(object): + ''' + Generator category features. + + Register all records by calling `register` first, then call `gen` to generate + one-hot representation for a record. + ''' + + def __init__(self): + self.dic = {'unk': 0} + self.counter = 1 + + def register(self, key): + ''' + Register record. + ''' + if key not in self.dic: + self.dic[key] = self.counter + self.counter += 1 + + def size(self): + return len(self.dic) + + def gen(self, key): + ''' + Generate one-hot representation for a record. + ''' + if key not in self.dic: + res = self.dic['unk'] + else: + res = self.dic[key] + return [res] + + def __repr__(self): + return '' % len(self.dic) + +本任务中,类别类特征会输入到 DNN 中使用。 + + + + +## ID 类特征 + +ID 类特征代稀疏值,且值的空间很大的情况,一般用模操作规约到一个有限空间, +之后可以当成类别类特征使用,这里我们会将 ID 类特征输入到 LR 模型中使用。 + + class IDfeatureGenerator(object): + def __init__(self, max_dim): + ''' + @max_dim: int + Size of the id elements' space + ''' + self.max_dim = max_dim + + def gen(self, key): + ''' + Generate one-hot representation for records + ''' + return [hash(key) % self.max_dim] + + def size(self): + return self.max_dim + + + + +## 交叉类特征 + +LR 模型作为 Wide & Deep model 的 \`wide\` 部分,可以输入很 wide 的数据(特征空间的维度很大), +为了充分利用这个优势,我们将演示交叉组合特征构建成更大维度特征的情况,之后塞入到模型中训练。 + +这里我们依旧使用模操作来约束最终组合出的特征空间的大小,具体实现是直接在 \`IDfeatureGenerator\` 中添加一个\`gencrossfeature\` 的方法: + + def gen_cross_fea(self, fea1, fea2): + key = str(fea1) + str(fea2) + return self.gen(key) + +比如,我们觉得原始数据中,\`deviceid\` 和 \`siteid\` 有一些关联(比如某个 device 倾向于浏览特定 site), +我们通过组合出两者组合来捕捉这类信息。 + + + + +## 特征维度 + + + + +### Deep submodel(DNN)特征 + + + + +++ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
featuredimention
appcategory21
sitecategory22
deviceconntype5
hour24
bannerpos7
Total79
+ + + + +### Wide submodel(LR)特征 + + + + +++ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureDimention
id10000
siteid10000
appid10000
deviceid10000
deviceid X siteid1000000
Total1,040,000
+ + + + +# 输入到 Paddle 中 + +Deep 和 Wide 两部分均以 \`sparsebinaryvector\` 的格式[1]输入,输入前需要将相关特征拼合,模型最终只接受 3 个 input, +分别是 + +1. \`dnn input\`,DNN 的输入 +2. \`lr input\`, LR 的输入 +3. \`click\`, 标签 + +拼合特征的方法: + + def concat_sparse_vectors(inputs, dims): + ''' + concaterate sparse vectors into one + + @inputs: list + list of sparse vector + @dims: list of int + dimention of each sparse vector + ''' + res = [] + assert len(inputs) == len(dims) + start = 0 + for no, vec in enumerate(inputs): + for v in vec: + res.append(v + start) + start += dims[no] + return res + +[1] + diff --git a/ctr/dataset.org b/ctr/dataset.org new file mode 100644 index 00000000..6c98a159 --- /dev/null +++ b/ctr/dataset.org @@ -0,0 +1,209 @@ +#+title: 数据处理 +* 数据集介绍 +数据集使用 `csv` 格式存储,其中各个字段内容如下: + +- id: ad identifier +- click: 0/1 for non-click/click +- hour: format is YYMMDDHH, so 14091123 means 23:00 on Sept. 11, 2014 UTC. +- C1 -- anonymized categorical variable +- banner_pos +- site_id +- site_domain +- site_category +- app_id +- app_domain +- app_category +- device_id +- device_ip +- device_model +- device_type +- device_conn_type +- C14-C21 -- anonymized categorical variables + +* 特征提取 +下面我们会简单演示几种特征的提取方式。 + +原始数据中的特征可以分为以下几类: + +1. ID 类特征(稀疏,数量多) + - id + - site_id + - app_id + - device_id + +2. 类别类特征(稀疏,但数量有限) + - C1 + - site_category + - device_type + - C14-C21 + +3. 数值型特征转化为类别型特征 + - hour (可以转化成数值,也可以按小时为单位转化为类别) +** 类别类特征 +类别类特征的提取方法有以下两种: + +1. One-hot 表示作为特征 +2. 类似词向量,用一个 Embedding Table 将每个类别映射到对应的向量 + +** ID 类特征 +ID 类特征的特点是稀疏数据,但量比较大,直接使用 One-hot 表示时维度过大。 + +一般会作如下处理: + +1. 确定表示的最大维度 N +2. newid = id % N +3. 用 newid 作为类别类特征使用 + +上面的方法尽管存在一定的碰撞概率,但能够处理任意数量的 ID 特征,并保留一定的效果[2]。 + +** 数值型特征 +一般会做如下处理: + +- 归一化,直接作为特征输入模型 +- 用区间分割处理成类别类特征,稀疏化表示,模糊细微上的差别 + +** 特征处理方法 + +具体特征处理方法参看 [[./dataset.md][data process]] + +* 特征处理 +** 类别型特征 + 类别型特征有有限多种值,在模型中,我们一般使用 embedding table 将每种值映射为连续值的向量。 + + 这种特征在输入到模型时,一般使用 One-hot 表示,相关处理方法如下: + + #+BEGIN_SRC python + class CategoryFeatureGenerator(object): + ''' + Generator category features. + + Register all records by calling `register` first, then call `gen` to generate + one-hot representation for a record. + ''' + + def __init__(self): + self.dic = {'unk': 0} + self.counter = 1 + + def register(self, key): + ''' + Register record. + ''' + if key not in self.dic: + self.dic[key] = self.counter + self.counter += 1 + + def size(self): + return len(self.dic) + + def gen(self, key): + ''' + Generate one-hot representation for a record. + ''' + if key not in self.dic: + res = self.dic['unk'] + else: + res = self.dic[key] + return [res] + + def __repr__(self): + return '' % len(self.dic) + #+END_SRC + + 本任务中,类别类特征会输入到 DNN 中使用。 + +** ID 类特征 + ID 类特征代稀疏值,且值的空间很大的情况,一般用模操作规约到一个有限空间, + 之后可以当成类别类特征使用,这里我们会将 ID 类特征输入到 LR 模型中使用。 + + #+BEGIN_SRC python + class IDfeatureGenerator(object): + def __init__(self, max_dim): + ''' + @max_dim: int + Size of the id elements' space + ''' + self.max_dim = max_dim + + def gen(self, key): + ''' + Generate one-hot representation for records + ''' + return [hash(key) % self.max_dim] + + def size(self): + return self.max_dim + #+END_SRC +** 交叉类特征 + LR 模型作为 Wide & Deep model 的 `wide` 部分,可以输入很 wide 的数据(特征空间的维度很大), + 为了充分利用这个优势,我们将演示交叉组合特征构建成更大维度特征的情况,之后塞入到模型中训练。 + + 这里我们依旧使用模操作来约束最终组合出的特征空间的大小,具体实现是直接在 `IDfeatureGenerator` 中添加一个`gen_cross_feature` 的方法: + + #+BEGIN_SRC python + def gen_cross_fea(self, fea1, fea2): + key = str(fea1) + str(fea2) + return self.gen(key) + #+END_SRC + + 比如,我们觉得原始数据中,`device_id` 和 `site_id` 有一些关联(比如某个 device 倾向于浏览特定 site), + 我们通过组合出两者组合来捕捉这类信息。 +** 特征维度 +*** Deep submodel(DNN)特征 +|------------------+-----------| +| feature | dimention | +|------------------+-----------| +| app_category | 21 | +| site_category | 22 | +| device_conn_type | 5 | +| hour | 24 | +| banner_pos | 7 | +|------------------+-----------| +| Total | 79 | +|------------------+-----------| + +*** Wide submodel(LR)特征 +|---------------------+-----------| +| Feature | Dimention | +|---------------------+-----------| +| id | 10000 | +| site_id | 10000 | +| app_id | 10000 | +| device_id | 10000 | +| device_id X site_id | 1000000 | +|---------------------+-----------| +| Total | 1,040,000 | +|---------------------+-----------| +* 输入到 Paddle 中 +Deep 和 Wide 两部分均以 `sparse_binary_vector` 的格式[1]输入,输入前需要将相关特征拼合,模型最终只接受 3 个 input, +分别是 + +1. `dnn input`,DNN 的输入 +2. `lr input`, LR 的输入 +3. `click`, 标签 + +拼合特征的方法: + +#+BEGIN_SRC python + def concat_sparse_vectors(inputs, dims): + ''' + concaterate sparse vectors into one + + @inputs: list + list of sparse vector + @dims: list of int + dimention of each sparse vector + ''' + res = [] + assert len(inputs) == len(dims) + start = 0 + for no, vec in enumerate(inputs): + for v in vec: + res.append(v + start) + start += dims[no] + return res +#+END_SRC + + +[1] https://github.com/PaddlePaddle/Paddle/blob/develop/doc/api/v1/data_provider/pydataprovider2_en.rst + -- GitLab