diff --git a/ctr/dataset.md b/ctr/dataset.md
new file mode 100644
index 0000000000000000000000000000000000000000..6c437434952980641a50b13c418d49ffd41b0090
--- /dev/null
+++ b/ctr/dataset.md
@@ -0,0 +1,373 @@
+
+
+
+
+
+# 数据集介绍
+
+数据集使用 \`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)特征
+
+
+
+
+
+
+
+
+
+
+
+feature |
+dimention |
+
+
+
+
+
+appcategory |
+21 |
+
+
+
+
+sitecategory |
+22 |
+
+
+
+
+deviceconntype |
+5 |
+
+
+
+
+hour |
+24 |
+
+
+
+
+bannerpos |
+7 |
+
+
+
+
+
+Total |
+79 |
+
+
+
+
+
+
+
+### Wide submodel(LR)特征
+
+
+
+
+
+
+
+
+
+
+
+Feature |
+Dimention |
+
+
+
+
+
+id |
+10000 |
+
+
+
+
+siteid |
+10000 |
+
+
+
+
+appid |
+10000 |
+
+
+
+
+deviceid |
+10000 |
+
+
+
+
+deviceid X siteid |
+1000000 |
+
+
+
+
+
+Total |
+1,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 0000000000000000000000000000000000000000..6c98a159e18ac92ba18e3042b7e75847f29b5bd0
--- /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
+