未验证 提交 e73269c5 编写于 作者: M MRXLT 提交者: GitHub

Merge branch 'master' into master

# PaddlePaddle大规模分类库PLSC
# PLSC: PaddlePaddle大规模分类库
## 简介
PaddlePaddle大规模分类库PLSC (PaddlePaddle Large Scale Classification)是基于[飞桨平台](https://www.paddlepaddle.org.cn)开发的超大规模分类库,为用户提供从训练到部署的全流程大规模分类应用解决方案。
PaddlePaddle大规模分类库(PLSC: PaddlePaddle Large Scale Classification)是
基于[飞桨平台](https://www.paddlepaddle.org.cn)构建的超大规模分类库,为用
户提供从训练到部署的大规模分类问题全流程解决方案。
PLSC具备以下特点:
深度学习中用于解决多分类问题的深度神经网络的最后一层通常是全连接层+Softmax,
并采用交叉熵(Cross-Entropy)算法计算网络的损失函数。由于全连接层的参数量随着
分类类别数的增长线性增长,当分类类别数相当大时,会面临下面两个主要挑战:
1. 参数量过大,超出单个GPU卡的显存容量:假设分类网络最后一层隐层的输出维度为512,
那么当分类类别数为一百万时,最后一层全连接层参数的大小约为2GB(假设以32比特浮点
数表示参数)。当分类问题的类别数为一亿时(例如,对自然界中的生物进行分类),则
最后一层全连接层参数的大小接近200GB,远远超过当前GPU的显存容量。
2. 参数量较大,同步训练方式下通信开销较大:数据并行训练方式下,所有GPU卡之间需
要同步参数的梯度信息,以完成参数值的同步更新。当参数数量较大时,参数的梯度信息
数据量同样较大,从而导致参数梯度信息的通信开销较大,影响训练速度。
为了解决大规模分类问题,我们设计开发了PaddlePaddle大规模分类库PLCS,为用户提供
从训练到部署的大规模分类问题全流程解决方案。
## 设计思想
解决大规模分类问题的核心思想是采用模型并行方案实现深度神经网络模型的全连接层以
及之后的损失值计算。
首先,我们回顾大规模分类问题面临的两个主要挑战:
1. 参数量过大,超出单个GPU卡的显存容量
2. 参数量较大,同步训练方式下通信开销较大
### 显存优化
为了解决显存不足的问题,PLSC采用模型并行设计,将深度神经网络的最后一层全连接层切
分到各个GPU卡。全连接层天然地具有可切分属性,无外乎是一个矩阵乘法和加法(存在偏置
项的情形下)。假设以100张GPU卡进行模型训练,当分类类别数目为一亿时,每张GPU卡上的
全连接参数的大小约为2GB,这完全是可接受的。
对于全连接层计算,可以表示为矩阵乘法和加法,如下面的公示所示:
![FC计算公示](images/fc_computing.png)
其中,*W**b*全连接层参数,*X*是神经网络最后一层隐层的输出。将根据矩阵分块原理,全
连接层计算又可以进一步地表示为下面的形式:
![FC计算公示展开](images/fc_computing_block.png)
这里,*n*是分块的块数。因此,我们可以将神经网络的最后一层全连接参数分布到多张GPU卡,
并在每张卡上分别完成全连接层的部分计算,从而实现整个全连接层的计算,并解决大规模分
类问题面临的GPU显存空间不足的问题。
需要注意的是,由于将神经网络模型最后一层全连接层参数划分到多张GPU卡,因此需要汇总
各个GPU上的*X*参数,得到全连接层的全局输入*X*’(可以通过集合通信allgather实现),并
计算全连接层输出:
![全局FC计算公示](images/fc_computing_block_global.png)
### 通信优化
为了得到多分类任务的损失值,在完成全连接层计算后,通常会使用Softmax+交叉熵操作。
softmax的计算公示如下图所示:
![softmax计算公示](images/softmax_computing.png)
由于softmax计算是基于全类别的logit值的,因此需要进行全局同步,以计算分母项。这需
要执行*N*次AllGather操作,这里*N*是参与训练的GPU卡数。这种全局通信方式的开销较大。
为了减少通信和计算代价,PLSC实现中仅同步其中的分母项。由于各个GPU卡上分母项是一个
标量,所以可以显著降低通信开销。
## PLSC的特征:
- 基于源于产业实践的开源深度学习平台[飞桨平台](https://www.paddlepaddle.org.cn)
- 包含大量的预训练模型 (TBD)
- 提供从训练到部署的全流程解决方案 (TBD)
飞桨是由百度研发的一款源于产业实践的开源深度学习平台,致力于让深度学习技术的创
新与应用更简单。PLSC基于飞桨平台研发,实现与飞桨平台的无缝链接,可以更好地服务
产业实践。
- 包含多种预训练模型
除了PLSC库源码,我们还发布了基于ResNet50模型、ResNet101模型、ResNet152模型的大
规模分类模型在多种数据集上的预训练模型,方便用户基于这些预训练模型进行下游任务
的fine-tuning。
- 提供从训练到部署的全流程解决方案
PLSC库功能包括数据预处理、模型训练、验证和在线预测服务,提供从训练到部署的大规
模分类问题全流程解决方案,用户可以基于PLSC库快速、便捷地搭建大规模分类问题解决
方案。
## 预训练模型和性能
### 预训练模型
我们提供了下面的预训练模型,以帮助用户对下游任务进行fine-tuning。
| 模型 | 描述 |
| :--------------- | :------------- |
| [resnet50_distarcface_ms1m_v2](http://icm.baidu-int.com/user-center/account) | 该模型使用ResNet50网络训练,数据集为MS1M_v2,训练阶段使用的loss_type为'dist_arcface',预训练模型在lfw验证集上的验证精度为0.99817。 |
### 训练性能
| 模型 | 训练集 | lfw | agendb_30 | cfp_ff | cfp_fp |
| :--------------- | :------------- | :------ | :----- | :------ | :---- |
| 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)
## 使用教程
我们提供了一系列使用教程,来帮助用户完成使用PLSC大规模分类库进行训练、评估和部署。
这一系列文档分为__快速入门__、__基础功能__、__预测部署__和__高级功能__四个部分,由浅入深地介绍PLSC大规模分类库的设计思路和使用方法。
这一系列文档分为**快速入门****基础功能****预测部署****高级功能**四个部分,
由浅入深地介绍PLSC大规模分类库的使用方法。
### 快速入门
* [安装说明](docs/installation.md)
* [训练/评估/部署](docs/usage.md)
* [训练和验证](docs/usage.md)
### 基础功能
* [API简介](docs/api_intro.md)
* [自定义模型](docs/custom_models.md)
* [自定义Reader接口]
### 预测部署
......
......@@ -2,7 +2,8 @@
## 默认配置参数
PLSC大规模分类库提供了默认配置参数,用于设置训练、评估和模型相关的信息,如训练数据集目录、训练轮数等。
PLSC大规模分类库提供了默认配置参数,用于设置训练、评估和模型相关的信息,如训练数
据集目录、训练轮数等。
这些参数信息位于plsc.config模块中,下面给出这些参数的含义和默认值。
......@@ -64,19 +65,19 @@ PLSC大规模分类库提供了默认配置参数,用于设置训练、评估
| set_checkpoint_dir(dir) | 设置用于加载的预训练模型的目录 | 类型为字符串 |
| set_warmup_epochs(num) | 设置warmup的轮数 | 类型为int |
| set_loss_type(loss_type) | 设置模型的loss类型 | 类型为字符串 |
| set_image_size(size) | 设置图像尺寸,格式为CHW | 类型为元组 |
| set_image_shape(size) | 设置图像尺寸,格式为CHW | 类型为元组 |
| set_optimizer(optimizer) | 设置训练阶段的optimizer | Optimizer类实例 |
| convert_for_prediction() | 将预训练模型转换为预测模型 | None |
| predict() | 离线预测接口,用于验证线上模型的正确性 | None |
| test() | 模型评估 | None |
| train() | 模型训练 | None |
备注:上述API均为PaddlePaddle大规模分类库PLSC的plsc.entry.Entry类的方法,需要通过该类的实例调用,例如:
备注:上述API均为PaddlePaddle大规模分类库PLSC的Entry类的方法,需要通过该类的实例
调用,例如:
```shell
import plsc.entry as entry
```python
from plsc import Entry
ins = entry.Entry()
ins = Entry()
ins.set_class_num(85742)
ins.train()
```
......@@ -37,7 +37,12 @@ dataset.part10
## 工具使用方法
工具位于tools目录下。
工具位于tools目录下。使用该工具时,需要安装sqlite3模块,可以通过下面的命令安装:
```shell
pip install sqlite3
```
可以通过下面的命令行查看工具的使用帮助信息:
```python
......
......@@ -2,12 +2,14 @@
默认地,PaddlePaddle大规模分类库构建基于ResNet50模型的训练模型。
PLSC提供了模型基类plsc.models.base_model.BaseModel,用户可以基于该基类构建自己的网络模型。用户自定义的模型类需要继承自该基类,并实现build_network方法,该方法用于构建用户自定义模型。
PLSC提供了模型基类plsc.models.base_model.BaseModel,用户可以基于该基类构建自己的
网络模型。用户自定义的模型类需要继承自该基类,并实现build_network方法,该方法用
于构建用户自定义模型。
下面的例子给出如何使用BaseModel基类定义用户自己的网络模型, 以及如何使用。
```python
import paddle.fluid as fluid
import plsc.entry as entry
from plsc import Entry
from plsc.models.base_model import BaseModel
class ResNet(BaseModel):
......@@ -64,20 +66,22 @@ class ResNet(BaseModel):
is_test=False if is_train else True)
return emb
def conv_bn_layer(
... ...
if __name__ == "__main__":
ins = entry.Entry()
ins = Entry()
ins.set_model(ResNet())
ins.train()
```
用户自定义模型类需要继承自基类BaseModel,并实现build_network方法,实现用户的自定义模型。
用户自定义模型类需要继承自基类BaseModel,并实现build_network方法,实现用户的自定
义模型。
build_network方法的输入如下:
* input: 输入图像数据
* label: 图像类别
* is_train: 表示训练阶段还是测试/预测阶段
build_network方法返回用户自定义组网的输出变量,BaseModel类的get_output方法将调用该方法获取用户自定义组网的输出,并自动在其后添加分布式FC层
build_network方法返回用户自定义组网的输出变量。
......@@ -2,20 +2,15 @@
## 简介
对于最后一层全连接层参数(W和b,假设参数b存在,否则,全连接参数仅为W),通常切分到所有训练GPU卡。例如,
假设训练阶段使用的GPU卡数为N,那么
$$W = [W_{1}, W_{2},..., W_{N}$$
$$b = [b_{1}, b_{2},..., b_{N}$$
并且,参数$W_{i}$和$b_{i}$保存在第i个GPU。
对于最后一层全连接层参数(W和b,假设参数b存在,否则,全连接参数仅为W),通常切分到
所有训练GPU卡。那么,每个GPU卡上只保存部分全连接层参数。
当保存模型时,各个GPU卡的分布式参数均会得到保存。
在热启动或fine-tuning阶段,如果训练GPU卡数和热启动前或者预训练阶段使用的GPU卡数不同时,需要
对分布式参数进行转换,以保证分布式参数的数量和训练使用的GPU卡数相同。
在热启动或fine-tuning阶段,如果训练GPU卡数和热启动前或者预训练阶段使用的GPU卡数
不同时,需要对分布式参数进行转换,以保证分布式参数的数量和训练使用的GPU卡数相同。
默认地,当使用plsc.entry.Entry.train()方法时,会自动进行分布式参数的转换。
默认地,当使用train()方法时,会自动进行分布式参数的转换。
## 工具使用方法
......
......@@ -2,17 +2,21 @@
通常,PaddlePaddle大规模分类库在训练过程中保存的模型只保存模型参数信息,
而不包括预测模型结构。为了部署PLSC预测库,需要将预训练模型导出为预测模型。
预测模型包括预测所需要的模型参数和模型结构,用于后续地预测任务(参见[C++预测库使用](./serving.md))
可以通过下面的代码将预训练模型导出为预测模型:
```python
import plsc.entry as entry
from plsc import Entry
if __name__ == "__main__":
ins = entry.Entry()
ins = Entry()
ins.set_checkpoint_dir('./pretrain_model')
ins.set_model_save_dir('./inference_model')
ins.convert_for_prediction()
```
其中'./pretrain_model'目录为预训练模型目录,'./inference_model'为用于预测的模型
目录。
......@@ -29,7 +29,13 @@ conda install -c paddle paddlepaddle-gpu cudatoolkit=9.0
更多安装方式和信息请参考[PaddlePaddle安装说明](https://www.paddlepaddle.org.cn/documentation/docs/zh/beginners_guide/install/index_cn.html)
## 2. 安装大规模分类库
## 2. 安装依赖包
```shell
pip install -r requirements.txt
```
## 3. 安装大规模分类库
```shell
pip install plsc
......
# 混合精度训练
PLSC支持混合精度训练。使用混合精度训练可以提升训练的速度,同时减少训练使用的内存。
可以通过下面的代码设置开启混合精度训练:
```python
from __future__ import print_function
import plsc.entry as entry
def main():
ins = entry.Entry()
ins.set_mixed_precision(True, 1.0)
ins.train()
if __name__ == "__main__":
main()
```
其中,`set_mixed_precision`函数介绍如下:
| API | 描述 | 参数说明 |
| :------------------- | :--------------------| :---------------------- |
| set_mixed_precision(use_fp16, loss_scaling) | 设置混合精度训练 | `use_fp16`为是否开启混合精度训练,默认为False;`loss_scaling`为初始的损失缩放值,默认为1.0|
- `use_fp16`:bool类型,当想要开启混合精度训练时,可将此参数设为True即可。
- `loss_scaling`:float类型,为初始的损失缩放值,这个值有可能会影响混合精度训练的精度,建议设为默认值1.0。
为了提高混合精度训练的稳定性和精度,默认开启了动态损失缩放机制。更多关于混合精度训练的介绍可参考:[混合精度训练](https://arxiv.org/abs/1710.03740)
# 训练、评估和部署
# 模型训练和评估
PaddlePaddle大规模分类提供了从训练、评估到预测部署的全流程解决方案。本文档介绍如何使用PaddlePaddle大规模分类库快速完成训练、评估和预测部署。
PaddlePaddle大规模分类提供了从训练、评估到预测部署的全流程解决方案。本文档介绍如
何使用PaddlePaddle大规模分类库快速完成训练、评估和预测部署。
## 数据准备
......@@ -16,7 +17,11 @@ 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*文件的内容示例如下:
......@@ -37,24 +42,27 @@ images/00000007.jpg 0
### 训练代码
下面的例子给出使用PLSC完成大规模分类训练的脚本*train.py*
```python
import plsc.entry as entry
from plsc import Entry
if __name__ == "__main__":
ins = entry.Entry()
ins = Entry()
ins.train()
```
1. 从plsc包导入entry.Entry类,其是使用PLCS大规模分类库功能的接口类。
1. 从plsc包导入Entry类,其是使用PLCS大规模分类库功能的接口类。
2. 生成Entry类的实例。
3. 调用Entry类的train方法,即可开始训练。
默认地,训练阶段每个训练轮次的之后会使用验证集验证模型的效果,当没有验证数据集时,
可以使用*set_with_test(False)* API关闭验证功能。
### 开始训练
下面的例子给出如何使用上述脚本启动训练任务:
```shell
python -m paddle.distributed.launch \
--cluster_ips="127.0.0.1" \
--cluster_node_ips="127.0.0.1" \
--node_ip="127.0.0.1" \
--selected_gpus=0,1,2,3,4,5,6,7 \
train.py
......@@ -62,31 +70,29 @@ python -m paddle.distributed.launch \
paddle.distributed.launch模块用于启动多机/多卡分布式训练任务脚本,简化分布式训练任务启动过程,各个参数的含义如下:
* cluster_ips: 参与训练的节点的ip地址列表,以逗号分隔;
* cluster_node_ips: 参与训练的节点的ip地址列表,以逗号分隔;
* node_ip: 当前训练节点的ip地址;
* selected_gpus: 每个训练节点所使用的gpu设备列表,以逗号分隔。
## 模型评估
## 模型验证
本教程中,我们使用lfw.bin验证数据集评估训练模型的效果。
### 评估代码
### 验证代码
下面的例子给出使用PLSC完成大规模分类训练的脚本*val.py*
下面的例子给出使用PLSC完成大规模分类验证的脚本*val.py*
```python
import plsc.entry as entry
from plsc import Entry
if __name__ == "__main__":
ins = entry.Entry()
ins = Entry()
ins.set_checkpoint("output/0")
ins.test()
```
默认地,PLSC将训练脚本保存在'./ouput'目录下,并以pass_id作为区分不同训练轮次模型的子目录,例如'./output/0'目录下保存完成第一个轮次的训练后保存的模型。
在模型评估阶段,我们首先需要设置训练模型的目录,接着调用Entry类的test方法开始模型评估。
## 预测部署
默认地,PLSC将训练脚本保存在'./ouput'目录下,并以pass作为区分不同训练轮次模型
的子目录,例如'./output/0'目录下保存完成第一个轮次的训练后保存的模型。
TBD
在模型评估阶段,我们首先需要设置训练模型的目录,接着调用Entry类的test方法开始模
型验证。
numpy>=1.12, <=1.16.4 ; python_version<"3.5"
numpy>=1.12 ; python_version>="3.5"
scipy>=0.19.0, <=1.2.1 ; python_version<"3.5"
paddlepaddle>=1.6.2
scipy ; python_version>="3.5"
Pillow
sklearn
......
......@@ -23,8 +23,7 @@ from plsc.version import plsc_version
REQUIRED_PACKAGES = [
'sklearn', 'easydict', 'paddlepaddle>=1.6.2', 'Pillow',
'numpy', 'scipy'
'sklearn', 'easydict', 'Pillow', 'numpy', 'scipy'
]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册