From bc456a6d88a23f7d3b32db5de2e4b2b88967962c Mon Sep 17 00:00:00 2001 From: chengmo Date: Tue, 2 Jun 2020 00:22:02 +0800 Subject: [PATCH] update doc --- README.md | 28 +++++--- doc/development.md | 163 +++++++++++++++++++++++++++++++++++++++++++++ doc/yaml.md | 57 +++++++++------- 3 files changed, 215 insertions(+), 33 deletions(-) create mode 100644 doc/development.md diff --git a/README.md b/README.md index fe2241c5..895f3c72 100644 --- a/README.md +++ b/README.md @@ -96,9 +96,10 @@ cd paddlerec 修改dnn模型的[超参配置](./models/rank/dnn/config.yaml),例如将迭代训练轮数从10轮修改为5轮: ```yaml -train: - # epochs: 10 - epochs: 5 +runner: +- name: runner1 + class: single_train + epochs: 5 # 10->5 ``` 在Linux环境下,可以使用`vim`等文本编辑工具修改yaml文件: @@ -126,9 +127,9 @@ python -m paddlerec.run -m ./models/rank/dnn/config.yaml 我们以dnn模型为例,在paddlerec代码目录下,修改dnn模型的`config.yaml`文件: ```yaml -train: - #engine: single - engine: local_cluster +runner: +- name: runner1 + class: local_cluster_train ``` 然后启动paddlerec训练: @@ -142,9 +143,9 @@ python -m paddlerec.run -m ./models/rank/dnn/config.yaml 我们以dnn模型为例,在paddlerec代码目录下,首先修改dnn模型`config.yaml`文件: ```yaml -train: - #engine: single - engine: cluster +runner: +- name: runner1 + class: cluster_train ``` 再添加分布式启动配置文件`backend.yaml`,具体配置规则在[分布式训练](doc/distributed_train.md)教程中介绍。最后启动paddlerec训练: @@ -177,7 +178,7 @@ python -m paddlerec.run -m ./models/rank/dnn/config.yaml -b backend.yaml | 多任务 | [ESMM](models/multitask/esmm/model.py) | ✓ | ✓ | ✓ | | 多任务 | [MMOE](models/multitask/mmoe/model.py) | ✓ | ✓ | ✓ | | 多任务 | [ShareBottom](models/multitask/share-bottom/model.py) | ✓ | ✓ | ✓ | -| 重排序 | [Listwise](models/rerank/listwise/model.py) | ✓ | x | ✓ | +| 重排序 | [Listwise](models/rerank/listwise/model.py) | ✓ | x | ✓ | @@ -203,6 +204,13 @@ python -m paddlerec.run -m ./models/rank/dnn/config.yaml -b backend.yaml ### 关于PaddleRec性能 * [Benchmark](doc/benchmark.md) +### 开发者教程 +* [PaddleRec设计文档](doc/design.md) +* [二次开发](doc/development.md) + +### 关于PaddleRec性能 +* [Benchmark](doc/benchmark.md) + ### FAQ * [常见问题FAQ](doc/faq.md) diff --git a/doc/development.md b/doc/development.md new file mode 100644 index 00000000..0c0162ba --- /dev/null +++ b/doc/development.md @@ -0,0 +1,163 @@ +# 二次开发 + +## 如何添加自定义模型 + +当您希望开发自定义模型时,需要继承模型的模板基类,并实现三个必要的方法`init_hyper_parameter`,`intput_data`,`net` + +并按照以下规范添加代码。 + +### 基类的继承 + +继承`paddlerec.core.model`的ModelBase,命名为`Class Model` + +```python +from paddlerec.core.model import ModelBase + + +class Model(ModelBase): + + # 构造函数无需显式指定 + # 若继承,务必调用基类的__init__方法 + def __init__(self, config): + ModelBase.__init__(self, config) + # ModelBase的__init__方法会调用_init_hyper_parameter() + +``` + +### 超参的初始化 + +继承并实现`_init_hyper_parameter`方法(必要),可以在该方法中,从`yaml`文件获取超参或进行自定义操作。如下面的示例: + +所有的envs调用接口在_init_hyper_parameters()方法中实现,同时类成员也推荐在此做声明及初始化。 + +```python + def _init_hyper_parameters(self): + self.feature_size = envs.get_global_env( + "hyper_parameters.feature_size") + self.expert_num = envs.get_global_env("hyper_parameters.expert_num") + self.gate_num = envs.get_global_env("hyper_parameters.gate_num") + self.expert_size = envs.get_global_env("hyper_parameters.expert_size") + self.tower_size = envs.get_global_env("hyper_parameters.tower_size") +``` + + +### 数据输入的定义 +继承并实现`input_data`方法(非必要) + + +#### 直接使用基类的数据读取方法 + +`ModelBase`中的input_data默认实现为slot_reader,在`config.yaml`中分别配置`reader.sparse_slot`及`reader.dense_slot`选项实现`slog:feasign`模式的数据读取。 + +> Slot : Feasign 是什么? +> +> Slot直译是槽位,在Rec工程中,是指某一个宽泛的特征类别,比如用户ID、性别、年龄就是Slot,Feasign则是具体值,比如:12345,男,20岁。 +> +> 在实践过程中,很多特征槽位不是单一属性,或无法量化并且离散稀疏的,比如某用户兴趣爱好有三个:游戏/足球/数码,且每个具体兴趣又有多个特征维度,则在兴趣爱好这个Slot兴趣槽位中,就会有多个Feasign值。 +> +> PaddleRec在读取数据时,每个Slot ID对应的特征,支持稀疏,且支持变长,可以非常灵活的支持各种场景的推荐模型训练。 + +使用示例请参考`rank.dnn`模型。 + +#### 自定义数据输入 + + +如果您不想使用`slot:feasign`模式,则需继承并实现`input_data`接口,接口定义:`def input_data(self, is_infer=False, **kwargs)` + +使用示例如下: + +```python +def input_data(self, is_infer=False, **kwargs): + ser_slot_names = fluid.data( + name='user_slot_names', + shape=[None, 1], + dtype='int64', + lod_level=1) + item_slot_names = fluid.data( + name='item_slot_names', + shape=[None, self.item_len], + dtype='int64', + lod_level=1) + lens = fluid.data(name='lens', shape=[None], dtype='int64') + labels = fluid.data( + name='labels', + shape=[None, self.item_len], + dtype='int64', + lod_level=1) + + train_inputs = [user_slot_names] + [item_slot_names] + [lens] + [labels] + infer_inputs = [user_slot_names] + [item_slot_names] + [lens] + + if is_infer: + return infer_inputs + else: + return train_inputs +``` + +更多数据读取教程,请参考[自定义数据集及Reader](custom_dataset_reader.md) + + +### 组网的定义 + +继承并实现`net`方法(必要) + +- 接口定义`def net(self, inputs, is_infer=False)` +- 自定义网络需在该函数中使用paddle组网,实现前向逻辑,定义网络的Loss及Metrics,通过`is_infer`判断是否为infer网络。 +- 我们强烈建议`train`及`infer`尽量复用相同代码, +- `net`中调用的其他函数以下划线为头进行命名,封装网络中的结构模块,如`_sparse_embedding_layer(self)`。 +- `inputs`为`def input_data()`的输出,若使用`slot_reader`方式,inputs为占位符,无实际意义,通过以下方法拿到dense及sparse的输入 + + ```python + self.sparse_inputs = self._sparse_data_var[1:] + self.dense_input = self._dense_data_var[0] + self.label_input = self._sparse_data_var[0] + ``` + +可以参考官方模型的示例学习net的构造方法。 + +## 如何运行自定义模型 + +记录`model.py`,`config.yaml`及数据读取`reader.py`的文件路径,建议置于同一文件夹下,如`/home/custom_model`下,更改`config.yaml`中的配置选项 + +1. 更改 workerspace为模型文件所在文件夹 +```yaml +workspace: "/home/custom_model" +``` + +2. 更改数据地址及读取reader地址 +```yaml +dataset: +- name: custom_model_train +- data_path: "{workspace}/data/train" # or "/home/custom_model/data/train" +- data_converter: "{workspace}/reader.py" # or "/home/custom_model/reader.py" +``` + +3. 更改执行器的路径配置 +```yaml +mode: train_runner + +runner: +- name: train_runner + class: single_train + device: cpu + epochs: 10 + save_checkpoint_interval: 2 + save_inference_interval: 5 + save_checkpoint_path: "{workspace}/increment" # or "/home/custom_model/increment" + save_inference_path: "{workspace}/inference" # or "/home/custom_model/inference" + print_interval: 10 + +phase: +- name: train + model: "{workspace}/model.py" # or "/home/custom_model/model" + dataset_name: custom_model_train + thread_num: 1 +``` + +4. 使用paddlerec.run方法运行自定义模型 + +```shell +python -m paddlerec.run -m /home/custom_model/config.yaml +``` + +以上~请开始享受你的推荐算法高效开发流程。如有任何问题,欢迎在[issue](https://github.com/PaddlePaddle/PaddleRec/issues)提出,我们会第一时间跟进解决。 diff --git a/doc/yaml.md b/doc/yaml.md index 18492cc7..3dc9c4a5 100644 --- a/doc/yaml.md +++ b/doc/yaml.md @@ -1,46 +1,55 @@ -``` +```yaml # 全局配置 +# Debug 模式开关,Debug模式下,会打印OP的耗时及IO占比 debug: false -workspace: "." + +# 工作区目录 +# 使用文件夹路径,则会在该目录下寻找超参配置,组网,数据等必须文件 +workspace: "/home/demo_model/" +# 若 workspace: paddlerec.models.rank.dnn +# 则会使用官方默认配置与组网 -# 用户可以配多个dataset,exector里不同阶段可以用不同的dataset +# 用户可以指定多个dataset(数据读取配置) +# 运行的不同阶段可以使用不同的dataset dataset: - - name: sample_1 - type: DataLoader #或者QueueDataset + # dataloader 示例 + - name: dataset_1 + type: DataLoader batch_size: 5 data_path: "{workspace}/data/train" - # 用户自定义reader + # 指定自定义的reader.py所在路径 data_converter: "{workspace}/rsc15_reader.py" - - name: sample_2 - type: QueueDataset #或者DataLoader + # QueueDataset 示例 + - name: dataset_2 + type: QueueDataset batch_size: 5 data_path: "{workspace}/data/train" - # 用户可以配置sparse_slots和dense_slots,无需再定义data_converter + # 用户可以配置sparse_slots和dense_slots,无需再定义data_converter,使用默认reader sparse_slots: "click ins_weight 6001 6002 6003 6005 6006 6007 6008 6009" dense_slots: "readlist:9" -#示例一,用户自定义参数,用于组网配置 +# 自定义超参数,主要涉及网络中的模型超参及优化器 hyper_parameters: #优化器 - optimizer: - class: Adam - learning_rate: 0.001 - strategy: "{workspace}/conf/config_fleet.py" - # 用户自定义配置 + optimizer: + class: Adam # 直接配置Optimizer,目前支持sgd/Adam/AdaGrad + learning_rate: 0.001 + strategy: "{workspace}/conf/config_fleet.py" # 使用大规模稀疏pslib模式的特有配置 + # 模型超参 vocab_size: 1000 hid_size: 100 - my_key1: 233 - my_key2: 0.1 -mode: runner1 +# 通过全局参数mode指定当前运行的runner +mode: runner_1 +# runner主要涉及模型的执行环境,如:单机/分布式,CPU/GPU,迭代轮次,模型加载与保存地址 runner: - - name: runner1 # 示例一,train - trainer_class: single_train + - name: runner_1 # 配置一个runner,进行单机的训练 + class: single_train # 配置运行模式的选择,还可以选择:single_infer/local_cluster_train/cluster_train epochs: 10 device: cpu init_model_path: "" @@ -50,14 +59,16 @@ runner: save_checkpoint_path: "xxxx" save_inference_path: "xxxx" - - name: runner2 # 示例二,infer - trainer_class: single_train + - name: runner_2 # 配置一个runner,进行单机的预测 + class: single_infer epochs: 1 device: cpu init_model_path: "afs:/xxx/xxx" - +# 模型在训练时,可能存在多个阶段,每个阶段的组网与数据读取都可能不尽相同 +# 每个runner都会完整的运行所有阶段 +# phase指定运行时加载的模型及reader phase: - name: phase1 model: "{workspace}/model.py" -- GitLab