Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
PaddleRec
提交
5a0982fa
P
PaddleRec
项目概览
PaddlePaddle
/
PaddleRec
通知
68
Star
12
Fork
5
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
27
列表
看板
标记
里程碑
合并请求
10
Wiki
1
Wiki
分析
仓库
DevOps
项目成员
Pages
P
PaddleRec
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
27
Issue
27
列表
看板
标记
里程碑
合并请求
10
合并请求
10
Pages
分析
分析
仓库分析
DevOps
Wiki
1
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
5a0982fa
编写于
5月 13, 2020
作者:
C
chengmo
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add reader doc
上级
33fc1750
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
201 addition
and
77 deletion
+201
-77
doc/custom_dataset_reader.md
doc/custom_dataset_reader.md
+187
-60
doc/rec_background.md
doc/rec_background.md
+2
-0
readme.md
readme.md
+12
-17
未找到文件。
doc/custom_dataset_reader.md
浏览文件 @
5a0982fa
# PaddleRec 自定义数据集及Reader
# PaddleRec 自定义数据集及Reader
## dataset数据读取
## 数据集及reader配置简介
为了能高速运行CTR模型的训练,我们使用
`dataset`
API进行高性能的IO,dataset是为多线程及全异步方式量身打造的数据读取方式,每个数据读取线程会与一个训练线程耦合,形成了多生产者-多消费者的模式,会极大的加速我们的模型训练。
如何在我们的训练中引入dataset读取方式呢?无需变更数据格式,只需在我们的训练代码中加入以下内容,便可达到媲美二进制读取的高效率,以下是一个比较完整的流程
:
以
`ctr-dnn`
模型举例
:
### 引入dataset
```
yaml
reader
:
batch_size
:
2
class
:
"
{workspace}/../criteo_reader.py"
train_data_path
:
"
{workspace}/data/train"
reader_debug_mode
:
False
```
有以上4个需要重点关注的配置选项:
-
batch_size: 网络进行小批量训练的一组数据的大小
-
class: 指定数据处理及读取的
`reader`
python文件
-
train_data_path: 训练数据所在地址
-
reader_debug_mode: 测试reader语法,及输出是否符合预期的debug模式的开关
## 自定义数据集
PaddleRec支持模型自定义数据集,在model.config.yaml文件中的reader部分,通过
`train_data_path`
指定数据读取路径。
> 关于数据的tips
>
> - PaddleRec 面向的是推荐与搜索领域,数据以文本格式为主
> - Dataset模式支持读取文本数据压缩后的`.gz`格式
> - Dataset模式下,训练线程与数据读取线程的关系强相关,为了多线程充分利用,`强烈建议将文件拆成多个小文件`,尤其是在分布式训练场景下,可以均衡各个节点的数据量。
## 自定义Reader
数据集准备就绪后,需要适当修改或重写一个新的reader以适配数据集或新组网。
我们以
`ctr-dnn`
网络举例
`reader`
的正确打开方式,网络文件位于
`models/rank/dnn`
。
### Criteo数据集格式
CTR-DNN训练及测试数据集选用
[
Display Advertising Challenge
](
https://www.kaggle.com/c/criteo-display-ad-challenge/
)
所用的Criteo数据集。该数据集包括两部分:训练集和测试集。训练集包含一段时间内Criteo的部分流量,测试集则对应训练数据后一天的广告点击流量。
每一行数据格式如下所示:
```
bash
<label> <integer feature 1> ... <integer feature 13> <categorical feature 1> ... <categorical feature 26>
```
其中
```<label>```
表示广告是否被点击,点击用1表示,未点击用0表示。
```<integer feature>```
代表数值特征(连续特征),共有13个连续特征。
```<categorical feature>```
代表分类特征(离散特征),共有26个离散特征。相邻两个特征用
```\t```
分隔,缺失特征用空格表示。测试集中
```<label>```
特征已被移除。
### Criteo数据集的预处理
1.
通过工厂类
`fluid.DatasetFactory()`
创建一个dataset对象。
数据预处理共包括两步:
2.
将我们定义好的数据输入格式传给dataset,通过
`dataset.set_use_var(inputs)`
实现。
-
将原始训练集按9:1划分为训练集和验证集
3.
指定我们的数据读取方式,由
`dataset_generator.py`
实现数据读取的规则,后面将会介绍读取规则的实现。
-
数值特征(连续特征)需进行归一化处理,但需要注意的是,对每一个特征
```<integer feature i>```
,归一化时用到的最大值并不是用全局最大值,而是取排序后95%位置处的特征值作为最大值,同时保留极值。
4.
指定数据读取的batch_size。
5.
指定数据读取的线程数,该线程数和训练线程应保持一致,两者为耦合的关系。
6.
指定dataset读取的训练文件的列表。
### CTR网络输入的定义
正如前所述,Criteo数据集中,分为连续数据与离散(稀疏)数据,所以整体而言,CTR-DNN模型的数据输入层包括三个,分别是:
`dense_input`
用于输入连续数据,维度由超参数
`dense_feature_dim`
指定,数据类型是归一化后的浮点型数据。
`sparse_input_ids`
用于记录离散数据,在Criteo数据集中,共有26个slot,所以我们创建了名为
`C1~C26`
的26个稀疏参数输入,并设置
`lod_level=1`
,代表其为变长数据,数据类型为整数;最后是每条样本的
`label`
,代表了是否被点击,数据类型是整数,0代表负样例,1代表正样例。
在Paddle中数据输入的声明使用
`paddle.fluid.layers.data()`
,会创建指定类型的占位符,数据IO会依据此定义进行数据的输入。
稀疏参数输入的定义:
```
python
```
python
def
get_dataset
(
inputs
,
args
)
def
sparse_inputs
():
dataset
=
fluid
.
DatasetFactory
().
create_dataset
()
ids
=
envs
.
get_global_env
(
"hyper_parameters.sparse_inputs_slots"
,
None
,
self
.
_namespace
)
dataset
.
set_use_var
(
inputs
)
dataset
.
set_pipe_command
(
"python dataset_generator.py"
)
sparse_input_ids
=
[
dataset
.
set_batch_size
(
args
.
batch_size
)
fluid
.
layers
.
data
(
name
=
"S"
+
str
(
i
),
dataset
.
set_thread
(
int
(
args
.
cpu_num
))
shape
=
[
1
],
file_list
=
[
lod_level
=
1
,
str
(
args
.
train_files_path
)
+
"/%s"
%
x
dtype
=
"int64"
)
for
i
in
range
(
1
,
ids
)
for
x
in
os
.
listdir
(
args
.
train_files_path
)
]
]
logger
.
info
(
"file list: {}"
.
format
(
file_list
))
return
sparse_input_ids
return
dataset
,
file_list
```
```
### 如何指定数据读取规则
稠密参数输入的定义:
```
python
def
dense_input
():
dim
=
envs
.
get_global_env
(
"hyper_parameters.dense_input_dim"
,
None
,
self
.
_namespace
)
在上文我们提到了由
`dataset_generator.py`
实现具体的数据读取规则,那么,怎样为dataset创建数据读取的规则呢?
dense_input_var
=
fluid
.
layers
.
data
(
name
=
"D"
,
以下是
`dataset_generator.py`
的全部代码,具体流程如下:
shape
=
[
dim
],
1.
首先我们需要引入dataset的库,位于
`paddle.fluid.incubate.data_generator`
。
dtype
=
"float32"
)
2.
声明一些在数据读取中会用到的变量,如示例代码中的
`cont_min_`
、
`categorical_range_`
等。
return
dense_input_var
3.
创建一个子类,继承dataset的基类,基类有多种选择,如果是多种数据类型混合,并且需要转化为数值进行预处理的,建议使用
`MultiSlotDataGenerator`
;若已经完成了预处理并保存为数据文件,可以直接以
`string`
的方式进行读取,使用
`MultiSlotStringDataGenerator`
,能够进一步加速。在示例代码,我们继承并实现了名为
`CriteoDataset`
的dataset子类,使用
`MultiSlotDataGenerator`
方法。
```
4.
继承并实现基类中的
`generate_sample`
函数,逐行读取数据。该函数应返回一个可以迭代的reader方法(带有yield的函数不再是一个普通的函数,而是一个生成器generator,成为了可以迭代的对象,等价于一个数组、链表、文件、字符串etc.)
5.
在这个可以迭代的函数中,如示例代码中的
`def reader()`
,我们定义数据读取的逻辑。例如对以行为单位的数据进行截取,转换及预处理。
6.
最后,我们需要将数据整理为特定的格式,才能够被dataset正确读取,并灌入的训练的网络中。简单来说,数据的输出顺序与我们在网络中创建的
`inputs`
必须是严格一一对应的,并转换为类似字典的形式。在示例代码中,我们使用
`zip`
的方法将参数名与数值构成的元组组成了一个list,并将其yield输出。如果展开来看,我们输出的数据形如
`[('dense_feature',[value]),('C1',[value]),('C2',[value]),...,('C26',[value]),('label',[value])]`
标签的定义:
```
python
def
label_input
():
label
=
fluid
.
layers
.
data
(
name
=
"click"
,
shape
=
[
1
],
dtype
=
"int64"
)
return
label
```
组合起来,正确的声明他们:
```
python
```
python
import
paddle.fluid.incubate.data_generator
as
dg
self
.
sparse_inputs
=
sparse_inputs
()
self
.
dense_input
=
dense_input
()
self
.
label_input
=
label_input
()
self
.
_data_var
.
append
(
self
.
dense_input
)
for
input
in
self
.
sparse_inputs
:
self
.
_data_var
.
append
(
input
)
self
.
_data_var
.
append
(
self
.
label_input
)
if
self
.
_platform
!=
"LINUX"
:
self
.
_data_loader
=
fluid
.
io
.
DataLoader
.
from_generator
(
feed_list
=
self
.
_data_var
,
capacity
=
64
,
use_double_buffer
=
False
,
iterable
=
False
)
```
若运行于
**Linux**
环境下,默认使用
**dataset**
模式读取数据集;若运行于
**windows**
或
**mac**
下,默认使用
**dataloader**
模式读取数据集。以上两种方法是paddle.io中提供的不同模式,
`dataset`
运行速度更快,但依赖于linux的环境,因此会有该逻辑判断。
cont_min_
=
[
0
,
-
3
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
]
> Paddle的组网中不支持数据输入为`str`类型,`强烈不建议使用明文保存和读取数据`
cont_max_
=
[
20
,
600
,
100
,
50
,
64000
,
500
,
100
,
50
,
500
,
10
,
10
,
10
,
50
]
cont_diff_
=
[
20
,
603
,
100
,
50
,
64000
,
500
,
100
,
50
,
500
,
10
,
10
,
10
,
50
]
hash_dim_
=
1000001
continuous_range_
=
range
(
1
,
14
)
categorical_range_
=
range
(
14
,
40
)
class
CriteoDataset
(
dg
.
MultiSlotDataGenerator
):
### Criteo Reader写法
```
python
# 引入PaddleRec的Reader基类
from
paddlerec.core.reader
import
Reader
# 引入PaddleRec的读取yaml配置文件的方法
from
paddlerec.core.utils
import
envs
# 定义TrainReader,需要继承 paddlerec.core.reader.Reader
class
TrainReader
(
Reader
):
# 数据预处理逻辑,继承自基类
# 如果无需处理, 使用pass跳过该函数的执行
def
init
(
self
):
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_
=
envs
.
get_global_env
(
"hyper_parameters.sparse_feature_number"
,
None
,
"train.model"
)
self
.
continuous_range_
=
range
(
1
,
14
)
self
.
categorical_range_
=
range
(
14
,
40
)
# 读取数据方法,继承自基类
# 实现可以迭代的reader函数,逐行处理数据
def
generate_sample
(
self
,
line
):
def
generate_sample
(
self
,
line
):
"""
Read the data line by line and process it as a dictionary
"""
def
reader
():
def
reader
():
"""
This function needs to be implemented by the user, based on data format
"""
features
=
line
.
rstrip
(
'
\n
'
).
split
(
'
\t
'
)
features
=
line
.
rstrip
(
'
\n
'
).
split
(
'
\t
'
)
dense_feature
=
[]
dense_feature
=
[]
sparse_feature
=
[]
sparse_feature
=
[]
for
idx
in
continuous_range_
:
for
idx
in
self
.
continuous_range_
:
if
features
[
idx
]
==
""
:
if
features
[
idx
]
==
""
:
dense_feature
.
append
(
0.0
)
dense_feature
.
append
(
0.0
)
else
:
else
:
dense_feature
.
append
(
dense_feature
.
append
(
(
float
(
features
[
idx
])
-
cont_min_
[
idx
-
1
])
/
(
float
(
features
[
idx
])
-
self
.
cont_min_
[
idx
-
1
])
/
cont_diff_
[
idx
-
1
])
self
.
cont_diff_
[
idx
-
1
])
for
idx
in
categorical_range_
:
for
idx
in
self
.
categorical_range_
:
sparse_feature
.
append
(
sparse_feature
.
append
(
[
hash
(
str
(
idx
)
+
features
[
idx
])
%
hash_dim_
])
[
hash
(
str
(
idx
)
+
features
[
idx
])
%
self
.
hash_dim_
])
label
=
[
int
(
features
[
0
])]
label
=
[
int
(
features
[
0
])]
process_line
=
dense_feature
,
sparse_feature
,
label
feature_name
=
[
"D"
]
feature_name
=
[
"dense_feature"
]
for
idx
in
self
.
categorical_range_
:
for
idx
in
categorical_range_
:
feature_name
.
append
(
"S"
+
str
(
idx
-
13
))
feature_name
.
append
(
"C"
+
str
(
idx
-
13
))
feature_name
.
append
(
"label"
)
feature_name
.
append
(
"label"
)
yield
zip
(
feature_name
,
[
dense_feature
]
+
sparse_feature
+
[
label
])
yield
zip
(
feature_name
,
[
dense_feature
]
+
sparse_feature
+
[
label
])
return
reader
return
reader
```
### 如何自定义数据读取规则
在上文我们看到了由
`criteo_reader.py`
实现具体的数据读取规则,那么,怎样为自己的数据集写规则呢?
具体流程如下:
1.
首先我们需要引入Reader基类
```
python
from
paddlerec.core.reader
import
Reader
```
2.
创建一个子类,继承Reader的基类,训练所需Reader命名为
`TrainerReader`
3.
在
`init(self)`
函数中声明一些在数据读取中会用到的变量,如示例代码中的
`cont_min_`
、
`categorical_range_`
等,必要时可以在
`config.yaml`
文件中配置变量,通过
`env.get_global_env()`
拿到。
4.
继承并实现基类中的
`generate_sample(self, line)`
函数,逐行读取数据。该函数应返回一个可以迭代的reader方法(带有yield的函数不再是一个普通的函数,而是一个生成器generator,成为了可以迭代的对象,等价于一个数组、链表、文件、字符串etc.)
5.
在这个可以迭代的函数中,如示例代码中的
`def reader()`
,我们定义数据读取的逻辑。例如对以行为单位的数据进行截取,转换及预处理。
6.
最后,我们需要将数据整理为特定的格式,才能够被dataset正确读取,并灌入的训练的网络中。简单来说,数据的输出顺序与我们在网络中创建的
`inputs`
必须是严格一一对应的,并转换为类似字典的形式。在示例代码中,我们使用
`zip`
的方法将参数名与数值构成的元组组成了一个list,并将其yield输出。如果展开来看,我们输出的数据形如
`[('dense_feature',[value]),('C1',[value]),('C2',[value]),...,('C26',[value]),('label',[value])]`
d
=
CriteoDataset
()
### 调试Reader
d
.
run_from_stdin
()
在Linux下运行时,默认启动
`Dataset`
模式,在Win/Mac下运行时,默认启动
`Dataloader`
模式。
通过在
`config.yaml`
中添加或修改
`reader_debug_mode=True`
打开debug模式,只会结合组网运行reader的部分,读取10条样本,并print,方便您观察格式是否符合预期或隐藏bug。
```
yaml
reader
:
batch_size
:
2
class
:
"
{workspace}/../criteo_reader.py"
train_data_path
:
"
{workspace}/data/train"
reader_debug_mode
:
True
```
```
### 快速调试Dataset
我们可以脱离组网架构,单独验证Dataset的输出是否符合我们预期。使用命令
修改后,使用paddlerec.run执行该修改后的yaml文件,可以观察输出。
`cat 数据文件 | python dataset读取python文件`
进行dataset代码的调试:
```
bash
```
bash
cat
train_data/part-0 | python dataset_generator.py
python
-m
paddlerec.run
-m
./models/rank/dnn/config.yaml
-e
single
```
```
输出的数据格式如下:
### Dataset调试
dataset输出的数据格式如下:
` dense_input:size ; dense_input:value ; sparse_input:size ; sparse_input:value ; ... ; sparse_input:size ; sparse_input:value ; label:size ; label:value `
` dense_input:size ; dense_input:value ; sparse_input:size ; sparse_input:value ; ... ; sparse_input:size ; sparse_input:value ; label:size ; label:value `
理想的输出为(截取了一个片段):
基本规律是对于每个变量,会先输出其维度大小,再输出其具体值。
直接debug
`criteo_reader`
理想的输出为(截取了一个片段):
```
bash
```
bash
...
...
13 0.05 0.00663349917081 0.05 0.0 0.02159375 0.008 0.15 0.04 0.362 0.1 0.2 0.0 0.04 1 715353 1 817085 1 851010 1 833725 1 286835 1 948614 1 881652 1 507110 1 27346 1 646986 1 643076 1 200960 1 18464 1 202774 1 532679 1 729573 1 342789 1 562805 1 880474 1 984402 1 666449 1 26235 1 700326 1 452909 1 884722 1 787527 1 0
13 0.0 0.00497512437811 0.05 0.08 0.207421875 0.028 0.35 0.08 0.082 0.0 0.4 0.0 0.08 1 737395 1 210498 1 903564 1 286224 1 286835 1 906818 1 90
6116 1 67180 1 27346 1 51086 1 142177 1 95024 1 157883 1 873363 1 600281 1 812592 1 228085 1 35900 1 880474 1 984402 1 100885 1 26235 1 410878 1 798162 1 499868 1 306163 1 0
...
...
```
```
可以看到首先输出的是13维的dense参数,随后是分立的sparse参数,最后一个是1维的label,数值为0,输出符合预期。
>使用Dataset的一些注意事项
>使用Dataset的一些注意事项
> - Dataset的基本原理:将数据print到缓存,再由C++端的代码实现读取,因此,我们不能在dataset的读取代码中,加入与数据读取无关的print信息,会导致C++端拿到错误的数据信息。
> - Dataset的基本原理:将数据print到缓存,再由C++端的代码实现读取,因此,我们不能在dataset的读取代码中,加入与数据读取无关的print信息,会导致C++端拿到错误的数据信息。
> - dataset目前只支持在`unbuntu`及`CentOS`等标准Linux环境下使用,在`Windows`及`Mac`下使用时,会产生预料之外的错误,请知悉。
> - dataset目前只支持在`unbuntu`及`CentOS`等标准Linux环境下使用,在`Windows`及`Mac`下使用时,会产生预料之外的错误,请知悉。
\ No newline at end of file
### DataLoader调试
dataloader的输出格式为
`list: [ list[var_1], list[var_2], ... , list[var_3]]`
,每条样本的数据会被放在一个
**list[list]**
中,list[0]为第一个variable。
直接debug
`criteo_reader`
理想的输出为(截取了一个片段):
```
bash
...
[[
0.0, 0.004975124378109453, 0.05, 0.08, 0.207421875, 0.028, 0.35, 0.08, 0.082, 0.0, 0.4, 0.0, 0.08],
[
560746],
[
902436],
[
262029],
[
182633],
[
368411],
[
735166],
[
321120],
[
39572],
[
185732],
[
140298],
[
926671],
[
81559],
[
461249],
[
728372],
[
915018],
[
907965],
[
818961],
[
850958],
[
311492],
[
980340],
[
254960],
[
175041],
[
524857],
[
764893],
[
526288],
[
220126],
[
0]]
...
```
可以看到首先输出的是13维的dense参数的list,随后是分立的sparse参数,各自在一个list中,最后一个是1维的label的list,数值为0,输出符合预期。
doc/rec_background.md
0 → 100644
浏览文件 @
5a0982fa
# 推荐系统背景知识
> 占位
\ No newline at end of file
readme.md
浏览文件 @
5a0982fa
...
@@ -69,9 +69,11 @@
...
@@ -69,9 +69,11 @@
<h2
align=
"center"
>
快速启动
</h2>
<h2
align=
"center"
>
快速启动
</h2>
目前框架内置了多个模型,简单的命令即可使用内置模型开始单机训练和本地1
*
1模拟训练,我们以
`ctr-dnn`
为例介绍PaddleRec的简单使用。
### 一行命令启动训练
### 启动内置模型
目前框架内置了多个模型,简单的命令即可使用内置模型开始单机训练和本地1
*
1模拟训练,我们以
`ctr-dnn`
为例介绍PaddleRec的简单使用。
<h3
align=
"center"
>
单机训练
</h3>
<h3
align=
"center"
>
单机训练
</h3>
...
@@ -97,6 +99,10 @@ python -m fleetrec.run -m fleetrec.models.rank.dnn -d cpu -e local_cluster
...
@@ -97,6 +99,10 @@ python -m fleetrec.run -m fleetrec.models.rank.dnn -d cpu -e local_cluster
python
-m
fleetrec.run
-m
fleetrec.models.rank.dnn
-d
cpu
-e
cluster
python
-m
fleetrec.run
-m
fleetrec.models.rank.dnn
-d
cpu
-e
cluster
```
```
### 启动自定义模型
若您复用内置模型,更改了超参,重新配置了数据后
<h2
align=
"center"
>
支持模型列表
</h2>
<h2
align=
"center"
>
支持模型列表
</h2>
> 部分表格占位待改(大规模稀疏)
> 部分表格占位待改(大规模稀疏)
...
@@ -122,43 +128,32 @@ python -m fleetrec.run -m fleetrec.models.rank.dnn -d cpu -e cluster
...
@@ -122,43 +128,32 @@ python -m fleetrec.run -m fleetrec.models.rank.dnn -d cpu -e cluster
<h2
align=
"center"
>
文档
</h2>
<h2
align=
"center"
>
文档
</h2>
### 新手教程
### 新手教程
*
[
环境要求
](
#环境要求
)
*
[
环境要求
](
#环境要求
)
*
[
安装命令
](
#安装命令
)
*
[
安装命令
](
#安装命令
)
*
[
快速开始
](
#一行命令启动训练
)
*
[
快速开始
](
#一行命令启动训练
)
*
[
推荐系统背景知识
](
doc/
)
### 进阶教程
### 进阶教程
*
[
自定义数据集及Reader
](
doc/custom_dataset_reader.md
)
*
[
自定义数据集及Reader
](
doc/custom_dataset_reader.md
)
*
[
模型调参
](
doc/optimization_model.md
)
*
[
单机训练
](
doc/local_train.md
)
*
[
分布式训练
](
doc/distributed_train.md
)
*
[
分布式训练
](
doc/distributed_train.md
)
*
[
离线预测
](
doc/predict.md
)
### 关于PaddleRec性能
### 关于PaddleRec性能
*
[
Bench
am
rk
](
doc/benchmark.md
)
*
[
Bench
ma
rk
](
doc/benchmark.md
)
### FAQ
### FAQ
*
[
常见问题FAQ
](
doc/faq.md
)
*
[
常见问题FAQ
](
doc/faq.md
)
### 设计文档
*
[
PaddleRec设计文档
](
doc/design.md
)
<h2
align=
"center"
>
社区
</h2>
<h2
align=
"center"
>
社区
</h2>
### 贡献代码
*
[
优化PaddleRec框架
](
doc/contribute.md
)
*
[
新增模型到PaddleRec
](
doc/contribute.md
)
### 反馈
### 反馈
如有意见、建议及使用中的BUG,欢迎在
`GitHub Issue`
提交
如有意见、建议及使用中的BUG,欢迎在
`GitHub Issue`
提交
### 版本历史
### 版本历史
*
[
版本更新
](
#版本更新
)
-
2020.5.14 - PaddleRec v0.1
### 许可证书
### 许可证书
本项目的发布受
[
Apache 2.0 license
](
LICENSE
)
许可认证。
本项目的发布受
[
Apache 2.0 license
](
LICENSE
)
许可认证。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录