diff --git a/README.md b/README.md index 140ea18a0cc029dc93c7ecc12f5c7f5f4e02c6ce..528dffdac055d7e2447c300be7d37080d5cedf57 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,19 @@ # PLSC: PaddlePaddle大规模分类库 ## 简介 -PaddlePaddle大规模分类库(PLSC: PaddlePaddle Large Scale Classification)是 -基于[飞桨平台](https://www.paddlepaddle.org.cn)构建的超大规模分类库,为用 -户提供从训练到部署的大规模分类问题全流程解决方案。 +PaddlePaddle大规模分类库(PLSC: PaddlePaddle Large Scale Classification)是基于[飞桨平台](https://www.paddlepaddle.org.cn)构建的超大规模分类库,为用户提供从训练到部署的大规模分类问题全流程解决方案。 -深度学习中用于解决多分类问题的深度神经网络的最后一层通常是全连接层+Softmax, -并采用交叉熵(Cross-Entropy)算法计算网络的损失函数。由于全连接层的参数量随着 -分类类别数的增长线性增长,当分类类别数相当大时,会面临下面两个主要挑战: +深度学习中用于解决多分类问题的深度神经网络的最后一层通常是全连接层+Softmax,并采用交叉熵(Cross-Entropy)算法计算网络的损失函数。由于全连接层的参数量随着分类类别数的增长线性增长,当分类类别数相当大时,会面临下面两个主要挑战: -1. 参数量过大,超出单个GPU卡的显存容量:假设分类网络最后一层隐层的输出维度为512, -那么当分类类别数为一百万时,最后一层全连接层参数的大小约为2GB(假设以32比特浮点 -数表示参数)。当分类问题的类别数为一亿时(例如,对自然界中的生物进行分类),则 -最后一层全连接层参数的大小接近200GB,远远超过当前GPU的显存容量。 +1. 参数量过大,超出单个GPU卡的显存容量:假设分类网络最后一层隐层的输出维度为512,那么当分类类别数为一百万时,最后一层全连接层参数的大小约为2GB(假设以32比特浮点数表示参数)。当分类问题的类别数为一亿时(例如,对自然界中的生物进行分类),则最后一层全连接层参数的大小接近200GB,远远超过当前GPU的显存容量。 -2. 参数量较大,同步训练方式下通信开销较大:数据并行训练方式下,所有GPU卡之间需 -要同步参数的梯度信息,以完成参数值的同步更新。当参数数量较大时,参数的梯度信息 -数据量同样较大,从而导致参数梯度信息的通信开销较大,影响训练速度。 +2. 参数量较大,同步训练方式下通信开销较大:数据并行训练方式下,所有GPU卡之间需要同步参数的梯度信息,以完成参数值的同步更新。当参数数量较大时,参数的梯度信息数据量同样较大,从而导致参数梯度信息的通信开销较大,影响训练速度。 -为了解决大规模分类问题,我们设计开发了PaddlePaddle大规模分类库PLCS,为用户提供 -从训练到部署的大规模分类问题全流程解决方案。 +为了解决大规模分类问题,我们设计开发了PaddlePaddle大规模分类库PLCS,为用户提供从训练到部署的大规模分类问题全流程解决方案。 ## 设计思想 -解决大规模分类问题的核心思想是采用模型并行方案实现深度神经网络模型的全连接层以 -及之后的损失值计算。 +解决大规模分类问题的核心思想是采用模型并行方案实现深度神经网络模型的全连接层以及之后的损失值计算。 首先,我们回顾大规模分类问题面临的两个主要挑战: @@ -34,27 +23,19 @@ PaddlePaddle大规模分类库(PLSC: PaddlePaddle Large Scale Classification)是 ### 显存优化 -为了解决显存不足的问题,PLSC采用模型并行设计,将深度神经网络的最后一层全连接层切 -分到各个GPU卡。全连接层天然地具有可切分属性,无外乎是一个矩阵乘法和加法(存在偏置 -项的情形下)。假设以100张GPU卡进行模型训练,当分类类别数目为一亿时,每张GPU卡上的 -全连接参数的大小约为2GB,这完全是可接受的。 +为了解决显存不足的问题,PLSC采用模型并行设计,将深度神经网络的最后一层全连接层切分到各个GPU卡。全连接层天然地具有可切分属性,无外乎是一个矩阵乘法和加法(存在偏置项的情形下)。假设以100张GPU卡进行模型训练,当分类类别数目为一亿时,每张GPU卡上的全连接参数的大小约为2GB,这完全是可接受的。 对于全连接层计算,可以表示为矩阵乘法和加法,如下面的公示所示: ![FC计算公示](images/fc_computing.png) -其中,*W*和*b*全连接层参数,*X*是神经网络最后一层隐层的输出。将根据矩阵分块原理,全 -连接层计算又可以进一步地表示为下面的形式: +其中,*W*和*b*全连接层参数,*X*是神经网络最后一层隐层的输出。将根据矩阵分块原理,全连接层计算又可以进一步地表示为下面的形式: ![FC计算公示展开](images/fc_computing_block.png) -这里,*n*是分块的块数。因此,我们可以将神经网络的最后一层全连接参数分布到多张GPU卡, -并在每张卡上分别完成全连接层的部分计算,从而实现整个全连接层的计算,并解决大规模分 -类问题面临的GPU显存空间不足的问题。 +这里,*n*是分块的块数。因此,我们可以将神经网络的最后一层全连接参数分布到多张GPU卡,并在每张卡上分别完成全连接层的部分计算,从而实现整个全连接层的计算,并解决大规模分类问题面临的GPU显存空间不足的问题。 -需要注意的是,由于将神经网络模型最后一层全连接层参数划分到多张GPU卡,因此需要汇总 -各个GPU上的*X*参数,得到全连接层的全局输入*X*’(可以通过集合通信allgather实现),并 -计算全连接层输出: +需要注意的是,由于将神经网络模型最后一层全连接层参数划分到多张GPU卡,因此需要汇总各个GPU上的*X*参数,得到全连接层的全局输入*X*’(可以通过集合通信allgather实现),并计算全连接层输出: ![全局FC计算公示](images/fc_computing_block_global.png) @@ -66,29 +47,23 @@ softmax的计算公示如下图所示: ![softmax计算公示](images/softmax_computing.png) -由于softmax计算是基于全类别的logit值的,因此需要进行全局同步,以计算分母项。这需 -要执行*N*次AllGather操作,这里*N*是参与训练的GPU卡数。这种全局通信方式的开销较大。 +由于softmax计算是基于全类别的logit值的,因此需要进行全局同步,以计算分母项。这需要执行*N*次AllGather操作,这里*N*是参与训练的GPU卡数。这种全局通信方式的开销较大。 -为了减少通信和计算代价,PLSC实现中仅同步其中的分母项。由于各个GPU卡上分母项是一个 -标量,所以可以显著降低通信开销。 +为了减少通信和计算代价,PLSC实现中仅同步其中的分母项。由于各个GPU卡上分母项是一个标量,所以可以显著降低通信开销。 ## PLSC的特征: - 基于源于产业实践的开源深度学习平台[飞桨平台](https://www.paddlepaddle.org.cn) - 飞桨是由百度研发的一款源于产业实践的开源深度学习平台,致力于让深度学习技术的创 - 新与应用更简单。PLSC基于飞桨平台研发,实现与飞桨平台的无缝链接,可以更好地服务 - 产业实践。 + 飞桨是由百度研发的一款源于产业实践的开源深度学习平台,致力于让深度学习技术的创新与应用更简单。PLSC基于飞桨平台研发,实现与飞桨平台的无缝链接,可以更好地服务产业实践。 - 包含多种预训练模型 - 除了PLSC库源码,我们还发布了基于ResNet50模型、ResNet101模型、ResNet152模型的大 - 规模分类模型在多种数据集上的预训练模型,方便用户基于这些预训练模型进行下游任务 - 的fine-tuning。 + + 除了PLSC库源码,我们还发布了基于ResNet50模型、ResNet101模型、ResNet152模型的大规模分类模型在多种数据集上的预训练模型,方便用户基于这些预训练模型进行下游任务的fine-tuning。 - 提供从训练到部署的全流程解决方案 - PLSC库功能包括数据预处理、模型训练、验证和在线预测服务,提供从训练到部署的大规 - 模分类问题全流程解决方案,用户可以基于PLSC库快速、便捷地搭建大规模分类问题解决 - 方案。 + + PLSC库功能包括数据预处理、模型训练、验证和在线预测服务,提供从训练到部署的大规模分类问题全流程解决方案,用户可以基于PLSC库快速、便捷地搭建大规模分类问题解决方案。 ## 预训练模型和性能 @@ -107,15 +82,13 @@ softmax的计算公示如下图所示: | ResNet50 | MS1M-ArcFace | 0.99817 | 0.99827 | 0.99857 | 0.96314 | | ResNet50 | CASIA | 0.9895 | 0.9095 | 0.99057 | 0.915 | -备注:上述模型训练使用的loss_type为'dist_arcface'。更多关于ArcFace的内容请 -参考[ArcFace: Additive Angular Margin Loss for Deep Face Recognition](https://arxiv.org/abs/1801.07698) +备注:上述模型训练使用的loss_type为'dist_arcface'。更多关于ArcFace的内容请参考[ArcFace: Additive Angular Margin Loss for Deep Face Recognition](https://arxiv.org/abs/1801.07698) ## 使用教程 我们提供了一系列使用教程,来帮助用户完成使用PLSC大规模分类库进行训练、评估和部署。 -这一系列文档分为**快速入门**、**基础功能**、**预测部署**和**高级功能**四个部分, -由浅入深地介绍PLSC大规模分类库的使用方法。 +这一系列文档分为**快速入门**、**基础功能**、**预测部署**和**高级功能**四个部分,由浅入深地介绍PLSC大规模分类库的使用方法。 ### 快速入门 diff --git a/docs/api_intro.md b/docs/api_intro.md index 9a1c2e067dac768135ca2fbffddbd17de705e8fe..2411388d123e828bc58868ed49dde5cec0f018c7 100644 --- a/docs/api_intro.md +++ b/docs/api_intro.md @@ -2,8 +2,7 @@ ## 默认配置参数 -PLSC大规模分类库提供了默认配置参数,用于设置训练、评估和模型相关的信息,如训练数 -据集目录、训练轮数等。 +PLSC大规模分类库提供了默认配置参数,用于设置训练、评估和模型相关的信息,如训练数据集目录、训练轮数等。 这些参数信息位于plsc.config模块中,下面给出这些参数的含义和默认值。 diff --git a/docs/base64_preprocessor.md b/docs/base64_preprocessor.md index b23666f0ad1375718b35ff978fab623a07ad33b6..4d0665282c9062ac69b4c4d7bd8b31141be83c94 100644 --- a/docs/base64_preprocessor.md +++ b/docs/base64_preprocessor.md @@ -2,8 +2,7 @@ ## 简介 -实际业务中,一种常见的训练数据存储格式是将图像数据编码为base64格式。训练数据文件 -的每一行存储一张图像的base64数据和该图像的标签,并通常以制表符('\t')分隔。 +实际业务中,一种常见的训练数据存储格式是将图像数据编码为base64格式。训练数据文件的每一行存储一张图像的base64数据和该图像的标签,并通常以制表符('\t')分隔。 通常,所有训练数据文件的文件列表记录在一个单独的文件中,整个训练数据集的目录结构如下: @@ -16,8 +15,7 @@ dataset `-- dataset.part10 ``` -其中,file_list.txt记录训练数据的文件列表,每行代表一个文件,以上面的例子来说, -file_list.txt的文件内容如下: +其中,file_list.txt记录训练数据的文件列表,每行代表一个文件,以上面的例子来说,file_list.txt的文件内容如下: ```shell dataset.part1 @@ -28,12 +26,9 @@ dataset.part10 而数据文件的每一行表示一张图像数据的base64表示,以及以制表符分隔的图像标签。 -对于分布式训练,需要每张GPU卡处理相同数量的图像数据,并且通常需要在训练前做一次 -训练数据的全局shuffle。 +对于分布式训练,需要每张GPU卡处理相同数量的图像数据,并且通常需要在训练前做一次训练数据的全局shuffle。 -本文档介绍Base64格式图像预处理工具,用于在对训练数据做全局shuffle,并将训练数据均分到多个数据文件, -数据文件的数量和训练中使用的GPU卡数相同。当训练数据的总量不能整除GPU卡数时,通常会填充部分图像 -数据(填充的图像数据随机选自训练数据集),以保证总的训练图像数量是GPU卡数的整数倍。 +本文档介绍Base64格式图像预处理工具,用于在对训练数据做全局shuffle,并将训练数据均分到多个数据文件,数据文件的数量和训练中使用的GPU卡数相同。当训练数据的总量不能整除GPU卡数时,通常会填充部分图像数据(填充的图像数据随机选自训练数据集),以保证总的训练图像数量是GPU卡数的整数倍。 ## 工具使用方法 diff --git a/docs/custom_models.md b/docs/custom_models.md index 261a7ec212968d2c168562f036d8eb9281827a7b..243f7c8e07d87ac460c31652c3197d6af764d447 100644 --- a/docs/custom_models.md +++ b/docs/custom_models.md @@ -2,9 +2,7 @@ 默认地,PaddlePaddle大规模分类库构建基于ResNet50模型的训练模型。 -PLSC提供了模型基类plsc.models.base_model.BaseModel,用户可以基于该基类构建自己的 -网络模型。用户自定义的模型类需要继承自该基类,并实现build_network方法,该方法用 -于构建用户自定义模型。 +PLSC提供了模型基类plsc.models.base_model.BaseModel,用户可以基于该基类构建自己的网络模型。用户自定义的模型类需要继承自该基类,并实现build_network方法,该方法用于构建用户自定义模型。 下面的例子给出如何使用BaseModel基类定义用户自己的网络模型, 以及如何使用。 ```python @@ -75,8 +73,7 @@ if __name__ == "__main__": ins.train() ``` -用户自定义模型类需要继承自基类BaseModel,并实现build_network方法,实现用户的自定 -义模型。 +用户自定义模型类需要继承自基类BaseModel,并实现build_network方法,实现用户的自定义模型。 build_network方法的输入如下: * input: 输入图像数据 @@ -84,4 +81,3 @@ build_network方法的输入如下: * is_train: 表示训练阶段还是测试/预测阶段 build_network方法返回用户自定义组网的输出变量。 - diff --git a/docs/distributed_params.md b/docs/distributed_params.md index 3ddd8536262565d51e831be2f8a24b932339e6f2..dfd2dbd00e470a2b4219434454731bfb8092bae6 100644 --- a/docs/distributed_params.md +++ b/docs/distributed_params.md @@ -2,13 +2,11 @@ ## 简介 -对于最后一层全连接层参数(W和b,假设参数b存在,否则,全连接参数仅为W),通常切分到 -所有训练GPU卡。那么,每个GPU卡上只保存部分全连接层参数。 +对于最后一层全连接层参数(W和b,假设参数b存在,否则,全连接参数仅为W),通常切分到所有训练GPU卡。那么,每个GPU卡上只保存部分全连接层参数。 当保存模型时,各个GPU卡的分布式参数均会得到保存。 -在热启动或fine-tuning阶段,如果训练GPU卡数和热启动前或者预训练阶段使用的GPU卡数 -不同时,需要对分布式参数进行转换,以保证分布式参数的数量和训练使用的GPU卡数相同。 +在热启动或fine-tuning阶段,如果训练GPU卡数和热启动前或者预训练阶段使用的GPU卡数不同时,需要对分布式参数进行转换,以保证分布式参数的数量和训练使用的GPU卡数相同。 默认地,当使用train()方法时,会自动进行分布式参数的转换。 @@ -39,5 +37,4 @@ python -m plsc.utils.process_distfc_parameter --help python -m plsc.utils.process_distfc_parameter --nranks=4 --pretrained_model_dir=./output --output_dir=./output_post ``` -需要注意的是,转换后的分布式参数保存目录只包含转换后的分布式参数,而不包含其它模型参数。因此,通常需要使用转换后的分布式参数替换 -预训练模型中的分布式参数。 +需要注意的是,转换后的分布式参数保存目录只包含转换后的分布式参数,而不包含其它模型参数。因此,通常需要使用转换后的分布式参数替换预训练模型中的分布式参数。 diff --git a/docs/export_for_infer.md b/docs/export_for_infer.md index 0d24927a904f737de89bdc0298f87ee011188001..2ee146bddbf5f02368c32a112e9047a1179de0f3 100644 --- a/docs/export_for_infer.md +++ b/docs/export_for_infer.md @@ -1,9 +1,8 @@ # 预测模型导出 -通常,PaddlePaddle大规模分类库在训练过程中保存的模型只保存模型参数信息, -而不包括预测模型结构。为了部署PLSC预测库,需要将预训练模型导出为预测模型。 +通常,PaddlePaddle大规模分类库在训练过程中保存的模型只保存模型参数信息,而不包括预测模型结构。为了部署PLSC预测库,需要将预训练模型导出为预测模型。预测模型包括预测所需要的模型参数和模型结构,用于后续地预测任务(参见[C++预测库使用](./serving.md) -预测模型包括预测所需要的模型参数和模型结构,用于后续地预测任务(参见[C++预测库使用](./serving.md)) +预测模型包括预测所需要的模型参数和模型结构,用于后续地预测任务(参见[C++预测库使用](./serving.md))。 可以通过下面的代码将预训练模型导出为预测模型: @@ -18,5 +17,4 @@ if __name__ == "__main__": ins.convert_for_prediction() ``` -其中'./pretrain_model'目录为预训练模型目录,'./inference_model'为用于预测的模型 -目录。 +其中'./pretrain_model'目录为预训练模型目录,'./inference_model'为用于预测的模型目录。 diff --git a/docs/usage.md b/docs/usage.md index 99f3877cc7c5604138228db762e15cd9472227e0..5631880bee5881ff677089c75c3c2ef046a8805c 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -1,7 +1,6 @@ # 模型训练和评估 -PaddlePaddle大规模分类提供了从训练、评估到预测部署的全流程解决方案。本文档介绍如 -何使用PaddlePaddle大规模分类库快速完成训练、评估和预测部署。 +PaddlePaddle大规模分类提供了从训练、评估到预测部署的全流程解决方案。本文档介绍如何使用PaddlePaddle大规模分类库快速完成训练、评估和预测部署。 ## 数据准备 @@ -17,11 +16,7 @@ train_data/ `-- lfw.bin ``` -其中,*train_data*是用户数据的根目录,*agedb_30.bin*、*cfp_ff.bin*、*cfp_fp.bin* -和*lfw.bin*分别是不同的验证数据集,且这些验证数据集不是全部必须的。本文档教程默认 -使用lfw.bin作为验证数据集,因此在浏览本教程时,请确保lfw.bin验证数据集可用。 -*images*目录包含JPEG格式的训练图像,*label.txt*中的每一行对应一张训练图像以及该 -图像的类别。 +其中,*train_data*是用户数据的根目录,*agedb_30.bin*、*cfp_ff.bin*、*cfp_fp.bin*和*lfw.bin*分别是不同的验证数据集,且这些验证数据集不是全部必须的。本文档教程默认使用lfw.bin作为验证数据集,因此在浏览本教程时,请确保lfw.bin验证数据集可用。*images*目录包含JPEG格式的训练图像,*label.txt*中的每一行对应一张训练图像以及该图像的类别。 *label.txt*文件的内容示例如下: @@ -53,8 +48,7 @@ if __name__ == "__main__": 2. 生成Entry类的实例。 3. 调用Entry类的train方法,即可开始训练。 -默认地,训练阶段每个训练轮次的之后会使用验证集验证模型的效果,当没有验证数据集时, -可以使用*set_with_test(False)* API关闭验证功能。 +默认地,训练阶段每个训练轮次的之后会使用验证集验证模型的效果,当没有验证数据集时,可以使用*set_with_test(False)* API关闭验证功能。 ### 开始训练 @@ -91,8 +85,6 @@ if __name__ == "__main__": ins.test() ``` -默认地,PLSC将训练脚本保存在'./ouput'目录下,并以pass作为区分不同训练轮次模型 -的子目录,例如'./output/0'目录下保存完成第一个轮次的训练后保存的模型。 +默认地,PLSC将训练脚本保存在'./ouput'目录下,并以pass作为区分不同训练轮次模型的子目录,例如'./output/0'目录下保存完成第一个轮次的训练后保存的模型。 -在模型评估阶段,我们首先需要设置训练模型的目录,接着调用Entry类的test方法开始模 -型验证。 +在模型评估阶段,我们首先需要设置训练模型的目录,接着调用Entry类的test方法开始模型验证。