# 如何准备自己的实验 对于一般的深度学习实验,有几个部分需要处理。 1. 按照模型的需要对数据进行预处理,并且按批次迭代数据集; 2. 定义模型以及优化器等组件; 3. 写出训练过程(一般包括 forward/backward 计算,参数更新,log 记录,可视化,定期评估等步骤); 4. 配置并运行实验。 ## 数据处理 对于数据处理,`parakeet.data` 采用了 paddlepaddle 常用的 `Dataset -> DataLoader` 的流程。数据处理流程的概览如下: ```text Dataset --(transform)--> Dataset --+ sampler --+ batch_fn --+-> DataLoader ``` 其中 transform 代表的是对样例的预处理。可以使用 `parakeet.data` 中的 TransformDataset 来从一个 Dataset 构建另一个 Dataset. 得到想要的 Dataset 之后,提供 sampler 和 batch function, 即可据此构建 DataLoader. DataLoader 产生的结果可以直接用作模型的输入。 详细的使用方式参见 [data_cn](./data_cn.md). ## 模型 为了对模型的可复用行和功能做较好的平衡,我们把模型按照其特征分为几种。 对于较为常用,可以作为其他更大的模型的部分的模块,我们尽可能将其实现得足够简单和通用,因为它们会被复用。对于含有可训练参数的模块,一般实现为 `paddle.nn.Layer` 的子类,但它们不是直接面向一个任务,因此不会带上处理未加工的输入和输出的功能。对于不含有可训练参数的模块,可以直接实现为一个函数,其输入输出都是 `paddle.Tensor` 或其集合。 针对一个特定任务的开箱模型,一般实现为 `paddle.nn.Layer` 的子类,是一个任务的核心计算单元。为了方便地处理输入和输出,一般还可以为它添加处理未加工的输入输出的功能。比如对于 NLP 任务来说,尽管神经网络接受的输出是文本的 id, 但是为了使模型能够处理未加工的输入,文本预处理的功能,以及文本转 id 的字典,也都应该视作模型的一部分。 当一个模型足够复杂,对其进行模块化切分是更好的选择,尽管拆分出来的小模块的功能也不一定非常通用,可能只是用于某个模型,但是当作么做有利于代码的清晰简洁时,仍然推荐这么做。 在 parakeet 的目录结构中,复用性较高的模块被放在 [parakeet.modules](../parakeet/modules/), 但是针对特定任务的模型则放在 [parakeet.models](../parakeet/models). 当开发新的模型的时候,开发这需要考虑拆分模块的可行性,以及模块的通用程度,把它们分置于合适的目录。 ## 配置实验 我们使用 yacs 和 argparse 分别处理配置文件解析和命令行参数解析。关于配置的推荐方式,参考 [实验配置](./config_cn.md). ## 训练流程 训练流程一般就是多次训练一个循环体。典型的循环体包含如下的过程: 1. 迭代数据集; 2. 处理批次数据; 3. 神经网络的 forward/backward 计算; 4. 参数更新; 5. 符合一定条件时,在验证数据集上评估模型; 6. 写日志,可视化,以及在某些情况下保存必要的中间结果; 7. 保存模型和优化器的状态。 `数据处理` 包含了数据集以及 batch_function 的定义, 模型和优化器包含了模型的 forward/backward 计算的定义。而在模型和数据都准备好了,我们需要把这些组织起来,完成实验代码。 训练流程的组装,可以参考 [实验流程](./experiment_cn.md). ## 实验模板 实验代码一般以如下的方式组织: ```text ├── README.md (实验的帮助信息) ├── config.py (默认配置) ├── preprocess.py (数据预处理脚本) ├── data.py (Dataset, batch_function 等的定义) ├── synthesis.py (用于生成的代码) ├── train.py (用于训练的代码) └── utils.py (其他必要的辅助函数) ``` 在这个软件源中包含了几个例子,可以在 [Parakeet/examples](../examples) 中查看。这些实验被作为样例提供给用户,可以直接运行。同时也欢迎用户添加新的模型和实验并为 `Parakeet` 贡献代码。