Merge branch 'PaddlePaddle:release/2.3' into release/2.3

pull/1364/head
Wei Shengyu 2021-11-01 01:32:15 +08:00 committed by GitHub
commit 5059c4d865
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
255 changed files with 2469 additions and 3494 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -1,20 +0,0 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

View File

@ -0,0 +1,296 @@
# 一、数据增强分类实战
本节将基于ImageNet-1K的数据集详细介绍数据增强实验如果想快速体验此方法可以参考[**30分钟玩转PaddleClas进阶版**](../quick_start/quick_start_classification.md)中基于CIFAR100的数据增强实验。如果想了解相关算法的内容请参考[数据增强算法介绍](../algorithm_introduction/DataAugmentation.md)。
## 1.1 参数配置
由于不同的数据增强方式含有不同的超参数,为了便于理解和使用,我们在`configs/DataAugment`里分别列举了8种训练ResNet50的数据增强方式的参数配置文件用户可以在`tools/run.sh`里直接替换配置文件的路径即可使用。此处分别挑选了图像变换、图像裁剪、图像混叠中的一个示例展示,其他参数配置用户可以自查配置文件。
### AutoAugment
`AotoAugment`的图像增广方式的配置如下。`AutoAugment`是在uint8的数据格式上转换的所以其处理过程应该放在归一化操作`NormalizeImage`)之前。
```yaml
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- RandCropImage:
size: 224
- RandFlipImage:
flip_code: 1
- AutoAugment:
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
```
### RandAugment
`RandAugment`的图像增广方式的配置如下,其中用户需要指定其中的参数`num_layers`与`magnitude`,默认的数值分别是`2`和`5`。`RandAugment`是在uint8的数据格式上转换的所以其处理过程应该放在归一化操作`NormalizeImage`)之前。
```yaml
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- RandCropImage:
size: 224
- RandFlipImage:
flip_code: 1
- RandAugment:
num_layers: 2
magnitude: 5
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
```
### TimmAutoAugment
`TimmAutoAugment`的图像增广方式的配置如下,其中用户需要指定其中的参数`config_str`、`interpolation`、`img_size`,默认的数值分别是`rand-m9-mstd0.5-inc1`、`bicubic`、`224`。`TimmAutoAugment`是在uint8的数据格式上转换的所以其处理过程应该放在归一化操作`NormalizeImage`)之前。
```yaml
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- RandCropImage:
size: 224
- RandFlipImage:
flip_code: 1
- TimmAutoAugment:
config_str: rand-m9-mstd0.5-inc1
interpolation: bicubic
img_size: 224
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
```
### Cutout
`Cutout`的图像增广方式的配置如下,其中用户需要指定其中的参数`n_holes`与`length`,默认的数值分别是`1`和`112`。类似其他图像裁剪类的数据增强方式,`Cutout`既可以在uint8格式的数据上操作也可以在归一化`NormalizeImage`)后的数据上操作,此处给出的是在归一化后的操作。
```yaml
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- RandCropImage:
size: 224
- RandFlipImage:
flip_code: 1
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
- Cutout:
n_holes: 1
length: 112
```
### RandomErasing
`RandomErasing`的图像增广方式的配置如下,其中用户需要指定其中的参数`EPSILON`、`sl`、`sh`、`r1`、`attempt`、`use_log_aspect`、`mode`,默认的数值分别是`0.25`、`0.02`、`1.0/3.0`、`0.3`、`10`、`True`、`pixel`。类似其他图像裁剪类的数据增强方式,`RandomErasing`既可以在uint8格式的数据上操作也可以在归一化`NormalizeImage`)后的数据上操作,此处给出的是在归一化后的操作。
```yaml
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- RandCropImage:
size: 224
- RandFlipImage:
flip_code: 1
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
- RandomErasing:
EPSILON: 0.25
sl: 0.02
sh: 1.0/3.0
r1: 0.3
attempt: 10
use_log_aspect: True
mode: pixel
```
### HideAndSeek
`HideAndSeek`的图像增广方式的配置如下。类似其他图像裁剪类的数据增强方式,`HideAndSeek`既可以在uint8格式的数据上操作也可以在归一化`NormalizeImage`)后的数据上操作,此处给出的是在归一化后的操作。
```yaml
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- RandCropImage:
size: 224
- RandFlipImage:
flip_code: 1
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
- HideAndSeek:
```
### GridMask
`GridMask`的图像增广方式的配置如下,其中用户需要指定其中的参数`d1`、`d2`、`rotate`、`ratio`、`mode`, 默认的数值分别是`96`、`224`、`1`、`0.5`、`0`。类似其他图像裁剪类的数据增强方式,`GridMask`既可以在uint8格式的数据上操作也可以在归一化`NormalizeImage`)后的数据上操作,此处给出的是在归一化后的操作。
```yaml
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- RandCropImage:
size: 224
- RandFlipImage:
flip_code: 1
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
- GridMask:
d1: 96
d2: 224
rotate: 1
ratio: 0.5
mode: 0
```
### Mixup
`Mixup`的图像增广方式的配置如下,其中用户需要指定其中的参数`alpha`,默认的数值是`0.2`。类似其他图像混合类的数据增强方式,`Mixup`是在图像做完数据处理后将每个batch内的数据做图像混叠将混叠后的图像和标签输入网络中训练所以其是在图像数据处理图像变换、图像裁剪后操作。
```yaml
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- RandCropImage:
size: 224
- RandFlipImage:
flip_code: 1
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
batch_transform_ops:
- MixupOperator:
alpha: 0.2
```
### Cutmix
`Cutmix`的图像增广方式的配置如下,其中用户需要指定其中的参数`alpha`,默认的数值是`0.2`。类似其他图像混合类的数据增强方式,`Cutmix`是在图像做完数据处理后将每个batch内的数据做图像混叠将混叠后的图像和标签输入网络中训练所以其是在图像数据处理图像变换、图像裁剪后操作。
```yaml
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- RandCropImage:
size: 224
- RandFlipImage:
flip_code: 1
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
batch_transform_ops:
- CutmixOperator:
alpha: 0.2
```
### Mixup与Cutmix同时使用
`Mixup``与Cutmix`同时使用的配置如下,其中用户需要指定额外的参数`prob`,该参数控制不同数据增强的概率,默认为`0.5`。
```yaml
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- RandCropImage:
size: 224
- RandFlipImage:
flip_code: 1
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
- OpSampler:
MixupOperator:
alpha: 0.8
prob: 0.5
CutmixOperator:
alpha: 1.0
prob: 0.5
```
## 1.2 启动命令
当用户配置完训练环境后,类似于训练其他分类任务,只需要将`tools/train.sh`中的配置文件替换成为相应的数据增强方式的配置文件即可。
其中`train.sh`中的内容如下:
```bash
python3 -m paddle.distributed.launch \
--selected_gpus="0,1,2,3" \
--log_dir=ResNet50_Cutout \
tools/train.py \
-c ./ppcls/configs/ImageNet/DataAugment/ResNet50_Cutout.yaml
```
运行`train.sh`
```bash
sh tools/train.sh
```
## 1.3 注意事项
* 由于图像混叠时需对label进行混叠无法计算训练数据的准确率所以在训练过程中没有打印训练准确率。
* 在使用数据增强后,由于训练数据更难,所以训练损失函数可能较大,训练集的准确率相对较低,但其有拥更好的泛化能力,所以验证集的准确率相对较高。
* 在使用数据增强后,模型可能会趋于欠拟合状态,建议可以适当的调小`l2_decay`的值来获得更高的验证集准确率。
* 几乎每一类图像增强均含有超参数我们只提供了基于ImageNet-1k的超参数其他数据集需要用户自己调试超参数具体超参数的含义用户可以阅读相关的论文调试方法也可以参考训练技巧的章节。
## 二、实验结果
基于PaddleClas在ImageNet1k数据集上的分类精度如下。
| 模型 | 初始学习率策略 | l2 decay | batch size | epoch | 数据变化策略 | Top1 Acc | 论文中结论 |
|-------------|------------------|--------------|------------|-------|----------------|------------|----|
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | 标准变换 | 0.7731 | - |
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | AutoAugment | 0.7795 | 0.7763 |
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | mixup | 0.7828 | 0.7790 |
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | cutmix | 0.7839 | 0.7860 |
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | cutout | 0.7801 | - |
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | gridmask | 0.7785 | 0.7790 |
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | random-augment | 0.7770 | 0.7760 |
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | random erasing | 0.7791 | - |
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | hide and seek | 0.7743 | 0.7720 |
**注意**
* 在这里的实验中为了便于对比我们将l2 decay固定设置为1e-4在实际使用中我们推荐尝试使用更小的l2 decay。结合数据增强我们发现将l2 decay由1e-4减小为7e-5均能带来至少0.3~0.5%的精度提升。
* 我们目前尚未对不同策略进行组合并验证效果,这一块后续我们会开展更多的对比实验,敬请期待。

View File

@ -0,0 +1,223 @@
# PaddleClas代码解析
## 1. 整体代码结构解析
### 1.1 整体代码和目录概览
PaddleClas主要代码和目录结构如下
* benchmark: 文件夹下存放了一些shell脚本主要是为了测试PaddleClas中不同模型的速度指标如单卡训练速度指标、多卡训练速度指标等。
* dataset文件夹下存放数据集和用于处理数据集的脚本。脚本负责将数据集处理为适合Dataloader处理的格式。
* deploy部署核心代码文件夹存放的是部署工具支持 python/cpp inference、Hub Serveing、Paddle Lite、Slim离线量化等多种部署方式。
* ppcls训练核心代码文件夹下存放PaddleClas框架主体。配置文件、模型训练、评估、预测、动转静导出等具体代码实现均在这里。
* tools训练、评估、预测、模型动转静导出的入口函数和脚本均在该文件下。
* requirements.txt 文件用于安装 PaddleClas 的依赖项。使用pip进行升级安装使用。
* testsPaddleClas模型从训练到预测的全链路测试验证各功能是否能够正常使用。
### 1.2 训练模块定义
深度学习模型训练过程中,主要包含以下几个核心模块。
* 数据对于有监督任务来说训练数据一般包含原始数据及其标注。在基于单标签的图像分类任务中原始数据指的是图像数据而标注则是该图像数据所属的类比。PaddleClas中训练时需要提供标签文件形式如下每一行包含一条训练样本分别表示图片路径和类别标签用分隔符隔开默认为空格
```
train/n01440764/n01440764_10026.JPEG 0
train/n01440764/n01440764_10027.JPEG 0
```
在代码`ppcls/data/dataloader/common_dataset.py`中,包含`CommonDataset`类,继承自`paddle.io.Dataset`,该数据集类可以通过一个键值进行索引并获取指定样本。`ImageNetDataset`, `LogoDataset`, `CommonDataset` 等数据集类都对这个类别
对于读入的数据,需要通过数据转换,将原始的图像数据进行转换。训练时,标准的数据预处理包含:`DecodeImage`, `RandCropImage`, `RandFlipImage`, `NormalizeImage`, `ToCHWImage`。在配置文件中体现如下,数据预处理主要包含在`transforms`字段中,以列表形式呈现,会按照顺序对数据依次做这些转换。
```yaml
DataLoader:
Train:
dataset:
name: ImageNetDataset
image_root: ./dataset/ILSVRC2012/
cls_label_path: ./dataset/ILSVRC2012/train_list.txt
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- RandCropImage:
size: 224
- RandFlipImage:
flip_code: 1
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
```
PaddleClas 中也包含了 `AutoAugment`, `RandAugment` 等数据增广方法,也可以通过在配置文件中配置,从而添加到训练过程的数据预处理中。每个数据转换的方法均以类实现,方便迁移和复用,更多的数据处理具体实现过程可以参考 `ppcls/data/preprocess/ops/` 下的代码。
对于组成一个 batch 的数据,也可以使用 mixup 或者 cutmix 等方法进行数据增广。 PaddleClas 中集成了 `MixupOperator`, `CutmixOperator`, `FmixOperator` 等基于 batch 的数据增广方法,可以在配置文件中配置 mix 参数进行配置,更加具体的实现可以参考 `ppcls/data/preprocess/batch_ops/batch_operators.py`
图像分类中,数据后处理主要为 `argmax` 操作,在此不再赘述。
* 模型结构
在配置文件中,模型结构定义如下
```yaml
Arch:
name: ResNet50
class_num: 1000
pretrained: False
use_ssld: False
```
`Arch.name` 表示模型名称, `Arch.pretrained` 表示是否添加预训练模型,`use_ssld` 表示是否使用基于 `SSLD` 知识蒸馏得到的预训练模型。所有的模型名称均在 `ppcls/arch/backbone/__init__.py` 中定义。
对应的,在 `ppcls/arch/__init__.py` 中,通过 `build_model` 方法创建模型对象。
```python
def build_model(config):
config = copy.deepcopy(config)
model_type = config.pop("name")
mod = importlib.import_module(__name__)
arch = getattr(mod, model_type)(**config)
return arch
```
* 损失函数
PaddleClas中包含了 `CELoss` , `JSDivLoss`, `TripletLoss`, `CenterLoss` 等损失函数,均定义在 `ppcls/loss` 中。
`ppcls/loss/__init__.py` 文件中,使用 `CombinedLoss` 来构建及合并损失函数不同训练策略中所需要的损失函数与计算方法不同PaddleClas 在构建损失函数过程中,主要考虑了以下几个因素。
1. 是否使用 label smooth
2. 是否使用 mixup 或者 cutmix
3. 是否使用蒸馏方法进行训练
4. 是否是训练 metric learning
用户可以在配置文件中指定损失函数的类型及权重,如在训练中添加 TripletLossV2 ,配置文件如下:
```yaml
Loss:
Train:
- CELoss:
weight: 1.0
- TripletLossV2:
weight: 1.0
margin: 0.5
```
* 优化器和学习率衰减、权重衰减策略
图像分类任务中,`Momentum` 是一种比较常用的优化器, PaddleClas 中提供了 `Momentum``RMSProp`、`Adam`及`AdamW`等几种优化器策略。
权重衰减策略是一种比较常用的正则化方法,主要用于防止模型过拟合。 PaddleClas 中提供了 `L1Decay``L2Decay` 两种权重衰减策略。
学习率衰减是图像分类任务中必不可少的精度提升训练方法, PaddleClas 目前支持 `Cosine` , `Piecewise`, `Linear` 等学习率衰减策略。
在配置文件中,优化器、权重衰减策略、学习率衰减策略可以通过以下的字段进行配置。
```yaml
Optimizer:
name: Momentum
momentum: 0.9
lr:
name: Piecewise
learning_rate: 0.1
decay_epochs: [30, 60, 90]
values: [0.1, 0.01, 0.001, 0.0001]
regularizer:
name: 'L2'
coeff: 0.0001
```
`ppcls/optimizer/__init__.py` 中使用 `build_optimizer` 创建优化器和学习率对象。
```python
def build_optimizer(config, epochs, step_each_epoch, parameters):
config = copy.deepcopy(config)
# step1 build lr
lr = build_lr_scheduler(config.pop('lr'), epochs, step_each_epoch)
logger.debug("build lr ({}) success..".format(lr))
# step2 build regularization
if 'regularizer' in config and config['regularizer'] is not None:
reg_config = config.pop('regularizer')
reg_name = reg_config.pop('name') + 'Decay'
reg = getattr(paddle.regularizer, reg_name)(**reg_config)
else:
reg = None
logger.debug("build regularizer ({}) success..".format(reg))
# step3 build optimizer
optim_name = config.pop('name')
if 'clip_norm' in config:
clip_norm = config.pop('clip_norm')
grad_clip = paddle.nn.ClipGradByNorm(clip_norm=clip_norm)
else:
grad_clip = None
optim = getattr(optimizer, optim_name)(learning_rate=lr,
weight_decay=reg,
grad_clip=grad_clip,
**config)(parameters=parameters)
logger.debug("build optimizer ({}) success..".format(optim))
return optim, lr
```
不同优化器和权重衰减策略均以类的形式实现,具体实现可以参考文件 `ppcls/optimizer/optimizer.py` ;不同的学习率衰减策略可以参考文件 `ppcls/optimizer/learning_rate.py`
* 训练时评估与模型存储
模型在训练的时候可以设置模型保存的间隔也可以选择每隔若干个epoch对验证集进行评估从而可以保存在验证集上精度最佳的模型。配置文件中可以通过下面的字段进行配置。
```yaml
Global:
save_interval: 1 # 模型保存的epoch间隔
eval_during_train: True # 是否进行训练时评估
eval_interval: 1 # 评估的epoch间隔
```
模型存储是通过 Paddle 框架的 `paddle.save()` 函数实现的,存储的是模型的动态图版本,以字典的形式存储,便于继续训练。具体实现如下
```python
def save_model(program, model_path, epoch_id, prefix='ppcls'):
model_path = os.path.join(model_path, str(epoch_id))
_mkdir_if_not_exist(model_path)
model_prefix = os.path.join(model_path, prefix)
paddle.static.save(program, model_prefix)
logger.info(
logger.coloring("Already save model in {}".format(model_path), "HEADER"))
```
在保存的时候有两点需要注意:
1. 只在 0 号节点上保存模型。否则多卡训练的时候,如果所有节点都保存模型到相同的路径,则多个节点写文件时可能会发生写文件冲突,导致最终保存的模型无法被正确加载。
2. 优化器参数也需要存储,方便后续的加载断点进行训练。
* 模型裁剪、量化训练
如果想对模型进行压缩训练,则通过下面字段进行配置
模型裁剪:
```yaml
Slim:
prune:
name: fpgm
pruned_ratio: 0.3
```
模型量化:
```yaml
Slim:
quant:
name: pact
```
训练方法详见模型[裁剪量化使用介绍](../advanced_tutorials/model_prune_quantization.md) 算法介绍详见[裁剪量化算法介绍](../algorithm_introduction/model_prune_quantization.md)。
### 1.3 预测部署代码和方式
* 如果希望在服务端使用 cpp 进行部署,可以参考 [cpp inference 预测教程](../../../deploy/cpp_infer/readme.md) 。
* 如果希望将分类模型部署为服务,可以参考 [hub serving 预测部署教程](../../../deploy/hubserving/readme.md) 。
* 如果希望将对分类模型进行离线量化,可以参考 [模型量化裁剪教程](../advanced_tutorials/model_prune_quantization.md) 中离线量化部分。
* 如果希望在移动端使用分类模型进行预测,可以参考 [PaddleLite 预测部署教程](../../../deploy/lite/readme.md) 。

View File

@ -1,253 +0,0 @@
# 知识蒸馏
## 一、模型压缩方法简介
近年来,深度神经网络在计算机视觉、自然语言处理等领域被验证是一种极其有效的解决问题的方法。通过构建合适的神经网络,加以训练,最终网络模型的性能指标基本上都会超过传统算法。
在数据量足够大的情况下,通过合理构建网络模型的方式增加其参数量,可以显著改善模型性能,但是这又带来了模型复杂度急剧提升的问题。大模型在实际场景中使用的成本较高。
深度神经网络一般有较多的参数冗余,目前有几种主要的方法对模型进行压缩,减小其参数量。如裁剪、量化、知识蒸馏等,其中知识蒸馏是指使用教师模型(teacher model)去指导学生模型(student model)学习特定任务,保证小模型在参数量不变的情况下,得到比较大的性能提升,甚至获得与大模型相似的精度指标[1]。PaddleClas融合已有的蒸馏方法[2,3]提供了一种简单的半监督标签知识蒸馏方案SSLDSimple Semi-supervised Label Distillation基于ImageNet1k分类数据集在ResNet_vd以及MobileNet系列上的精度均有超过3%的绝对精度提升,具体指标如下图所示。
![](../../../images/distillation/distillation_perform_s.jpg)
## 二、SSLD 蒸馏策略
### 2.1 简介
SSLD的流程图如下图所示。
![](../../../images/distillation/ppcls_distillation.png)
首先我们从ImageNet22k中挖掘出了近400万张图片同时与ImageNet-1k训练集整合在一起得到了一个新的包含500万张图片的数据集。然后我们将学生模型与教师模型组合成一个新的网络该网络分别输出学生模型和教师模型的预测分布与此同时固定教师模型整个网络的梯度而学生模型可以做正常的反向传播。最后我们将两个模型的logits经过softmax激活函数转换为soft label并将二者的soft label做JS散度作为损失函数用于蒸馏模型训练。下面以MobileNetV3该模型直接训练精度为75.3%的知识蒸馏为例介绍该方案的核心关键点baseline为79.12%的ResNet50_vd模型蒸馏MobileNetV3训练集为ImageNet1k训练集loss为cross entropy loss迭代轮数为120epoch精度指标为75.6%)。
* 教师模型的选择。在进行知识蒸馏时如果教师模型与学生模型的结构差异太大蒸馏得到的结果反而不会有太大收益。相同结构下精度更高的教师模型对结果也有很大影响。相比于79.12%的ResNet50_vd教师模型使用82.4%的ResNet50_vd教师模型可以带来0.4%的绝对精度收益(`75.6%->76.0%`)。
* 改进loss计算方法。分类loss计算最常用的方法就是cross entropy loss我们经过实验发现在使用soft label进行训练时相对于cross entropy lossKL div loss对模型性能提升几乎无帮助但是使用具有对称特性的JS div loss时在多个蒸馏任务上相比cross entropy loss均有0.2%左右的收益(`76.0%->76.2%`)SSLD中也基于JS div loss展开实验。
* 更多的迭代轮数。蒸馏的baseline实验只迭代了120个epoch。实验发现迭代轮数越多蒸馏效果越好最终我们迭代了360epoch精度指标可以达到77.1%(`76.2%->77.1%`)。
* 无需数据集的真值标签很容易扩展训练集。SSLD的loss在计算过程中仅涉及到教师和学生模型对于相同图片的处理结果经过softmax激活函数处理之后的soft label因此即使图片数据不包含真值标签也可以用来进行训练并提升模型性能。该蒸馏方案的无标签蒸馏策略也大大提升了学生模型的性能上限`77.1%->78.5%`)。
* ImageNet1k蒸馏finetune。我们仅使用ImageNet1k数据使用蒸馏方法对上述模型进行finetune最终仍然可以获得0.4%的性能提升(`78.5%->78.9%`)。
### 2.2 数据选择
* SSLD蒸馏方案的一大特色就是无需使用图像的真值标签因此可以任意扩展数据集的大小考虑到计算资源的限制我们在这里仅基于ImageNet22k数据集对蒸馏任务的训练集进行扩充。在SSLD蒸馏任务中我们使用了`Top-k per class`的数据采样方案[3]。具体步骤如下。
* 训练集去重。我们首先基于SIFT特征相似度匹配的方式对ImageNet22k数据集与ImageNet1k验证集进行去重防止添加的ImageNet22k训练集中包含ImageNet1k验证集图像最终去除了4511张相似图片。部分过滤的相似图片如下所示。
![](../../../images/distillation/22k_1k_val_compare_w_sift.png)
* 大数据集soft label获取对于去重后的ImageNet22k数据集我们使用`ResNeXt101_32x16d_wsl`模型进行预测得到每张图片的soft label。
* Top-k数据选择ImageNet1k数据共有1000类对于每一类找出属于该类并且得分最高的k张图片最终得到一个数据量不超过`1000*k`的数据集某些类上得到的图片数量可能少于k张
* 将该数据集与ImageNet1k的训练集融合组成最终蒸馏模型所使用的数据集数据量为500万。
## 三、实验
* PaddleClas的蒸馏策略为`大数据集训练+ImageNet1k蒸馏finetune`的策略。选择合适的教师模型首先在挑选得到的500万数据集上进行训练然后在ImageNet1k训练集上进行finetune最终得到蒸馏后的学生模型。
### 3.1 教师模型的选择
为了验证教师模型和学生模型的模型大小差异和教师模型的模型精度对蒸馏结果的影响,我们做了几组实验验证。训练策略统一为:`cosine_decay_warmuplr=1.3, epoch=120, bs=2048`,学生模型均为从头训练。
|Teacher Model | Teacher Top1 | Student Model | Student Top1|
|- |:-: |:-: | :-: |
| ResNeXt101_32x16d_wsl | 84.2% | MobileNetV3_large_x1_0 | 75.78% |
| ResNet50_vd | 79.12% | MobileNetV3_large_x1_0 | 75.60% |
| ResNet50_vd | 82.35% | MobileNetV3_large_x1_0 | 76.00% |
从表中可以看出
> 教师模型结构相同时,其精度越高,最终的蒸馏效果也会更好一些。
>
> 教师模型与学生模型的模型大小差异不宜过大,否则反而会影响蒸馏结果的精度。
因此最终在蒸馏实验中对于ResNet系列学生模型我们使用`ResNeXt101_32x16d_wsl`作为教师模型对于MobileNet系列学生模型我们使用蒸馏得到的`ResNet50_vd`作为教师模型。
### 3.2 大数据蒸馏
基于PaddleClas的蒸馏策略为`大数据集训练+imagenet1k finetune`的策略。
针对从ImageNet22k挑选出的400万数据融合imagenet1k训练集组成共500万的训练集进行训练具体地在不同模型上的训练超参及效果如下。
|Student Model | num_epoch | l2_ecay | batch size/gpu cards | base lr | learning rate decay | top1 acc |
| - |:-: |:-: | :-: |:-: |:-: |:-: |
| MobileNetV1 | 360 | 3e-5 | 4096/8 | 1.6 | cosine_decay_warmup | 77.65% |
| MobileNetV2 | 360 | 1e-5 | 3072/8 | 0.54 | cosine_decay_warmup | 76.34% |
| MobileNetV3_large_x1_0 | 360 | 1e-5 | 5760/24 | 3.65625 | cosine_decay_warmup | 78.54% |
| MobileNetV3_small_x1_0 | 360 | 1e-5 | 5760/24 | 3.65625 | cosine_decay_warmup | 70.11% |
| ResNet50_vd | 360 | 7e-5 | 1024/32 | 0.4 | cosine_decay_warmup | 82.07% |
| ResNet101_vd | 360 | 7e-5 | 1024/32 | 0.4 | cosine_decay_warmup | 83.41% |
| Res2Net200_vd_26w_4s | 360 | 4e-5 | 1024/32 | 0.4 | cosine_decay_warmup | 84.82% |
### 3.3 ImageNet1k训练集finetune
对于在大数据集上训练的模型其学习到的特征可能与ImageNet1k数据特征有偏因此在这里使用ImageNet1k数据集对模型进行finetune。finetune的超参和finetune的精度收益如下。
|Student Model | num_epoch | l2_ecay | batch size/gpu cards | base lr | learning rate decay | top1 acc |
| - |:-: |:-: | :-: |:-: |:-: |:-: |
| MobileNetV1 | 30 | 3e-5 | 4096/8 | 0.016 | cosine_decay_warmup | 77.89% |
| MobileNetV2 | 30 | 1e-5 | 3072/8 | 0.0054 | cosine_decay_warmup | 76.73% |
| MobileNetV3_large_x1_0 | 30 | 1e-5 | 2048/8 | 0.008 | cosine_decay_warmup | 78.96% |
| MobileNetV3_small_x1_0 | 30 | 1e-5 | 6400/32 | 0.025 | cosine_decay_warmup | 71.28% |
| ResNet50_vd | 60 | 7e-5 | 1024/32 | 0.004 | cosine_decay_warmup | 82.39% |
| ResNet101_vd | 30 | 7e-5 | 1024/32 | 0.004 | cosine_decay_warmup | 83.73% |
| Res2Net200_vd_26w_4s | 360 | 4e-5 | 1024/32 | 0.004 | cosine_decay_warmup | 85.13% |
### 3.4 数据增广以及基于Fix策略的微调
* 基于前文所述的实验结论,我们在训练的过程中加入自动增广(AutoAugment)[4]同时进一步减小了l2_decay(4e-5->2e-5)最终ResNet50_vd经过SSLD蒸馏策略在ImageNet1k上的精度可以达到82.99%相比之前不加数据增广的蒸馏策略再次增加了0.6%。
* 对于图像分类任务在测试的时候测试尺度为训练尺度的1.15倍左右时,往往在不需要重新训练模型的情况下,模型的精度指标就可以进一步提升[5]对于82.99%的ResNet50_vd在320x320的尺度下测试精度可达83.7%我们进一步使用Fix策略即在320x320的尺度下进行训练使用与预测时相同的数据预处理方法同时固定除FC层以外的所有参数最终在320x320的预测尺度下精度可以达到**84.0%**。
### 3.5 实验过程中的一些问题
* 在预测过程中batch norm的平均值与方差是通过加载预训练模型得到设其模式为test mode。在训练过程中batch norm是通过统计当前batch的信息设其模式为train mode与历史保存信息进行滑动平均计算得到在蒸馏任务中我们发现通过train mode即教师模型的bn实时变化的模式去指导学生模型比通过test mode蒸馏得到的学生模型性能更好一些下面是一组实验结果。因此我们在该蒸馏方案中均使用train mode去得到教师模型的soft label。
|Teacher Model | Teacher Top1 | Student Model | Student Top1|
|- |:-: |:-: | :-: |
| ResNet50_vd | 82.35% | MobileNetV3_large_x1_0 | 76.00% |
| ResNet50_vd | 82.35% | MobileNetV3_large_x1_0 | 75.84% |
## 四、蒸馏模型的应用
### 4.1 使用方法
* 中间层学习率调整。蒸馏得到的模型的中间层特征图更加精细化,因此将蒸馏模型预训练应用到其他任务中时,如果采取和之前相同的学习率,容易破坏中间层特征。而如果降低整体模型训练的学习率,则会带来训练收敛速度慢的问题。因此我们使用了中间层学习率调整的策略。具体地:
* 针对ResNet50_vd我们设置一个学习率倍数列表res block之前的3个conv2d卷积参数具有统一的学习率倍数4个res block的conv2d分别有一个学习率参数共需设置5个学习率倍数的超参。在实验中发现。用于迁移学习finetune分类模型时`[0.1,0.1,0.2,0.2,0.3]`的中间层学习率倍数设置在绝大多数的任务中都性能更好;而在目标检测任务中,`[0.05,0.05,0.05,0.1,0.15]`的中间层学习率倍数设置能够带来更大的精度收益。
* 对于MoblileNetV3_large_x1_0由于其包含15个block我们设置每3个block共享一个学习率倍数参数因此需要共5个学习率倍数的参数最终发现在分类和检测任务中`[0.25,0.25,0.5,0.5,0.75]`的中间层学习率倍数能够带来更大的精度收益。
* 适当的l2 decay。不同分类模型在训练的时候一般都会根据模型设置不同的l2 decay大模型为了防止过拟合往往会设置更大的l2 decay如ResNet50等模型一般设置为`1e-4`而如MobileNet系列模型在训练时往往都会设置为`1e-5~4e-5`防止模型过度欠拟合在蒸馏时亦是如此。在将蒸馏模型应用到目标检测任务中时我们发现也需要调节backbone甚至特定任务模型模型的l2 decay和预训练蒸馏时的l2 decay尽可能保持一致。以Faster RCNN MobiletNetV3 FPN为例我们发现仅修改该参数在COCO2017数据集上就可以带来最多0.5%左右的精度(mAP)提升默认Faster RCNN l2 decay为1e-4我们修改为1e-5~4e-5均有0.3%~0.5%的提升)。
### 4.2 迁移学习finetune
* 为验证迁移学习的效果我们在10个小的数据集上验证其效果。在这里为了保证实验的可对比性我们均使用ImageNet1k数据集训练的标准预处理过程对于蒸馏模型我们也添加了蒸馏模型中间层学习率的搜索。
* 对于ResNet50_vdbaseline为Top1 Acc 79.12%的预训练模型基于grid search搜索得到的最佳精度对比实验则为基于该精度对预训练和中间层学习率进一步搜索得到的最佳精度。下面给出10个数据集上所有baseline和蒸馏模型的精度对比。
| Dataset | Model | Baseline Top1 Acc | Distillation Model Finetune |
|- |:-: |:-: | :-: |
| Oxford102 flowers | ResNete50_vd | 97.18% | 97.41% |
| caltech-101 | ResNete50_vd | 92.57% | 93.21% |
| Oxford-IIIT-Pets | ResNete50_vd | 94.30% | 94.76% |
| DTD | ResNete50_vd | 76.48% | 77.71% |
| fgvc-aircraft-2013b | ResNete50_vd | 88.98% | 90.00% |
| Stanford-Cars | ResNete50_vd | 92.65% | 92.76% |
| SUN397 | ResNete50_vd | 64.02% | 68.36% |
| cifar100 | ResNete50_vd | 86.50% | 87.58% |
| cifar10 | ResNete50_vd | 97.72% | 97.94% |
| Food-101 | ResNete50_vd | 89.58% | 89.99% |
* 可以看出在上面10个数据集上结合适当的中间层学习率倍数设置蒸馏模型平均能够带来1%以上的精度提升。
### 4.3 目标检测
我们基于两阶段目标检测Faster/Cascade RCNN模型验证蒸馏得到的预训练模型的效果。
* ResNet50_vd
设置训练与评测的尺度均为640x640最终COCO上检测指标如下。
| Model | train/test scale | pretrain top1 acc | feature map lr | coco mAP |
|- |:-: |:-: | :-: | :-: |
| Faster RCNN R50_vd FPN | 640/640 | 79.12% | [1.0,1.0,1.0,1.0,1.0] | 34.8% |
| Faster RCNN R50_vd FPN | 640/640 | 79.12% | [0.05,0.05,0.1,0.1,0.15] | 34.3% |
| Faster RCNN R50_vd FPN | 640/640 | 82.18% | [0.05,0.05,0.1,0.1,0.15] | 36.3% |
在这里可以看出,对于未蒸馏模型,过度调整中间层学习率反而降低最终检测模型的性能指标。基于该蒸馏模型,我们也提供了领先的服务端实用目标检测方案,详细的配置与训练代码均已开源,可以参考[PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection/tree/master/configs/rcnn_enhance)。
## 五、SSLD实战
本节将基于ImageNet-1K的数据集详细介绍SSLD蒸馏实验如果想快速体验此方法可以参考[**30分钟玩转PaddleClas进阶版**](../../tutorials/quick_start_professional.md)中基于CIFAR100的SSLD蒸馏实验。
### 5.1 参数配置
实战部分提供了SSLD蒸馏的示例在`ppcls/configs/ImageNet/Distillation/mv3_large_x1_0_distill_mv3_small_x1_0.yaml`中提供了`MobileNetV3_large_x1_0`蒸馏`MobileNetV3_small_x1_0`的配置文件,用户可以在`tools/train.sh`里直接替换配置文件的路径即可使用。
```yaml
Arch:
name: "DistillationModel"
# if not null, its lengths should be same as models
pretrained_list:
# if not null, its lengths should be same as models
freeze_params_list:
- True
- False
models:
- Teacher:
name: MobileNetV3_large_x1_0
pretrained: True
use_ssld: True
- Student:
name: MobileNetV3_small_x1_0
pretrained: False
infer_model_name: "Student"
```
在参数配置中,`freeze_params_list`中需要指定模型是否需要冻结参数,`models`中需要指定Teacher模型和Student模型其中Teacher模型需要加载预训练模型。用户可以直接在此处更改模型。
### 5.2 启动命令
当用户配置完训练环境后,类似于训练其他分类任务,只需要将`tools/train.sh`中的配置文件替换成为相应的蒸馏配置文件即可。
其中`train.sh`中的内容如下:
```bash
python -m paddle.distributed.launch \
--selected_gpus="0,1,2,3" \
--log_dir=mv3_large_x1_0_distill_mv3_small_x1_0 \
tools/train.py \
-c ./ppcls/configs/ImageNet/Distillation/mv3_large_x1_0_distill_mv3_small_x1_0.yaml
```
运行`train.sh`
```bash
sh tools/train.sh
```
### 5.3 注意事项
* 用户在使用SSLD蒸馏之前首先需要在目标数据集上训练一个教师模型该教师模型用于指导学生模型在该数据集上的训练。
* 如果学生模型没有加载预训练模型训练的其他超参数可以参考该学生模型在ImageNet-1k上训练的超参数如果学生模型加载了预训练模型学习率可以调整到原来的1/10或者1/100。
* 在SSLD蒸馏的过程中学生模型只学习soft-label导致训练目标变的更加复杂建议可以适当的调小`l2_decay`的值来获得更高的验证集准确率。
* 若用户准备添加无标签的训练数据只需要将新的训练数据放置在原本训练数据的路径下生成新的数据list即可另外新生成的数据list需要将无标签的数据添加伪标签只是为了统一读数据
> 如果您觉得此文档对您有帮助欢迎star我们的项目[https://github.com/PaddlePaddle/PaddleClas](https://github.com/PaddlePaddle/PaddleClas)
## 参考文献
[1] Hinton G, Vinyals O, Dean J. Distilling the knowledge in a neural network[J]. arXiv preprint arXiv:1503.02531, 2015.
[2] Bagherinezhad H, Horton M, Rastegari M, et al. Label refinery: Improving imagenet classification through label progression[J]. arXiv preprint arXiv:1805.02641, 2018.
[3] Yalniz I Z, Jégou H, Chen K, et al. Billion-scale semi-supervised learning for image classification[J]. arXiv preprint arXiv:1905.00546, 2019.
[4] Cubuk E D, Zoph B, Mane D, et al. Autoaugment: Learning augmentation strategies from data[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2019: 113-123.
[5] Touvron H, Vedaldi A, Douze M, et al. Fixing the train-test resolution discrepancy[C]//Advances in Neural Information Processing Systems. 2019: 8250-8260.

View File

@ -1,7 +0,0 @@
知识蒸馏
================================
.. toctree::
:maxdepth: 3
distillation.md

View File

@ -0,0 +1,229 @@
# PaddleClas 社区贡献指南
### 1.1 PaddleClas 分支说明
PaddleClas 未来将维护 2 种分支,分别为:
* release/x.x 系列分支:为稳定的发行版本分支,会适时打 tag 发布版本,适配 Paddle 的 release 版本。当前最新的分支为 release/2.3 分支,是当前默认分支,适配 Paddle v2.1.0 。随着版本迭代, release/x.x 系列分支会越来越多,默认维护最新版本的 release 分支,前 1 个版本分支会修复 bug ,其他的分支不再维护。
* develop 分支:为开发分支,适配 Paddle 的 develop 版本,主要用于开发新功能。如果有同学需要进行二次开发,请选择 develop 分支。为了保证 develop 分支能在需要的时候拉出 release/x.x 分支, develop 分支的代码只能使用 Paddle 最新 release 分支中有效的 api 。也就是说,如果 Paddle develop 分支中开发了新的 api但尚未出现在 release 分支代码中,那么请不要在 PaddleClas 中使用。除此之外,对于不涉及 api 的性能优化、参数调整、策略更新等,都可以正常进行开发。
PaddleClas 的历史分支,未来将不再维护。考虑到一些同学可能仍在使用,这些分支还会继续保留:
* release/static 分支:这个分支曾用于静态图的开发与测试,目前兼容 >=1.7 版本的 Paddle 。如果有特殊需求,要适配旧版本的 Paddle ,那还可以使用这个分支,但除了修复 bug 外不再更新代码。
* dygraph-dev 分支:这个分支将不再维护,也不再接受新的代码,请使用的同学尽快迁移到 develop 分支。
PaddleClas 欢迎大家向 repo 中积极贡献代码,下面给出一些贡献代码的基本流程。
### 1.2 PaddleClas 代码提交流程与规范
#### 1.2.1 fork 和 clone 代码
* 跳转到 [PaddleClas GitHub首页](https://github.com/PaddlePaddle/PaddleClas) ,然后单击 Fork 按钮,生成自己目录下的仓库,比如 `https://github.com/USERNAME/PaddleClas`
<div align="center">
<img src="../../images/quick_start/community/001_fork.png" width = "600" />
</div>
* 将远程仓库 clone 到本地
```shell
# 拉取develop分支的代码
git clone https://github.com/USERNAME/PaddleClas.git -b develop
cd PaddleClas
```
clone 的地址可以从下面获取
<div align="center">
<img src="../../images/quick_start/community/002_clone.png" width = "600" />
</div>
#### 1.2.2 和远程仓库建立连接
首先通过 `git remote -v` 查看当前远程仓库的信息。
```
origin https://github.com/USERNAME/PaddleClas.git (fetch)
origin https://github.com/USERNAME/PaddleClas.git (push)
```
上面的信息只包含了 clone 的远程仓库的信息,也就是自己用户名下的 PaddleClas ,接下来我们创建一个原始 PaddleClas 仓库的远程主机,命名为 upstream 。
```shell
git remote add upstream https://github.com/PaddlePaddle/PaddleClas.git
```
使用 `git remote -v` 查看当前远程仓库的信息,输出如下,发现包括了 origin 和 upstream 2 个远程仓库。
```
origin https://github.com/USERNAME/PaddleClas.git (fetch)
origin https://github.com/USERNAME/PaddleClas.git (push)
upstream https://github.com/PaddlePaddle/PaddleClas.git (fetch)
upstream https://github.com/PaddlePaddle/PaddleClas.git (push)
```
这主要是为了后续在提交 pull request (PR) 时,始终保持本地仓库最新。
#### 1.2.3 创建本地分支
可以基于当前分支创建新的本地分支,命令如下。
```shell
git checkout -b new_branch
```
也可以基于远程或者上游的分支创建新的分支,命令如下。
```shell
# 基于用户远程仓库(origin)的develop创建new_branch分支
git checkout -b new_branch origin/develop
# 基于上游远程仓库(upstream)的develop创建new_branch分支
# 如果需要从upstream创建新的分支需要首先使用git fetch upstream获取上游代码
git checkout -b new_branch upstream/develop
```
最终会显示切换到新的分支,输出信息如下
```
Branch new_branch set up to track remote branch develop from upstream.
Switched to a new branch 'new_branch'
```
#### 1.2.4 使用 pre-commit 勾子
Paddle 开发人员使用 pre-commit 工具来管理 Git 预提交钩子。 它可以帮助我们格式化源代码C++Python在提交commit前自动检查一些基本事宜如每个文件只有一个 EOLGit 中不要添加大文件等)。
pre-commit 测试是 Travis-CI 中单元测试的一部分,不满足钩子的 PR 不能被提交到 PaddleClas ,首先安装并在当前目录运行它:
```shell
pip install pre-commit
pre-commit install
```
* **注意**
1. Paddle 使用 clang-format 来调整 C/C++ 源代码格式,请确保 `clang-format` 版本在 3.8 以上。
2. 通过 `pip install pre-commit``conda install -c conda-forge pre-commit` 安装的 `yapf` 稍有不同的PaddleClas 开发人员使用的是 `pip install pre-commit`
#### 1.2.5 修改与提交代码
可以通过 `git status` 查看改动的文件。
对 PaddleClas 的 `README.md` 做了一些修改,希望提交上去。则可以通过以下步骤
```shell
git add README.md
pre-commit
```
重复上述步骤,直到 pre-comit 格式检查不报错。如下所示。
<div align="center">
<img src="../../images/quick_start/community/003_precommit_pass.png" width = "600" />
</div>
使用下面的命令完成提交。
```shell
git commit -m "your commit info"
```
#### 1.2.6 保持本地仓库最新
获取 upstream 的最新代码并更新当前分支。这里的 upstream 来自于 1.2 节的`和远程仓库建立连接`部分。
```shell
git fetch upstream
# 如果是希望提交到其他分支则需要从upstream的其他分支pull代码这里是develop
git pull upstream develop
```
#### 1.2.7 push到远程仓库
```shell
git push origin new_branch
```
#### 1.2.8 提交Pull Request
点击 new pull request选择本地分支和目标分支如下图所示。在 PR 的描述说明中,填写该 PR 所完成的功能。接下来等待 review ,如果有需要修改的地方,参照上述步骤更新 origin 中的对应分支即可。
<div align="center">
<img src="../../images/quick_start/community/004_create_pr.png" width = "600" />
</div>
#### 1.2.9 签署 CLA 协议和通过单元测试
* 签署 CLA
在首次向 PaddlePaddle 提交 Pull Request 时,您需要您签署一次 CLA (Contributor License Agreement) 协议,以保证您的代码可以被合入,具体签署方式如下:
1. 请您查看 PR 中的 Check 部分,找到 license/cla ,并点击右侧 detail ,进入 CLA 网站
2. 点击 CLA 网站中的 `Sign in with GitHub to agree` , 点击完成后将会跳转回您的 Pull Request 页面
#### 1.2.10 删除分支
* 删除远程分支
在 PR 被 merge 进主仓库后,我们可以在 PR 的页面删除远程仓库的分支。
也可以使用 `git push origin :分支名` 删除远程分支,如:
```shell
git push origin :new_branch
```
* 删除本地分支
```shell
# 切换到develop分支否则无法删除当前分支
git checkout develop
# 删除new_branch分支
git branch -D new_branch
```
#### 1.2.11 提交代码的一些约定
为了使官方维护人员在评审代码时更好地专注于代码本身,请您每次提交代码时,遵守以下约定:
1请保证 Travis-CI 中单元测试能顺利通过。如果没过,说明提交的代码存在问题,官方维护人员一般不做评审。
2提交 Pull Request前
请注意 commit 的数量。
原因:如果仅仅修改一个文件但提交了十几个 commit ,每个 commit 只做了少量的修改,这会给评审人带来很大困扰。评审人需要逐一查看每个 commit 才能知道做了哪些修改,且不排除 commit 之间的修改存在相互覆盖的情况。
建议:每次提交时,保持尽量少的 commit ,可以通过 `git commit --amend` 补充上次的 commit 。对已经 Push 到远程仓库的多个 commit ,可以参考 [squash commits after push](https://stackoverflow.com/questions/5667884/how-to-squash-commits-in-git-after-they-have-been-pushed) 。
请注意每个 commit 的名称:应能反映当前 commit 的内容,不能太随意。
3如果解决了某个 Issue 的问题,请在该 Pull Request 的第一个评论框中加上: `fix #issue_number` ,这样当该 Pull Request 被合并后,会自动关闭对应的 Issue 。关键词包括: close, closes, closed, fix, fixes, fixed, resolve, resolves, resolved ,请选择合适的词汇。详细可参考 [Closing issues via commit messages](https://help.github.com/articles/closing-issues-via-commit-messages) 。
此外,在回复评审人意见时,请您遵守以下约定:
1官方维护人员的每一个 review 意见都希望得到回复,这样会更好地提升开源社区的贡献。
- 对评审意见同意且按其修改完的,给个简单的 Done 即可;
- 对评审意见不同意的,请给出您自己的反驳理由。
2如果评审意见比较多,
- 请给出总体的修改情况。
- 请采用 `start a review` 进行回复,而非直接回复的方式。原因是每个回复都会发送一封邮件,会造成邮件灾难。
## 2. 总结
* 开源社区依赖于众多开发者与用户的贡献和反馈,在这里感谢与期待大家向 PaddleClas 提出宝贵的意见与 Pull Request ,希望我们可以一起打造一个领先实用全面的图像识别代码仓库!
## 3. 参考文献
1. [PaddlePaddle本地开发指南](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/08_contribution/index_cn.html)
2. [向开源框架提交pr的过程](https://blog.csdn.net/vim_wj/article/details/78300239)

View File

@ -1,7 +0,0 @@
图像增广
================================
.. toctree::
:maxdepth: 3
ImageAugment.md

View File

@ -1,9 +0,0 @@
高阶使用
================================
.. toctree::
:maxdepth: 1
image_augmentation/index
distillation/index
multilabel/index

View File

@ -0,0 +1,253 @@
# 知识蒸馏
## 一、模型压缩与知识蒸馏方法简介
近年来,深度神经网络在计算机视觉、自然语言处理等领域被验证是一种极其有效的解决问题的方法。通过构建合适的神经网络,加以训练,最终网络模型的性能指标基本上都会超过传统算法。
在数据量足够大的情况下,通过合理构建网络模型的方式增加其参数量,可以显著改善模型性能,但是这又带来了模型复杂度急剧提升的问题。大模型在实际场景中使用的成本较高。
深度神经网络一般有较多的参数冗余,目前有几种主要的方法对模型进行压缩,减小其参数量。如裁剪、量化、知识蒸馏等,其中知识蒸馏是指使用教师模型 (teacher model) 去指导学生模型 (student model) 学习特定任务,保证小模型在参数量不变的情况下,得到比较大的性能提升,甚至获得与大模型相似的精度指标 [1]。 PaddleClas 融合已有的蒸馏方法 [2,3] ,提供了一种简单的半监督标签知识蒸馏方案 SSLDSimple Semi-supervised Label Distillation ,基于 ImageNet1k 分类数据集,在 ResNet_vd 以及 MobileNet 系列上的精度均有超过 3% 的绝对精度提升,具体指标如下图所示。
<div align="center">
<img src="../../images/distillation/distillation_perform_s.jpg" width = "600" />
</div>
## 二、SSLD 蒸馏策略
### 2.1 简介
SSLD 的流程图如下图所示。
<div align="center">
<img src="../../images/distillation/ppcls_distillation.png" width = "600" />
</div>
首先,我们从 ImageNet22k 中挖掘出了近400万张图片同时与 ImageNet-1k 训练集整合在一起,得到了一个新的包含 500 万张图片的数据集。然后,我们将学生模型与教师模型组合成一个新的网络,该网络分别输出学生模型和教师模型的预测分布,与此同时,固定教师模型整个网络的梯度,而学生模型可以做正常的反向传播。最后,我们将两个模型的 logits 经过 softmax 激活函数转换为 soft label ,并将二者的 soft label 做 JS 散度作为损失函数,用于蒸馏模型训练。下面以 MobileNetV3 (该模型直接训练,精度为 75.3% 的知识蒸馏为例,介绍该方案的核心关键点( baseline 为 79.12% 的 ResNet50_vd 模型蒸馏 MobileNetV3 ,训练集为 ImageNet1k 训练集, loss 为 cross entropy loss ,迭代轮数为 120epoch ,精度指标为 75.6% )。
* 教师模型的选择。在进行知识蒸馏时,如果教师模型与学生模型的结构差异太大,蒸馏得到的结果反而不会有太大收益。相同结构下,精度更高的教师模型对结果也有很大影响。相比于 79.12% 的 ResNet50_vd 教师模型,使用 82.4% 的 ResNet50_vd 教师模型可以带来 0.4% 的绝对精度收益( `75.6%->76.0%` )。
* 改进 loss 计算方法。分类 loss 计算最常用的方法就是 cross entropy loss ,我们经过实验发现,在使用 soft label 进行训练时,相对于 cross entropy loss KL div loss 对模型性能提升几乎无帮助,但是使用具有对称特性的 JS div loss 时,在多个蒸馏任务上相比 cross entropy loss 均有 0.2% 左右的收益( `76.0%->76.2%` ) SSLD 中也基于 JS div loss 展开实验。
* 更多的迭代轮数。蒸馏的 baseline 实验只迭代了 120 个 epoch 。实验发现,迭代轮数越多,蒸馏效果越好,最终我们迭代了 360epoch ,精度指标可以达到 77.1%(`76.2%->77.1%`) 。
* 无需数据集的真值标签,很容易扩展训练集。 SSLD 的 loss 在计算过程中,仅涉及到教师和学生模型对于相同图片的处理结果(经过 softmax 激活函数处理之后的 soft label ),因此即使图片数据不包含真值标签,也可以用来进行训练并提升模型性能。该蒸馏方案的无标签蒸馏策略也大大提升了学生模型的性能上限( `77.1%->78.5%` )。
* ImageNet1k 蒸馏 finetune 。 我们仅使用 ImageNet1k 数据,使用蒸馏方法对上述模型进行 finetune ,最终仍然可以获得 0.4% 的性能提升( `78.5%->78.9%` )。
### 2.2 数据选择
* SSLD 蒸馏方案的一大特色就是无需使用图像的真值标签,因此可以任意扩展数据集的大小,考虑到计算资源的限制,我们在这里仅基于 ImageNet22k 数据集对蒸馏任务的训练集进行扩充。在 SSLD 蒸馏任务中,我们使用了 `Top-k per class` 的数据采样方案 [3] 。具体步骤如下。
* 训练集去重。我们首先基于 SIFT 特征相似度匹配的方式对 ImageNet22k 数据集与 ImageNet1k 验证集进行去重,防止添加的 ImageNet22k 训练集中包含 ImageNet1k 验证集图像,最终去除了 4511 张相似图片。部分过滤的相似图片如下所示。
<div align="center">
<img src="../../images/distillation/22k_1k_val_compare_w_sift.png" width = "600" />
</div>
* 大数据集 soft label 获取,对于去重后的 ImageNet22k 数据集,我们使用 `ResNeXt101_32x16d_wsl` 模型进行预测,得到每张图片的 soft label 。
* Top-k 数据选择, ImageNet1k 数据共有 1000 类,对于每一类,找出属于该类并且得分最高的 `k` 张图片,最终得到一个数据量不超过`1000*k`的数据集(某些类上得到的图片数量可能少于 `k` 张)。
* 将该数据集与 ImageNet1k 的训练集融合组成最终蒸馏模型所使用的数据集,数据量为 500 万。
## 三、实验
* PaddleClas 的蒸馏策略为`大数据集训练 + ImageNet1k 蒸馏 finetune`的策略。选择合适的教师模型,首先在挑选得到的 500 万数据集上进行训练,然后在 ImageNet1k 训练集上进行 finetune最终得到蒸馏后的学生模型。
### 3.1 教师模型的选择
为了验证教师模型和学生模型的模型大小差异和教师模型的模型精度对蒸馏结果的影响,我们做了几组实验验证。训练策略统一为:`cosine_decay_warmuplr=1.3, epoch=120, bs=2048`,学生模型均为从头训练。
|Teacher Model | Teacher Top1 | Student Model | Student Top1|
|- |:-: |:-: | :-: |
| ResNeXt101_32x16d_wsl | 84.2% | MobileNetV3_large_x1_0 | 75.78% |
| ResNet50_vd | 79.12% | MobileNetV3_large_x1_0 | 75.60% |
| ResNet50_vd | 82.35% | MobileNetV3_large_x1_0 | 76.00% |
从表中可以看出
> 教师模型结构相同时,其精度越高,最终的蒸馏效果也会更好一些。
>
> 教师模型与学生模型的模型大小差异不宜过大,否则反而会影响蒸馏结果的精度。
因此最终在蒸馏实验中对于ResNet系列学生模型我们使用 `ResNeXt101_32x16d_wsl` 作为教师模型;对于 MobileNet 系列学生模型,我们使用蒸馏得到的 `ResNet50_vd` 作为教师模型。
### 3.2 大数据蒸馏
基于 PaddleClas 的蒸馏策略为`大数据集训练 + imagenet1k finetune` 的策略。
针对从 ImageNet22k 挑选出的 400 万数据,融合 imagenet1k 训练集,组成共 500 万的训练集进行训练,具体地,在不同模型上的训练超参及效果如下。
|Student Model | num_epoch | l2_ecay | batch size/gpu cards | base lr | learning rate decay | top1 acc |
| - |:-: |:-: | :-: |:-: |:-: |:-: |
| MobileNetV1 | 360 | 3e-5 | 4096/8 | 1.6 | cosine_decay_warmup | 77.65% |
| MobileNetV2 | 360 | 1e-5 | 3072/8 | 0.54 | cosine_decay_warmup | 76.34% |
| MobileNetV3_large_x1_0 | 360 | 1e-5 | 5760/24 | 3.65625 | cosine_decay_warmup | 78.54% |
| MobileNetV3_small_x1_0 | 360 | 1e-5 | 5760/24 | 3.65625 | cosine_decay_warmup | 70.11% |
| ResNet50_vd | 360 | 7e-5 | 1024/32 | 0.4 | cosine_decay_warmup | 82.07% |
| ResNet101_vd | 360 | 7e-5 | 1024/32 | 0.4 | cosine_decay_warmup | 83.41% |
| Res2Net200_vd_26w_4s | 360 | 4e-5 | 1024/32 | 0.4 | cosine_decay_warmup | 84.82% |
### 3.3 ImageNet1k 训练集 finetune
对于在大数据集上训练的模型,其学习到的特征可能与 ImageNet1k 数据特征有偏,因此在这里使用 ImageNet1k 数据集对模型进行 finetune。 finetune 的超参和 finetune 的精度收益如下。
|Student Model | num_epoch | l2_ecay | batch size/gpu cards | base lr | learning rate decay | top1 acc |
| - |:-: |:-: | :-: |:-: |:-: |:-: |
| MobileNetV1 | 30 | 3e-5 | 4096/8 | 0.016 | cosine_decay_warmup | 77.89% |
| MobileNetV2 | 30 | 1e-5 | 3072/8 | 0.0054 | cosine_decay_warmup | 76.73% |
| MobileNetV3_large_x1_0 | 30 | 1e-5 | 2048/8 | 0.008 | cosine_decay_warmup | 78.96% |
| MobileNetV3_small_x1_0 | 30 | 1e-5 | 6400/32 | 0.025 | cosine_decay_warmup | 71.28% |
| ResNet50_vd | 60 | 7e-5 | 1024/32 | 0.004 | cosine_decay_warmup | 82.39% |
| ResNet101_vd | 30 | 7e-5 | 1024/32 | 0.004 | cosine_decay_warmup | 83.73% |
| Res2Net200_vd_26w_4s | 360 | 4e-5 | 1024/32 | 0.004 | cosine_decay_warmup | 85.13% |
### 3.4 数据增广以及基于 Fix 策略的微调
* 基于前文所述的实验结论,我们在训练的过程中加入自动增广 (AutoAugment)[4] ,同时进一步减小了 l2_decay (4e-5->2e-5) ,最终 ResNet50_vd 经过 SSLD 蒸馏策略,在 ImageNet1k 上的精度可以达到 82.99% ,相比之前不加数据增广的蒸馏策略再次增加了 0.6% 。
* 对于图像分类任务,在测试的时候,测试尺度为训练尺度的 1.15 倍左右时,往往在不需要重新训练模型的情况下,模型的精度指标就可以进一步提升 [5] ,对于 82.99% 的 ResNet50_vd 在 320x320 的尺度下测试,精度可达 83.7% ,我们进一步使用 Fix 策略,即在 320x320 的尺度下进行训练,使用与预测时相同的数据预处理方法,同时固定除 FC 层以外的所有参数,最终在 320x320 的预测尺度下,精度可以达到 **84.0%**
### 3.5 实验过程中的一些问题
* 在预测过程中, batch norm 的平均值与方差是通过加载预训练模型得到(设其模式为 test mode )。在训练过程中, batch norm 是通过统计当前 batch 的信息(设其模式为 train mode ),与历史保存信息进行滑动平均计算得到,在蒸馏任务中,我们发现通过 train mode ,即教师模型的均值与方差实时变化的模式,去指导学生模型,比通过 test mode 蒸馏,得到的学生模型性能更好一些,下面是一组实验结果。因此我们在该蒸馏方案中,均使用 train mode 去得到教师模型的 soft label 。
|Teacher Model | Teacher Top1 | Student Model | Student Top1|
|- |:-: |:-: | :-: |
| ResNet50_vd | 82.35% | MobileNetV3_large_x1_0 | 76.00% |
| ResNet50_vd | 82.35% | MobileNetV3_large_x1_0 | 75.84% |
## 四、蒸馏模型的应用
### 4.1 使用方法
* 中间层学习率调整。蒸馏得到的模型的中间层特征图更加精细化,因此将蒸馏模型预训练应用到其他任务中时,如果采取和之前相同的学习率,容易破坏中间层特征。而如果降低整体模型训练的学习率,则会带来训练收敛速度慢的问题。因此我们使用了中间层学习率调整的策略。具体地:
* 针对 ResNet50_vd ,我们设置一个学习率倍数列表, res block 之前的 3 个 conv2d 卷积参数具有统一的学习率倍数, 4 个 res block 的 conv2d 分别有一个学习率参数,共需设置 5 个学习率倍数的超参。在实验中发现。用于迁移学习finetune分类模型时 `[0.1,0.1,0.2,0.2,0.3]` 的中间层学习率倍数设置在绝大多数的任务中都性能更好;而在目标检测任务中, `[0.05,0.05,0.05,0.1,0.15]` 的中间层学习率倍数设置能够带来更大的精度收益。
* 对于 MoblileNetV3_large_x1_0 ,由于其包含 15 个 block ,我们设置每 3 个 block 共享一个学习率倍数参数,因此需要共 5 个学习率倍数的参数,最终发现在分类和检测任务中, `[0.25,0.25,0.5,0.5,0.75]` 的中间层学习率倍数能够带来更大的精度收益。
* 适当的 l2 decay 。不同分类模型在训练的时候一般都会根据模型设置不同的 l2 decay ,大模型为了防止过拟合,往往会设置更大的 l2 decay ,如 ResNet50 等模型,一般设置为 `1e-4` ;而如 MobileNet 系列模型,在训练时往往都会设置为 `1e-5~4e-5` ,防止模型过度欠拟合,在蒸馏时亦是如此。在将蒸馏模型应用到目标检测任务中时,我们发现也需要调节 backbone 甚至特定任务模型模型的 l2 decay ,和预训练蒸馏时的 l2 decay 尽可能保持一致。以 Faster RCNN MobiletNetV3 FPN 为例,我们发现仅修改该参数,在 COCO2017 数据集上就可以带来最多 0.5% 左右的精度 (mAP) 提升(默认 Faster RCNN l2 decay 为 1e-4 ,我们修改为 1e-5~4e-5 均有 0.3%~0.5% 的提升)。
### 4.2 迁移学习 finetune
* 为验证迁移学习的效果,我们在 10 个小的数据集上验证其效果。在这里为了保证实验的可对比性,我们均使用 ImageNet1k 数据集训练的标准预处理过程,对于蒸馏模型我们也添加了蒸馏模型中间层学习率的搜索。
* 对于 ResNet50_vd baseline 为 Top1 Acc 79.12% 的预训练模型基于 grid search 搜索得到的最佳精度,对比实验则为基于该精度对预训练和中间层学习率进一步搜索得到的最佳精度。下面给出 10 个数据集上所有 baseline 和蒸馏模型的精度对比。
| Dataset | Model | Baseline Top1 Acc | Distillation Model Finetune |
|- |:-: |:-: | :-: |
| Oxford102 flowers | ResNete50_vd | 97.18% | 97.41% |
| caltech-101 | ResNete50_vd | 92.57% | 93.21% |
| Oxford-IIIT-Pets | ResNete50_vd | 94.30% | 94.76% |
| DTD | ResNete50_vd | 76.48% | 77.71% |
| fgvc-aircraft-2013b | ResNete50_vd | 88.98% | 90.00% |
| Stanford-Cars | ResNete50_vd | 92.65% | 92.76% |
| SUN397 | ResNete50_vd | 64.02% | 68.36% |
| cifar100 | ResNete50_vd | 86.50% | 87.58% |
| cifar10 | ResNete50_vd | 97.72% | 97.94% |
| Food-101 | ResNete50_vd | 89.58% | 89.99% |
* 可以看出在上面 10 个数据集上,结合适当的中间层学习率倍数设置,蒸馏模型平均能够带来 1% 以上的精度提升。
### 4.3 目标检测
我们基于两阶段目标检测 Faster/Cascade RCNN 模型验证蒸馏得到的预训练模型的效果。
* ResNet50_vd
设置训练与评测的尺度均为 640x640 ,最终 COCO 上检测指标如下。
| Model | train/test scale | pretrain top1 acc | feature map lr | coco mAP |
|- |:-: |:-: | :-: | :-: |
| Faster RCNN R50_vd FPN | 640/640 | 79.12% | [1.0,1.0,1.0,1.0,1.0] | 34.8% |
| Faster RCNN R50_vd FPN | 640/640 | 79.12% | [0.05,0.05,0.1,0.1,0.15] | 34.3% |
| Faster RCNN R50_vd FPN | 640/640 | 82.18% | [0.05,0.05,0.1,0.1,0.15] | 36.3% |
在这里可以看出,对于未蒸馏模型,过度调整中间层学习率反而降低最终检测模型的性能指标。基于该蒸馏模型,我们也提供了领先的服务端实用目标检测方案,详细的配置与训练代码均已开源,可以参考 [PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection/tree/master/configs/rcnn_enhance)。
## 五、SSLD实战
本节将基于 ImageNet-1K 的数据集详细介绍 SSLD 蒸馏实验,如果想快速体验此方法,可以参考 [**30分钟玩转PaddleClas进阶版**](../../tutorials/quick_start_professional.md) 中基于 CIFAR100 的 SSLD 蒸馏实验。
### 5.1 参数配置
实战部分提供了 SSLD 蒸馏的示例,在 `ppcls/configs/ImageNet/Distillation/mv3_large_x1_0_distill_mv3_small_x1_0.yaml` 中提供了 `MobileNetV3_large_x1_0` 蒸馏`MobileNetV3_small_x1_0` 的配置文件,用户可以在 `tools/train.sh` 里直接替换配置文件的路径即可使用。
```yaml
Arch:
name: "DistillationModel"
# if not null, its lengths should be same as models
pretrained_list:
# if not null, its lengths should be same as models
freeze_params_list:
- True
- False
models:
- Teacher:
name: MobileNetV3_large_x1_0
pretrained: True
use_ssld: True
- Student:
name: MobileNetV3_small_x1_0
pretrained: False
infer_model_name: "Student"
```
在参数配置中,`freeze_params_list` 中需要指定模型是否需要冻结参数, `models` 中需要指定 Teacher 模型和 Student 模型,其中 Teacher 模型需要加载预训练模型。用户可以直接在此处更改模型。
### 5.2 启动命令
当用户配置完训练环境后,类似于训练其他分类任务,只需要将 `tools/train.sh` 中的配置文件替换成为相应的蒸馏配置文件即可。
其中 `train.sh` 中的内容如下:
```bash
python -m paddle.distributed.launch \
--selected_gpus="0,1,2,3" \
--log_dir=mv3_large_x1_0_distill_mv3_small_x1_0 \
tools/train.py \
-c ./ppcls/configs/ImageNet/Distillation/mv3_large_x1_0_distill_mv3_small_x1_0.yaml
```
运行 `train.sh`
```bash
sh tools/train.sh
```
### 5.3 注意事项
* 用户在使用 SSLD 蒸馏之前,首先需要在目标数据集上训练一个教师模型,该教师模型用于指导学生模型在该数据集上的训练。
* 如果学生模型没有加载预训练模型,训练的其他超参数可以参考该学生模型在 ImageNet-1k 上训练的超参数,如果学生模型加载了预训练模型,学习率可以调整到原来的 1/10 或者 1/100 。
* 在 SSLD 蒸馏的过程中,学生模型只学习 soft-label 导致训练目标变的更加复杂,建议可以适当的调小 `l2_decay` 的值来获得更高的验证集准确率。
* 若用户准备添加无标签的训练数据,只需要将新的训练数据放置在原本训练数据的路径下,生成新的数据 list 即可,另外,新生成的数据 list 需要将无标签的数据添加伪标签(只是为了统一读数据)。
## 参考文献
[1] Hinton G, Vinyals O, Dean J. Distilling the knowledge in a neural network[J]. arXiv preprint arXiv:1503.02531, 2015.
[2] Bagherinezhad H, Horton M, Rastegari M, et al. Label refinery: Improving imagenet classification through label progression[J]. arXiv preprint arXiv:1805.02641, 2018.
[3] Yalniz I Z, Jégou H, Chen K, et al. Billion-scale semi-supervised learning for image classification[J]. arXiv preprint arXiv:1905.00546, 2019.
[4] Cubuk E D, Zoph B, Mane D, et al. Autoaugment: Learning augmentation strategies from data[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2019: 113-123.
[5] Touvron H, Vedaldi A, Douze M, et al. Fixing the train-test resolution discrepancy[C]//Advances in Neural Information Processing Systems. 2019: 8250-8260.

View File

@ -0,0 +1,147 @@
## 模型量化、裁剪使用介绍
复杂的模型有利于提高模型的性能,但也导致模型中存在一定冗余。此部分提供精简模型的功能,包括两部分:模型量化(量化训练、离线量化)、模型剪枝。
其中模型量化将全精度缩减到定点数减少这种冗余,达到减少模型计算复杂度,提高模型推理性能的目的。
模型量化可以在基本不损失模型的精度的情况下将FP32精度的模型参数转换为Int8精度减小模型参数大小并加速计算使用量化后的模型在移动端等部署时更具备速度优势。
模型剪枝将CNN中不重要的卷积核裁剪掉减少模型参数量从而降低模型计算复杂度。
本教程将介绍如何使用飞桨模型压缩库PaddleSlim做PaddleClas模型的压缩即裁剪、量化功能。
[PaddleSlim](https://github.com/PaddlePaddle/PaddleSlim) 集成了模型剪枝、量化(包括量化训练和离线量化)、蒸馏和神经网络搜索等多种业界常用且领先的模型压缩功能,如果您感兴趣,可以关注并了解。
在开始本教程之前,建议先了解[PaddleClas模型的训练方法](../models_training/classification.md)以及[PaddleSlim](https://paddleslim.readthedocs.io/zh_CN/latest/index.html),相关裁剪、量化方法可以参考[模型裁剪量化算法介绍文档](../algorithm_introduction/model_prune_quantization.md)。
## 快速开始
当训练出一个模型后,如果希望进一步的压缩模型大小并加速预测,可使用量化或者剪枝的方法压缩模型。
模型压缩主要包括五个步骤:
1. 安装 PaddleSlim
2. 准备训练好的模型
3. 模型压缩
4. 导出量化推理模型
5. 量化模型预测部署
### 1. 安装PaddleSlim
* 可以通过pip install的方式进行安装。
```bash
pip install paddleslim -i https://pypi.tuna.tsinghua.edu.cn/simple
```
* 如果获取PaddleSlim的最新特性可以从源码安装。
```bash
git clone https://github.com/PaddlePaddle/PaddleSlim.git
cd Paddleslim
python3.7 setup.py install
```
### 2. 准备训练好的模型
PaddleClas提供了一系列训练好的[模型](../models/models_intro.md),如果待量化的模型不在列表中,需要按照[常规训练](../models_training/classification.md)方法得到训练好的模型。
### 3. 模型裁剪、量化
进入PaddleClas根目录
```bash
cd PaddleClas
```
`slim`训练相关代码已经集成到`ppcls/engine/`下,离线量化代码位于`deploy/slim/quant_post_static.py`。
#### 3.1 模型量化
量化训练包括离线量化训练和在线量化训练,在线量化训练效果更好,需加载预训练模型,在定义好量化策略后即可对模型进行量化。
##### 3.1.1 在线量化训练
训练指令如下:
* CPU/单卡GPU
以CPU为例若使用GPU则将命令中改成`cpu`改成`gpu`
```bash
python3.7 tools/train.py -c ppcls/configs/slim/ResNet50_vd_quantization.yaml -o Global.device=cpu
```
其中`yaml`文件解析详见[参考文档](../models_training/config_description.md)。为了保证精度,`yaml`文件中已经使用`pretrained model`.
* 单机多卡/多机多卡启动
```bash
export CUDA_VISIBLE_DEVICES=0,1,2,3
python3.7 -m paddle.distributed.launch \
--gpus="0,1,2,3" \
tools/train.py \
-c ppcls/configs/slim/ResNet50_vd_quantization.yaml
```
##### 3.1.2 离线量化
**注意**:目前离线量化,必须使用已经训练好的模型,导出的`inference model`进行量化。一般模型导出`inference model`可参考[教程](../inference_deployment/export_model.md).
一般来说,离线量化损失模型精度较多。
生成`inference model`后,离线量化运行方式如下
```bash
python3.7 deploy/slim/quant_post_static.py -c ppcls/configs/ImageNet/ResNet/ResNet50_vd.yaml -o Global.save_inference_dir=./deploy/models/class_ResNet50_vd_ImageNet_infer
```
`Global.save_inference_dir`是`inference model`存放的目录。
执行成功后,在`Global.save_inference_dir`的目录下,生成`quant_post_static_model`文件夹,其中存储生成的离线量化模型,其可以直接进行预测部署,无需再重新导出模型。
#### 3.2 模型剪枝
训练指令如下:
- CPU/单卡GPU
以CPU为例若使用GPU则将命令中改成`cpu`改成`gpu`
```bash
python3.7 tools/train.py -c ppcls/configs/slim/ResNet50_vd_prune.yaml -o Global.device=cpu
```
- 单机单卡/单机多卡/多机多卡启动
```bash
export CUDA_VISIBLE_DEVICES=0,1,2,3
python3.7 -m paddle.distributed.launch \
--gpus="0,1,2,3" \
tools/train.py \
-c ppcls/configs/slim/ResNet50_vd_prune.yaml
```
### 4. 导出模型
在得到在线量化训练、模型剪枝保存的模型后可以将其导出为inference model用于预测部署以模型剪枝为例
```bash
python3.7 tools/export.py \
-c ppcls/configs/slim/ResNet50_vd_prune.yaml \
-o Global.pretrained_model=./output/ResNet50_vd/best_model \
-o Global.save_inference_dir=./inference
```
### 5. 模型部署
上述步骤导出的模型可以直接使用inferecne 进行部署,参考[inference部署](../inference_deployment/)。
也通过PaddleLite的opt模型转换工具完成inference模型到移动端模型转换用于移动端的模型部署。
移动端模型部署的可参考 [移动端模型部署](../../../deploy/lite/readme.md)
## 训练超参数建议
* 量化、裁剪训练时,建议加载常规训练得到的预训练模型,加速量化训练收敛。
* 量化训练时,建议初始学习率修改为常规训练的`1/20~1/10`同时将训练epoch数修改为常规训练的`1/5~1/2`学习率策略方面加上Warmup其他配置信息不建议修改。
* 裁剪训练时,建议超参数配置与普通训练一致。

View File

@ -1,7 +0,0 @@
多标签分类
================================
.. toctree::
:maxdepth: 3
multilabel.md

View File

@ -1,90 +0,0 @@
# 多标签分类quick start
基于[NUS-WIDE-SCENE](https://lms.comp.nus.edu.sg/wp-content/uploads/2019/research/nuswide/NUS-WIDE.html)数据集体验多标签分类的训练、评估、预测的过程该数据集是NUS-WIDE数据集的一个子集。请事先参考[安装指南](install.md)配置运行环境和克隆PaddleClas代码。
## 一、数据和模型准备
* 进入PaddleClas目录。
```
cd path_to_PaddleClas
```
* 创建并进入`dataset/NUS-WIDE-SCENE`目录下载并解压NUS-WIDE-SCENE数据集。
```shell
mkdir dataset/NUS-WIDE-SCENE
cd dataset/NUS-WIDE-SCENE
wget https://paddle-imagenet-models-name.bj.bcebos.com/data/NUS-SCENE-dataset.tar
tar -xf NUS-SCENE-dataset.tar
```
* 返回`PaddleClas`根目录
```
cd ../../
```
## 二、模型训练
```shell
export CUDA_VISIBLE_DEVICES=0,1,2,3
python3 -m paddle.distributed.launch \
--gpus="0,1,2,3" \
tools/train.py \
-c ./ppcls/configs/quick_start/professional/MobileNetV1_multilabel.yaml
```
训练10epoch之后验证集最好的正确率应该在0.95左右。
## 三、模型评估
```bash
python3 tools/eval.py \
-c ./ppcls/configs/quick_start/professional/MobileNetV1_multilabel.yaml \
-o Arch.pretrained="./output/MobileNetV1/best_model"
```
## 四、模型预测
```bash
python3 tools/infer.py \
-c ./ppcls/configs/quick_start/professional/MobileNetV1_multilabel.yaml \
-o Arch.pretrained="./output/MobileNetV1/best_model"
```
得到类似下面的输出:
```
[{'class_ids': [6, 13, 17, 23, 26, 30], 'scores': [0.95683, 0.5567, 0.55211, 0.99088, 0.5943, 0.78767], 'file_name': './deploy/images/0517_2715693311.jpg', 'label_names': []}]
```
## 五、基于预测引擎预测
### 5.1 导出inference model
```bash
python3 tools/export_model.py \
-c ./ppcls/configs/quick_start/professional/MobileNetV1_multilabel.yaml \
-o Arch.pretrained="./output/MobileNetV1/best_model"
```
inference model的路径默认在当前路径下`./inference`
### 5.2 基于预测引擎预测
首先进入deploy目录下
```bash
cd ./deploy
```
通过预测引擎推理预测:
```
python3 python/predict_cls.py \
-c configs/inference_multilabel_cls.yaml
```
得到类似下面的输出:
```
0517_2715693311.jpg: class id(s): [6, 13, 17, 23, 26, 30], score(s): [0.96, 0.56, 0.55, 0.99, 0.59, 0.79], label_name(s): []
```

View File

@ -1,14 +1,14 @@
# 一、数据增广
# 一、数据增
在图像分类任务中,图像数据的增广是一种常用的正则化方法,常用于数据量不足或者模型参数较多的场景。在本章节中,我们将对除 ImageNet 分类任务标准数据增广外的8种数据增广方式进行简单的介绍和对比用户也可以将这些增广方法应用到自己的任务中以获得模型精度的提升。这8种数据增广方式在ImageNet上的精度指标如下所示。
在图像分类任务中,图像数据的增广是一种常用的正则化方法,常用于数据量不足或者模型参数较多的场景。在本章节中,我们将对除 ImageNet 分类任务标准数据增强外的8种数据增强方式进行简单的介绍和对比用户也可以将这些增广方法应用到自己的任务中以获得模型精度的提升。这8种数据增方式在ImageNet上的精度指标如下所示。
![](../../../images/image_aug/main_image_aug.png)
![](../../images/image_aug/main_image_aug.png)
# 二、常用数据增广方法
# 二、常用数据增方法
如果没有特殊说明,本章节中所有示例为 ImageNet 分类,并且假设最终输入网络的数据维度为:`[batch-size, 3, 224, 224]`
其中 ImageNet 分类训练阶段的标准数据增广方式分为以下几个步骤:
其中 ImageNet 分类训练阶段的标准数据增方式分为以下几个步骤:
1. 图像解码:简写为 `ImageDecode`
2. 随机裁剪到长宽均为 224 的图像:简写为 `RandCrop`
@ -25,7 +25,7 @@
增广后的可视化效果如下所示。
![](../../../images/image_aug/image_aug_samples_s.jpg)
![](../../images/image_aug/image_aug_samples_s.jpg)
具体如下表所示:
@ -43,7 +43,7 @@
| **Process** | (N, 3, 224, 224)<br>float32 | (N, 3, 224, 224)<br>float32 | \- | \- | \- | \- | \- | \- | Y | Y |
PaddleClas中集成了上述所有的数据增广策略,每种数据增广策略的参考论文与参考开源代码均在下面的介绍中列出。下文将介绍这些策略的原理与使用方法,并以下图为例,对变换后的效果进行可视化。为了说明问题,本章节中将 `RandCrop` 替换为 `Resize`
PaddleClas中集成了上述所有的数据增强策略,每种数据增强策略的参考论文与参考开源代码均在下面的介绍中列出。下文将介绍这些策略的原理与使用方法,并以下图为例,对变换后的效果进行可视化。为了说明问题,本章节中将 `RandCrop` 替换为 `Resize`
![][test_baseline]
@ -53,6 +53,7 @@ PaddleClas中集成了上述所有的数据增广策略每种数据增广策
+ AutoAugment
+ RandAugment
+ TimmAutoAugment
## 3.1 AutoAugment
@ -60,30 +61,9 @@ PaddleClas中集成了上述所有的数据增广策略每种数据增广策
开源代码github地址[https://github.com/DeepVoltaire/AutoAugment](https://github.com/DeepVoltaire/AutoAugment)
不同于常规的人工设计图像增广方式AutoAugment 是在一系列图像增广子策略的搜索空间中通过搜索算法找到的适合特定数据集的图像增广方案。针对 ImageNet 数据集,最终搜索出来的数据增广方案包含 25 个子策略组合,每个子策略中都包含两种变换,针对每幅图像都随机的挑选一个子策略组合,然后以一定的概率来决定是否执行子策略中的每种变换。
不同于常规的人工设计图像增广方式AutoAugment 是在一系列图像增广子策略的搜索空间中通过搜索算法找到的适合特定数据集的图像增广方案。针对 ImageNet 数据集,最终搜索出来的数据增方案包含 25 个子策略组合,每个子策略中都包含两种变换,针对每幅图像都随机的挑选一个子策略组合,然后以一定的概率来决定是否执行子策略中的每种变换。
PaddleClas中`AutoAugment`的使用方法如下所示。
```python
size = 224
decode_op = DecodeImage()
resize_op = ResizeImage(size=(size, size))
autoaugment_op = ImageNetPolicy()
ops = [decode_op, resize_op, autoaugment_op]
imgs_dir = "imgs_dir"
file_names = os.listdir(imgs_dir)
for file_name in file_names:
file_path = os.join(imgs_dir, file_name)
with open(file_path) as f:
data = f.read()
img = transform(data, ops)
```
结果如下图所示。
经过AutoAugment数据增强后结果如下图所示。
![][test_autoaugment]
@ -96,32 +76,19 @@ for file_name in file_names:
`AutoAugment` 的搜索方法比较暴力,直接在数据集上搜索针对该数据集的最优策略,其计算量很大。在 `RandAugment` 文章中作者发现,一方面,针对越大的模型,越大的数据集,使用 `AutoAugment` 方式搜索到的增广方式产生的收益也就越小;另一方面,这种搜索出的最优策略是针对该数据集的,其迁移能力较差,并不太适合迁移到其他数据集上。
`RandAugment` 中,作者提出了一种随机增广的方式,不再像 `AutoAugment` 中那样使用特定的概率确定是否使用某种子策略,而是所有的子策略都会以同样的概率被选择到,论文中的实验也表明这种数据增广方式即使在大模型的训练中也具有很好的效果。
`RandAugment` 中,作者提出了一种随机增广的方式,不再像 `AutoAugment` 中那样使用特定的概率确定是否使用某种子策略,而是所有的子策略都会以同样的概率被选择到,论文中的实验也表明这种数据增方式即使在大模型的训练中也具有很好的效果。
PaddleClas中`RandAugment`的使用方法如下所示。
```python
size = 224
decode_op = DecodeImage()
resize_op = ResizeImage(size=(size, size))
randaugment_op = RandAugment()
ops = [decode_op, resize_op, randaugment_op]
imgs_dir = 图像路径
fnames = os.listdir(imgs_dir)
for f in fnames:
data = open(os.path.join(imgs_dir, f)).read()
img = transform(data, ops)
```
结果如下图所示。
经过RandAugment数据增强后结果如下图所示。
![][test_randaugment]
## 3.3 TimmAutoAugment
开源代码github地址[https://github.com/rwightman/pytorch-image-models/blob/master/timm/data/auto_augment.py](https://github.com/rwightman/pytorch-image-models/blob/master/timm/data/auto_augment.py)
`TimmAutoAugment`是开源作者对AutoAugment和RandAugment的改进事实证明其在很多视觉任务上有更好的表现目前绝大多数VisionTransformer模型都是基于TimmAutoAugment去实现的。
# 四、图像裁剪类
@ -145,26 +112,7 @@ for f in fnames:
Cutout 可以理解为 Dropout 的一种扩展操作,不同的是 Dropout 是对图像经过网络后生成的特征进行遮挡,而 Cutout 是直接对输入的图像进行遮挡相对于Dropout对噪声的鲁棒性更好。作者在论文中也进行了说明这样做法有以下两点优势(1) 通过 Cutout 可以模拟真实场景中主体被部分遮挡时的分类场景;(2) 可以促进模型充分利用图像中更多的内容来进行分类,防止网络只关注显著性的图像区域,从而发生过拟合。
PaddleClas中`Cutout`的使用方法如下所示。
```python
size = 224
decode_op = DecodeImage()
resize_op = ResizeImage(size=(size, size))
cutout_op = Cutout(n_holes=1, length=112)
ops = [decode_op, resize_op, cutout_op]
imgs_dir = 图像路径
fnames = os.listdir(imgs_dir)
for f in fnames:
data = open(os.path.join(imgs_dir, f)).read()
img = transform(data, ops)
```
结果如下图所示。
经过RandAugment数据增强后结果如下图所示。
![][test_cutout]
@ -179,25 +127,7 @@ for f in fnames:
PaddleClas中`RandomErasing`的使用方法如下所示。
```python
size = 224
decode_op = DecodeImage()
resize_op = ResizeImage(size=(size, size))
randomerasing_op = RandomErasing()
ops = [decode_op, resize_op, tochw_op, randomerasing_op]
imgs_dir = 图像路径
fnames = os.listdir(imgs_dir)
for f in fnames:
data = open(os.path.join(imgs_dir, f)).read()
img = transform(data, ops)
img = img.transpose((1, 2, 0))
```
结果如下图所示。
经过RandomErasing数据增强后结果如下图所示。
![][test_randomerassing]
@ -217,25 +147,8 @@ for f in fnames:
PaddleClas中`HideAndSeek`的使用方法如下所示。
```python
size = 224
decode_op = DecodeImage()
resize_op = ResizeImage(size=(size, size))
hide_and_seek_op = HideAndSeek()
ops = [decode_op, resize_op, tochw_op, hide_and_seek_op]
imgs_dir = 图像路径
fnames = os.listdir(imgs_dir)
for f in fnames:
data = open(os.path.join(imgs_dir, f)).read()
img = transform(data, ops)
img = img.transpose((1, 2, 0))
```
结果如下图所示。
经过HideAndSeek数据增强后结果如下图所示。
![][test_hideandseek]
@ -265,31 +178,7 @@ for f in fnames:
论文中验证上述第二种方法的训练效果更好一些。
PaddleClas中`GridMask`的使用方法如下所示。
```python
size = 224
decode_op = DecodeImage()
resize_op = ResizeImage(size=(size, size))
tochw_op = ToCHWImage()
gridmask_op = GridMask(d1=96, d2=224, rotate=1, ratio=0.6, mode=1, prob=0.8)
ops = [decode_op, resize_op, tochw_op, gridmask_op]
imgs_dir = 图像路径
fnames = os.listdir(imgs_dir)
for f in fnames:
data = open(os.path.join(imgs_dir, f)).read()
img = transform(data, ops)
img = img.transpose((1, 2, 0))
```
结果如下图所示。
经过GridMask数据增强后结果如下图所示。
![][test_gridmask]
@ -313,34 +202,8 @@ Mixup 是最先提出的图像混叠增广方案,其原理简单、方便实
如下是 `imaug` 中的实现,需要指出的是,下述实现会出现对同一幅进行相加的情况,也就是最终得到的图和原图一样,随着 `batch-size` 的增加这种情况出现的概率也会逐渐减小。
PaddleClas中`Mixup`的使用方法如下所示。
```python
size = 224
decode_op = DecodeImage()
resize_op = ResizeImage(size=(size, size))
tochw_op = ToCHWImage()
hide_and_seek_op = HideAndSeek()
mixup_op = MixupOperator()
cutmix_op = CutmixOperator()
ops = [decode_op, resize_op, tochw_op]
imgs_dir = 图像路径
batch = []
fnames = os.listdir(imgs_dir)
for idx, f in enumerate(fnames):
data = open(os.path.join(imgs_dir, f)).read()
img = transform(data, ops)
batch.append( (img, idx) ) # fake label
new_batch = mixup_op(batch)
```
结果如下图所示。
经过Mixup数据增强结果如下图所示。
![][test_mixup]
@ -352,167 +215,11 @@ new_batch = mixup_op(batch)
`Mixup` 直接对两幅图进行相加不一样,`Cutmix` 是从一幅图中随机裁剪出一个 `ROI`,然后覆盖当前图像中对应的区域,代码实现如下所示:
```python
size = 224
decode_op = DecodeImage()
resize_op = ResizeImage(size=(size, size))
tochw_op = ToCHWImage()
hide_and_seek_op = HideAndSeek()
cutmix_op = CutmixOperator()
ops = [decode_op, resize_op, tochw_op]
imgs_dir = 图像路径
batch = []
fnames = os.listdir(imgs_dir)
for idx, f in enumerate(fnames):
data = open(os.path.join(imgs_dir, f)).read()
img = transform(data, ops)
batch.append( (img, idx) ) # fake label
new_batch = cutmix_op(batch)
```
结果如下图所示。
经过Cutmix数据增强后结果如下图所示。
![][test_cutmix]
# 六、实验
基于PaddleClas在ImageNet1k数据集上的分类精度如下。
| 模型 | 初始学习率策略 | l2 decay | batch size | epoch | 数据变化策略 | Top1 Acc | 论文中结论 |
|-------------|------------------|--------------|------------|-------|----------------|------------|----|
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | 标准变换 | 0.7731 | - |
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | AutoAugment | 0.7795 | 0.7763 |
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | mixup | 0.7828 | 0.7790 |
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | cutmix | 0.7839 | 0.7860 |
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | cutout | 0.7801 | - |
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | gridmask | 0.7785 | 0.7790 |
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | random-augment | 0.7770 | 0.7760 |
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | random erasing | 0.7791 | - |
| ResNet50 | 0.1/cosine_decay | 0.0001 | 256 | 300 | hide and seek | 0.7743 | 0.7720 |
**注意**
* 在这里的实验中为了便于对比我们将l2 decay固定设置为1e-4在实际使用中我们推荐尝试使用更小的l2 decay。结合数据增广我们发现将l2 decay由1e-4减小为7e-5均能带来至少0.3~0.5%的精度提升。
* 我们目前尚未对不同策略进行组合并验证效果,这一块后续我们会开展更多的对比实验,敬请期待。
# 七、数据增广分类实战
本节将基于ImageNet-1K的数据集详细介绍数据增广实验如果想快速体验此方法可以参考[**30分钟玩转PaddleClas进阶版**](../../tutorials/quick_start_professional.md)中基于CIFAR100的数据增广实验。
## 7.1 参数配置
由于不同的数据增广方式含有不同的超参数,为了便于理解和使用,我们在`configs/DataAugment`里分别列举了8种训练ResNet50的数据增广方式的参数配置文件用户可以在`tools/run.sh`里直接替换配置文件的路径即可使用。此处分别挑选了图像变换、图像裁剪、图像混叠中的一个示例展示,其他参数配置用户可以自查配置文件。
### RandAugment
`RandAugment`的图像增广方式的配置如下,其中用户需要指定其中的参数`num_layers`与`magnitude`,默认的数值分别是`2`和`5`。`RandAugment`是在uint8的数据格式上转换的所以其处理过程应该放在归一化操作`NormalizeImage`)之前。
```yaml
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- RandCropImage:
size: 224
- RandFlipImage:
flip_code: 1
- RandAugment:
num_layers: 2
magnitude: 5
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
```
### Cutout
`Cutout`的图像增广方式的配置如下,其中用户需要指定其中的参数`n_holes`与`length`,默认的数值分别是`1`和`112`。类似其他图像裁剪类的数据增广方式,`Cutout`既可以在uint8格式的数据上操作也可以在归一化`NormalizeImage`)后的数据上操作,此处给出的是在归一化后的操作。
```yaml
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- RandCropImage:
size: 224
- RandFlipImage:
flip_code: 1
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
- Cutout:
n_holes: 1
length: 112
```
### Mixup
`Mixup`的图像增广方式的配置如下,其中用户需要指定其中的参数`alpha`,默认的数值是`0.2`。类似其他图像混合类的数据增广方式,`Mixup`是在图像做完数据处理后将每个batch内的数据做图像混叠将混叠后的图像和标签输入网络中训练所以其是在图像数据处理图像变换、图像裁剪后操作。另外在配置文件中需要将`use_mix`参数设置为`True`。
```yaml
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- RandCropImage:
size: 224
- RandFlipImage:
flip_code: 1
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
batch_transform_ops:
- MixupOperator:
alpha: 0.2
```
## 7.2 启动命令
当用户配置完训练环境后,类似于训练其他分类任务,只需要将`tools/train.sh`中的配置文件替换成为相应的数据增广方式的配置文件即可。
其中`train.sh`中的内容如下:
```bash
python3 -m paddle.distributed.launch \
--selected_gpus="0,1,2,3" \
--log_dir=ResNet50_Cutout \
tools/train.py \
-c ./ppcls/configs/ImageNet/DataAugment/ResNet50_Cutout.yaml
```
运行`train.sh`
```bash
sh tools/train.sh
```
## 7.3 注意事项
* 由于图像混叠时需对label进行混叠无法计算训练数据的准确率所以在训练过程中没有打印训练准确率。
* 在使用数据增广后,由于训练数据更难,所以训练损失函数可能较大,训练集的准确率相对较低,但其有拥更好的泛化能力,所以验证集的准确率相对较高。
* 在使用数据增广后,模型可能会趋于欠拟合状态,建议可以适当的调小`l2_decay`的值来获得更高的验证集准确率。
* 几乎每一类图像增广均含有超参数我们只提供了基于ImageNet-1k的超参数其他数据集需要用户自己调试超参数具体超参数的含义用户可以阅读相关的论文调试方法也可以参考训练技巧的章节。
> 如果您觉得此文档对您有帮助欢迎star我们的项目[https://github.com/PaddlePaddle/PaddleClas](https://github.com/PaddlePaddle/PaddleClas)
关于数据增强相关的实战部分实参考[数据增强实战](../advanced_tutorials/DataAugmentation.md)。
# 参考文献
@ -536,14 +243,14 @@ sh tools/train.sh
[test_baseline]: ../../../images/image_aug/test_baseline.jpeg
[test_autoaugment]: ../../../images/image_aug/test_autoaugment.jpeg
[test_cutout]: ../../../images/image_aug/test_cutout.jpeg
[test_gridmask]: ../../../images/image_aug/test_gridmask.jpeg
[gridmask-0]: ../../../images/image_aug/gridmask-0.png
[test_hideandseek]: ../../../images/image_aug/test_hideandseek.jpeg
[test_randaugment]: ../../../images/image_aug/test_randaugment.jpeg
[test_randomerassing]: ../../../images/image_aug/test_randomerassing.jpeg
[hide_and_seek_mask_expanation]: ../../../images/image_aug/hide-and-seek-visual.png
[test_mixup]: ../../../images/image_aug/test_mixup.png
[test_cutmix]: ../../../images/image_aug/test_cutmix.png
[test_baseline]: ../../images/image_aug/test_baseline.jpeg
[test_autoaugment]: ../../images/image_aug/test_autoaugment.jpeg
[test_cutout]: ../../images/image_aug/test_cutout.jpeg
[test_gridmask]: ../../images/image_aug/test_gridmask.jpeg
[gridmask-0]: ../../images/image_aug/gridmask-0.png
[test_hideandseek]: ../../images/image_aug/test_hideandseek.jpeg
[test_randaugment]: ../../images/image_aug/test_randaugment.jpeg
[test_randomerassing]: ../../images/image_aug/test_randomerassing.jpeg
[hide_and_seek_mask_expanation]: ../../images/image_aug/hide-and-seek-visual.png
[test_mixup]: ../../images/image_aug/test_mixup.png
[test_cutmix]: ../../images/image_aug/test_cutmix.png

View File

@ -7,24 +7,25 @@
### 模型库概览图
基于ImageNet1k分类数据集PaddleClas支持35个系列分类网络结构以及对应的164个图像分类预训练模型训练技巧、每个系列网络结构的简单介绍和性能评估将在相应章节展现下面所有的速度指标评估环境如下
* CPU的评估环境基于骁龙855SD855
* Arm CPU的评估环境基于骁龙855SD855
* Intel CPU的评估环境基于Intel(R) Xeon(R) Gold 6148。
* GPU评估环境基于T4机器在FP32+TensorRT配置下运行500次测得去除前10次的warmup时间
常见服务器端模型的精度指标与其预测耗时的变化曲线如下图所示。
![](../images/models/T4_benchmark/t4.fp32.bs1.main_fps_top1.png)
![](../../images/models/T4_benchmark/t4.fp32.bs1.main_fps_top1.png)
常见移动端模型的精度指标与其预测耗时、模型存储大小的变化曲线如下图所示。
![](../images/models/mobile_arm_storage.png)
![](../../images/models/mobile_arm_storage.png)
![](../images/models/mobile_arm_top1.png)
![](../../images/models/mobile_arm_top1.png)
<a name="SSLD知识蒸馏系列"></a>
### SSLD知识蒸馏预训练模型
基于SSLD知识蒸馏的预训练模型列表如下所示更多关于SSLD知识蒸馏方案的介绍可以参考[SSLD知识蒸馏文档](./advanced_tutorials/distillation/distillation.md)。
基于SSLD知识蒸馏的预训练模型列表如下所示更多关于SSLD知识蒸馏方案的介绍可以参考[SSLD知识蒸馏文档](./knowledge_distillation.md)。
* 服务器端知识蒸馏模型
@ -41,7 +42,7 @@
| SE_HRNet_W64_C_ssld | 0.848 | - | - | 31.697 | 94.995 | 57.83 | 128.97 | [下载链接](https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/legendary_models/SE_HRNet_W64_C_ssld_pretrained.pdparams) |
* 端知识蒸馏模型
* 移动端知识蒸馏模型
| 模型 | Top-1 Acc | Reference<br>Top-1 Acc | Acc gain | SD855 time(ms)<br>bs=1 | Flops(G) | Params(M) | 模型大小(M) | 下载地址 |
|---------------------|-----------|-----------|---------------|----------------|-----------|----------|-----------|-----------------------------------|
@ -69,7 +70,7 @@
<a name="PP-LCNet系列"></a>
### PP-LCNet系列
PP-LCNet系列模型的精度、速度指标如下表所示更多关于该系列的模型介绍可以参考[PP-LCNet系列模型文档](./models/PP-LCNet.md)。
PP-LCNet系列模型的精度、速度指标如下表所示更多关于该系列的模型介绍可以参考[PP-LCNet系列模型文档](../models/PP-LCNet.md)。
| 模型 | Top-1 Acc | Top-5 Acc | Intel-Xeon-Gold-6148 time(ms)<br>bs=1 | FLOPs(M) | Params(M) | 下载地址 |
|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
@ -86,7 +87,7 @@ PP-LCNet系列模型的精度、速度指标如下表所示更多关于该系
<a name="ResNet及其Vd系列"></a>
### ResNet及其Vd系列
ResNet及其Vd系列模型的精度、速度指标如下表所示更多关于该系列的模型介绍可以参考[ResNet及其Vd系列模型文档](./models/ResNet_and_vd.md)。
ResNet及其Vd系列模型的精度、速度指标如下表所示更多关于该系列的模型介绍可以参考[ResNet及其Vd系列模型文档](../models/ResNet_and_vd.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |
|---------------------|-----------|-----------|-----------------------|----------------------|----------|-----------|----------------------------------------------------------------------------------------------|
@ -110,7 +111,7 @@ ResNet及其Vd系列模型的精度、速度指标如下表所示更多关于
<a name="移动端系列"></a>
### 移动端系列
移动端系列模型的精度、速度指标如下表所示,更多关于该系列的模型介绍可以参考:[移动端系列模型文档](./models/Mobile.md)。
移动端系列模型的精度、速度指标如下表所示,更多关于该系列的模型介绍可以参考:[移动端系列模型文档](../models/Mobile.md)。
| 模型 | Top-1 Acc | Top-5 Acc | SD855 time(ms)<br>bs=1 | Flops(G) | Params(M) | 模型大小(M) | 下载地址 |
|----------------------------------|-----------|-----------|------------------------|----------|-----------|---------|-----------------------------------------------------------------------------------------------------------|
@ -155,7 +156,7 @@ ResNet及其Vd系列模型的精度、速度指标如下表所示更多关于
<a name="SEResNeXt与Res2Net系列"></a>
### SEResNeXt与Res2Net系列
SEResNeXt与Res2Net系列模型的精度、速度指标如下表所示更多关于该系列的模型介绍可以参考[SEResNeXt与Res2Net系列模型文档](./models/SEResNext_and_Res2Net.md)。
SEResNeXt与Res2Net系列模型的精度、速度指标如下表所示更多关于该系列的模型介绍可以参考[SEResNeXt与Res2Net系列模型文档](../models/SEResNext_and_Res2Net.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |
@ -190,7 +191,7 @@ SEResNeXt与Res2Net系列模型的精度、速度指标如下表所示更多
<a name="DPN与DenseNet系列"></a>
### DPN与DenseNet系列
DPN与DenseNet系列模型的精度、速度指标如下表所示更多关于该系列的模型介绍可以参考[DPN与DenseNet系列模型文档](./models/DPN_DenseNet.md)。
DPN与DenseNet系列模型的精度、速度指标如下表所示更多关于该系列的模型介绍可以参考[DPN与DenseNet系列模型文档](../models/DPN_DenseNet.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |
@ -211,7 +212,7 @@ DPN与DenseNet系列模型的精度、速度指标如下表所示更多关于
<a name="HRNet系列"></a>
### HRNet系列
HRNet系列模型的精度、速度指标如下表所示更多关于该系列的模型介绍可以参考[HRNet系列模型文档](./models/HRNet.md)。
HRNet系列模型的精度、速度指标如下表所示更多关于该系列的模型介绍可以参考[HRNet系列模型文档](../models/HRNet.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |
@ -231,7 +232,7 @@ HRNet系列模型的精度、速度指标如下表所示更多关于该系列
<a name="Inception系列"></a>
### Inception系列
Inception系列模型的精度、速度指标如下表所示更多关于该系列的模型介绍可以参考[Inception系列模型文档](./models/Inception.md)。
Inception系列模型的精度、速度指标如下表所示更多关于该系列的模型介绍可以参考[Inception系列模型文档](../models/Inception.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |
|--------------------|-----------|-----------|-----------------------|----------------------|----------|-----------|---------------------------------------------------------------------------------------------|
@ -248,7 +249,7 @@ Inception系列模型的精度、速度指标如下表所示更多关于该
<a name="EfficientNet与ResNeXt101_wsl系列"></a>
### EfficientNet与ResNeXt101_wsl系列
EfficientNet与ResNeXt101_wsl系列模型的精度、速度指标如下表所示更多关于该系列的模型介绍可以参考[EfficientNet与ResNeXt101_wsl系列模型文档](./models/EfficientNet_and_ResNeXt101_wsl.md)。
EfficientNet与ResNeXt101_wsl系列模型的精度、速度指标如下表所示更多关于该系列的模型介绍可以参考[EfficientNet与ResNeXt101_wsl系列模型文档](../models/EfficientNet_and_ResNeXt101_wsl.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |
@ -272,7 +273,7 @@ EfficientNet与ResNeXt101_wsl系列模型的精度、速度指标如下表所示
<a name="ResNeSt与RegNet系列"></a>
### ResNeSt与RegNet系列
ResNeSt与RegNet系列模型的精度、速度指标如下表所示更多关于该系列的模型介绍可以参考[ResNeSt与RegNet系列模型文档](./models/ResNeSt_RegNet.md)。
ResNeSt与RegNet系列模型的精度、速度指标如下表所示更多关于该系列的模型介绍可以参考[ResNeSt与RegNet系列模型文档](../models/ResNeSt_RegNet.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |
@ -285,7 +286,7 @@ ResNeSt与RegNet系列模型的精度、速度指标如下表所示更多关
<a name="ViT_and_DeiT系列"></a>
### ViT_and_DeiT系列
ViTVision Transformer与DeiTData-efficient Image Transformers系列模型的精度、速度指标如下表所示. 更多关于该系列模型的介绍可以参考: [ViT_and_DeiT系列模型文档](./models/ViT_and_DeiT.md)。
ViTVision Transformer与DeiTData-efficient Image Transformers系列模型的精度、速度指标如下表所示. 更多关于该系列模型的介绍可以参考: [ViT_and_DeiT系列模型文档](../models/ViT_and_DeiT.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |
@ -297,7 +298,7 @@ ViTVision Transformer与DeiTData-efficient Image Transformers系列
| ViT_large_<br/>patch16_224 | 0.8323 | 0.9650 | - | - | | 307 | [下载链接](https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ViT_large_patch16_224_pretrained.pdparams) |
| ViT_large_<br/>patch16_384 | 0.8513 | 0.9736 | - | - | | | [下载链接](https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ViT_large_patch16_384_pretrained.pdparams) |
| ViT_large_<br/>patch32_384 | 0.8153 | 0.9608 | - | - | | | [下载链接](https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ViT_large_patch32_384_pretrained.pdparams) |
| | | | | | | | |
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |
@ -310,13 +311,13 @@ ViTVision Transformer与DeiTData-efficient Image Transformers系列
| DeiT_small_<br>distilled_patch16_224 | 0.809 | 0.953 | - | - | | 22 | [下载链接](https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/DeiT_small_distilled_patch16_224_pretrained.pdparams) |
| DeiT_base_<br>distilled_patch16_224 | 0.831 | 0.964 | - | - | | 87 | [下载链接](https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/DeiT_base_distilled_patch16_224_pretrained.pdparams) |
| DeiT_base_<br>distilled_patch16_384 | 0.851 | 0.973 | - | - | | 88 | [下载链接](https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/DeiT_base_distilled_patch16_384_pretrained.pdparams) |
| | | | | | | | |
<a name="RepVGG系列"></a>
### RepVGG系列
关于RepVGG系列模型的精度、速度指标如下表所示更多介绍可以参考[RepVGG系列模型文档](./models/RepVGG.md)。
关于RepVGG系列模型的精度、速度指标如下表所示更多介绍可以参考[RepVGG系列模型文档](../models/RepVGG.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |
@ -336,7 +337,7 @@ ViTVision Transformer与DeiTData-efficient Image Transformers系列
### MixNet系列
关于MixNet系列模型的精度、速度指标如下表所示更多介绍可以参考[MixNet系列模型文档](./models/MixNet.md)。
关于MixNet系列模型的精度、速度指标如下表所示更多介绍可以参考[MixNet系列模型文档](../models/MixNet.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(M) | Params(M) | 下载地址 |
| -------- | --------- | --------- | ---------------- | ---------------- | -------- | --------- | ------------------------------------------------------------ |
@ -348,7 +349,7 @@ ViTVision Transformer与DeiTData-efficient Image Transformers系列
### ReXNet系列
关于ReXNet系列模型的精度、速度指标如下表所示更多介绍可以参考[ReXNet系列模型文档](./models/ReXNet.md)。
关于ReXNet系列模型的精度、速度指标如下表所示更多介绍可以参考[ReXNet系列模型文档](../models/ReXNet.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |
| ---------- | --------- | --------- | ---------------- | ---------------- | -------- | --------- | ------------------------------------------------------------ |
@ -362,7 +363,7 @@ ViTVision Transformer与DeiTData-efficient Image Transformers系列
### SwinTransformer系列
关于SwinTransformer系列模型的精度、速度指标如下表所示更多介绍可以参考[SwinTransformer系列模型文档](./models/SwinTransformer.md)。
关于SwinTransformer系列模型的精度、速度指标如下表所示更多介绍可以参考[SwinTransformer系列模型文档](../models/SwinTransformer.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |
| ---------- | --------- | --------- | ---------------- | ---------------- | -------- | --------- | ------------------------------------------------------------ |
@ -380,7 +381,7 @@ ViTVision Transformer与DeiTData-efficient Image Transformers系列
<a name="LeViT系列"></a>
### LeViT系列
关于LeViT系列模型的精度、速度指标如下表所示更多介绍可以参考[LeViT系列模型文档](./models/LeViT.md)。
关于LeViT系列模型的精度、速度指标如下表所示更多介绍可以参考[LeViT系列模型文档](../models/LeViT.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(M) | Params(M) | 下载地址 |
| ---------- | --------- | --------- | ---------------- | ---------------- | -------- | --------- | ------------------------------------------------------------ |
@ -395,7 +396,7 @@ ViTVision Transformer与DeiTData-efficient Image Transformers系列
<a name="Twins系列"></a>
### Twins系列
关于Twins系列模型的精度、速度指标如下表所示更多介绍可以参考[Twins系列模型文档](./models/Twins.md)。
关于Twins系列模型的精度、速度指标如下表所示更多介绍可以参考[Twins系列模型文档](../models/Twins.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |
| ---------- | --------- | --------- | ---------------- | ---------------- | -------- | --------- | ------------------------------------------------------------ |
@ -411,7 +412,7 @@ ViTVision Transformer与DeiTData-efficient Image Transformers系列
<a name="HarDNet系列"></a>
### HarDNet系列
关于HarDNet系列模型的精度、速度指标如下表所示更多介绍可以参考[HarDNet系列模型文档](./models/HarDNet.md)。
关于HarDNet系列模型的精度、速度指标如下表所示更多介绍可以参考[HarDNet系列模型文档](../models/HarDNet.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |
| ---------- | --------- | --------- | ---------------- | ---------------- | -------- | --------- | ------------------------------------------------------------ |
@ -423,7 +424,7 @@ ViTVision Transformer与DeiTData-efficient Image Transformers系列
<a name="DLA系列"></a>
### DLA系列
关于 DLA系列模型的精度、速度指标如下表所示更多介绍可以参考[DLA系列模型文档](./models/DLA.md)。
关于 DLA系列模型的精度、速度指标如下表所示更多介绍可以参考[DLA系列模型文档](../models/DLA.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |
| ---------- | --------- | --------- | ---------------- | ---------------- | -------- | --------- | ------------------------------------------------------------ |
@ -440,7 +441,7 @@ ViTVision Transformer与DeiTData-efficient Image Transformers系列
<a name="RedNet系列"></a>
### RedNet系列
关于RedNet系列模型的精度、速度指标如下表所示更多介绍可以参考[RedNet系列模型文档](./models/RedNet.md)。
关于RedNet系列模型的精度、速度指标如下表所示更多介绍可以参考[RedNet系列模型文档](../models/RedNet.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |
| ---------- | --------- | --------- | ---------------- | ---------------- | -------- | --------- | ------------------------------------------------------------ |
@ -453,7 +454,7 @@ ViTVision Transformer与DeiTData-efficient Image Transformers系列
<a name="TNT系列"></a>
### TNT系列
关于TNT系列模型的精度、速度指标如下表所示更多介绍可以参考[TNT系列模型文档](./models/TNT.md)。
关于TNT系列模型的精度、速度指标如下表所示更多介绍可以参考[TNT系列模型文档](../models/TNT.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |
| ---------- | --------- | --------- | ---------------- | ---------------- | -------- | --------- | ------------------------------------------------------------ |
@ -465,7 +466,7 @@ ViTVision Transformer与DeiTData-efficient Image Transformers系列
### 其他模型
关于AlexNet、SqueezeNet系列、VGG系列、DarkNet53等模型的精度、速度指标如下表所示更多介绍可以参考[其他模型文档](./models/Others.md)。
关于AlexNet、SqueezeNet系列、VGG系列、DarkNet53等模型的精度、速度指标如下表所示更多介绍可以参考[其他模型文档](../models/Others.md)。
| 模型 | Top-1 Acc | Top-5 Acc | time(ms)<br>bs=1 | time(ms)<br>bs=4 | Flops(G) | Params(M) | 下载地址 |

View File

@ -28,7 +28,7 @@ CIFAR-10数据集由10个类的60000个彩色图像组成图像分辨率为32
### 2.2 模型准备
在数据确定后模型往往决定了最终算法精度的上限在图像分类领域经典的模型层出不穷PaddleClas提供了35个系列共164个ImageNet预训练模型。具体的精度、速度等指标请参考[骨干网络和预训练模型库](../ImageNet_models_cn.md)。
在数据确定后模型往往决定了最终算法精度的上限在图像分类领域经典的模型层出不穷PaddleClas提供了36个系列共175个ImageNet预训练模型。具体的精度、速度等指标请参考[骨干网络和预训练模型库](./ImageNet_models.md)。
### 2.3 模型训练

View File

@ -0,0 +1,77 @@
# 知识蒸馏
## 1. 模型压缩和知识蒸馏方法简介
近年来,深度神经网络在计算机视觉、自然语言处理等领域被验证是一种极其有效的解决问题的方法。通过构建合适的神经网络,加以训练,最终网络模型的性能指标基本上都会超过传统算法。
在数据量足够大的情况下,通过合理构建网络模型的方式增加其参数量,可以显著改善模型性能,但是这又带来了模型复杂度急剧提升的问题。大模型在实际场景中使用的成本较高。
深度神经网络一般有较多的参数冗余,目前有几种主要的方法对模型进行压缩,减小其参数量。如裁剪、量化、知识蒸馏等,其中知识蒸馏是指使用教师模型(teacher model)去指导学生模型(student model)学习特定任务,保证小模型在参数量不变的情况下,得到比较大的性能提升,甚至获得与大模型相似的精度指标 [1]。
目前知识蒸馏的方法大致可以分为以下三种。
* Response based distillation教师模型对学生模型的输出进行监督。
* Feature based distillation教师模型对学生模型的中间层 feature map 进行监督。
* Relation based distillation对于不同的样本使用教师模型和学生模型同时计算样本之间 feature map 的相关性,使得学生模型和教师模型得到的相关性矩阵尽可能一致。
## 2. 知识蒸馏应用
知识蒸馏算法在模型轻量化过程任务中应用广泛,对于需要满足特定的精度的任务,通过使用知识蒸馏的方法,我们可以使用更小的模型便能达到要求的精度,从而减小了模型部署的成本。
此外对于相同的模型结构使用知识蒸馏训练得到的预训练模型精度往往更高这些预训练模型往往也可以提升下游任务的模型精度。比如在图像分类任务中基于知识蒸馏算法得到的精度更高的预训练模型也能够在目标检测、图像分割、OCR、视频分类等任务中获得明显的精度收益。
## 3. 知识蒸馏算法介绍
### 3.1 Response based distillation
最早的知识蒸馏算法KD由Hinton提出训练的损失函数中除了 gt loss 之外,还引入了学生模型与教师模型输出的 KL 散度,最终精度超过单纯使用 gt loss 训练的精度。这里需要注意的是,在训练的时候,需要首先训练得到一个更大的教师模型,来指导学生模型的训练过程。
PaddleClas 中提出了一种简单使用的 SSLD 知识蒸馏算法 [6],在训练的时候去除了对 gt label 的依赖,结合大量无标注数据,最终蒸馏训练得到的预训练模型在 15 个模型上的精度提升平均高达 3%。
上述标准的蒸馏方法是通过一个大模型作为教师模型来指导学生模型提升效果,而后来又发展出 DML (Deep Mutual Learning) 互学习蒸馏方法 [7],即通过两个结构相同的模型互相学习。具体的。相比于 KD 等依赖于大的教师模型的知识蒸馏算法DML 脱离了对大的教师模型的依赖,蒸馏训练的流程更加简单,模型产出效率也要更高一些。
### 3.2 Feature based distillation
Heo 等人提出了 OverHaul [8], 计算学生模型与教师模型的 feature map distance作为蒸馏的 loss在这里使用了学生模型、教师模型的转移来保证二者的 feature map 可以正常地进行 distance 的计算。
基于 feature map distance 的知识蒸馏方法也能够和 `3.1章节` 中的基于 response 的知识蒸馏算法融合在一起,同时对学生模型的输出结果和中间层 feature map 进行监督。而对于 DML 方法来说,这种融合过程更为简单,因为不需要对学生和教师模型的 feature map 进行转换,便可以完成对齐 (alignment) 过程。PP-OCRv2 系统中便使用了这种方法,最终大幅提升了 OCR 文字识别模型的精度。
### 3.3 Relation based distillation

`3.1``3.2` 章节中的论文中主要是考虑到学生模型与教师模型的输出或者中间层 feature map这些知识蒸馏算法只关注个体的输出结果没有考虑到个体之间的输出关系。
Park 等人提出了 RKD [10]基于关系的知识蒸馏算法RKD 中进一步考虑个体输出之间的关系,使用 2 种损失函数二阶的距离损失distance-wise和三阶的角度损失angle-wise
本论文提出的算法关系知识蒸馏RKD迁移教师模型得到的输出结果间的结构化关系给学生模型不同于之前的只关注个体输出结果RKD 算法使用两种损失函数:二阶的距离损失 distance-wise 和三阶的角度损失 angle-wise。在最终计算蒸馏损失函数的时候同时考虑KD loss 和 RKD loss。最终精度优于单独使用 KD loss 蒸馏得到的模型精度。
## 4. 参考文献
[1] Hinton G, Vinyals O, Dean J. Distilling the knowledge in a neural network[J]. arXiv preprint arXiv:1503.02531, 2015.
[2] Bagherinezhad H, Horton M, Rastegari M, et al. Label refinery: Improving imagenet classification through label progression[J]. arXiv preprint arXiv:1805.02641, 2018.
[3] Yalniz I Z, Jégou H, Chen K, et al. Billion-scale semi-supervised learning for image classification[J]. arXiv preprint arXiv:1905.00546, 2019.
[4] Cubuk E D, Zoph B, Mane D, et al. Autoaugment: Learning augmentation strategies from data[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2019: 113-123.
[5] Touvron H, Vedaldi A, Douze M, et al. Fixing the train-test resolution discrepancy[C]//Advances in Neural Information Processing Systems. 2019: 8250-8260.
[6] Cui C, Guo R, Du Y, et al. Beyond Self-Supervision: A Simple Yet Effective Network Distillation Alternative to Improve Backbones[J]. arXiv preprint arXiv:2103.05959, 2021.
[7] Zhang Y, Xiang T, Hospedales T M, et al. Deep mutual learning[C]//Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition. 2018: 4320-4328.
[8] Heo B, Kim J, Yun S, et al. A comprehensive overhaul of feature distillation[C]//Proceedings of the IEEE/CVF International Conference on Computer Vision. 2019: 1921-1930.
[9] Du Y, Li C, Guo R, et al. PP-OCRv2: Bag of Tricks for Ultra Lightweight OCR System[J]. arXiv preprint arXiv:2109.03144, 2021.
[10] Park W, Kim D, Lu Y, et al. Relational knowledge distillation[C]//Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2019: 3967-3976.

View File

@ -0,0 +1,57 @@
## 模型裁剪、量化算法介绍
深度学习因其计算复杂度或参数冗余在一些场景和设备上限制了相应的模型部署需要借助模型压缩、优化加速、异构计算等方法突破瓶颈。模型压缩算法能够有效降低参数冗余从而减少存储占用、通信带宽和计算复杂度有助于深度学习的应用部署。其中模型量化、裁剪应用比较广泛。在PaddleClas中主要应该应用以下两种算法。
- 量化方法PACT量化
- 裁剪FPGM裁剪
其中具体算法参数请参考[PaddeSlim](https://github.com/PaddlePaddle/PaddleSlim/)。
### PACT量化方法
模型量化主要包括两个部分一是对权重Weight量化一是针对激活值Activation量化。同时对两部分进行量化才能获得最大的计算效率收益。权重可以借助网络正则化等手段让权重分布尽量紧凑减少离群点、不均匀分布情况发生而对于激活值还缺乏有效的手段。
**PACT量化PArameterized Clipping acTivation**是一种新的量化方法该方法通过在量化激活值之前去掉一些离群点将模型量化带来的精度损失降到最低甚至比原模型准确率更高。提出方法的背景是作者发现“在运用权重量化方案来量化activation时激活值的量化结果和全精度结果相差较大”。作者发现activation的量化可能引起的误差很大(相较于weight基本在 0到1范围内activation的值的范围是无限大的这是RELU的结果),所以提出**截断式RELU** 的激活函数。该截断的上界,即$α$ 是可学习的参数,这保证了每层能够通过训练学习到不一样的量化范围,最大程度降低量化带来的舍入误差。其中量化的示意图如下图所示,**PACT**解决问题的方法是,不断裁剪激活值范围,使得激活值分布收窄,从而降低量化映射损失。**PACT**通过对激活数值做裁剪从而减少激活分布中的离群点使量化模型能够得到一个更合理的量化scale降低量化损失。
<div align="center">
<img src="../../images/algorithm_introduction/quantization.jpg" width = "600" />
</div>
**PACT**量化公式如下:
<div align="center">
<img src="../../images/algorithm_introduction/quantization_formula.png" width = "800" height="100"/>
</div>
可以看出PACT思想是用上述量化代替*ReLU*函数,对大于零的部分进行一个截断操作,截断阈值为$a$。但是在*PaddleSlim*中对上述公式做了进一步的改进,其改进如下:
<div align="center">
<img src="../../images/algorithm_introduction/quantization_formula_slim.png" width = "550" height="120"/>
</div>
经过如上改进后在激活值和待量化的OP卷积全连接等之间插入*PACT*预处理不只对大于0的分布进行截断同时也对小于0的部分做同样的限制从而更好地得到待量化的范围降低量化损失。同时截断阈值是一个可训练的参数在量化训练过程中模型会自动的找到一个合理的截断阈值从而进一步降低量化精度损失。
算法具体参数请参考PaddleSlim中[参数介绍](https://github.com/PaddlePaddle/PaddleSlim/blob/release/2.0.0/docs/zh_cn/api_cn/dygraph/quanter/qat.rst#qat)。
### FPGM裁剪
模型剪枝是减小模型大小提升预测效率的一种非常重要的手段。在之前的网络剪枝文章中一般将网络filter的范数作为其重要性度量**范数值较小的代表的filter越不重要**,将其从网络中裁剪掉,反之也就越重要。而**FPGM**认为之前的方法要依赖如下两点
- filter的范数偏差应该比较大这样重要和非重要的filter才可以很好区分开
- 不重要的filter的范数应该足够的小
基于此,**FPGM**利用层中filter的几何中心特性由于那些靠近中心的filter可以被其它的表达因而可以将其剔除从而避免了上面提到的两点剪枝条件从信息的冗余度出发而不是选择范数少的进行剪枝。下图展示了**FPGM**方法与之前方法的不同,具体细节请详看[论文](https://openaccess.thecvf.com/content_CVPR_2019/papers/He_Filter_Pruning_via_Geometric_Median_for_Deep_Convolutional_Neural_Networks_CVPR_2019_paper.pdf)。
<div align="center">
<img src="../../images/algorithm_introduction/fpgm.png" width = "600" />
</div>
算法具体参数请参考PaddleSlim中[参数介绍](https://github.com/PaddlePaddle/PaddleSlim/blob/release/2.0.0/docs/zh_cn/api_cn/dygraph/pruners/fpgm_filter_pruner.rst#fpgmfilterpruner)。

View File

@ -1,38 +0,0 @@
# 动漫人物识别
自七十年代以来人脸识别已经成为了计算机视觉和生物识别领域研究最多的主题之一。近年来传统的人脸识别方法已经被基于卷积神经网络CNN的深度学习方法代替。目前人脸识别技术广泛应用于安防、商业、金融、智慧自助终端、娱乐等各个领域。而在行业应用强烈需求的推动下动漫媒体越来越受到关注动漫人物的人脸识别也成为一个新的研究领域。
## 1 算法介绍
算法整体流程,详见[特征学习](./feature_learning.md)整体流程。值得注意的是,本流程没有使用`Neck`模块。
具体配置信息详见[配置文件](../../../ppcls/configs/Cartoonface/ResNet50_icartoon.yaml)。
具体模块如下所示,
### 1.1 数据增强
- 图像`Resize`到224
- 随机水平翻转
- Normalize归一化到0~1
### 1.2 Backbone的具体设置
采用ResNet50作为backbone。并采用大模型进行蒸馏
### 1.3 Metric Learning相关Loss设置
在动漫人物识别中,只使用了`CELoss`
## 2 实验结果
本方法使用iCartoonFace[1]数据集进行验证。该数据集由 5013 个动漫角色的 389678 张图像组成,并带有 ID、边界框、姿势和其他辅助属性。 iCartoonFace 是目前图像识别领域规模最大的卡通媒体数据集,而且质量高、注释丰富、内容全面,其中包含相似图像、有遮挡的图像以及外观有变化的图像。
与其他数据集相比iCartoonFace无论在图像数量还是实体数量上均具有明显领先的优势。其中训练集 5013类389678张图像 验证集: query2500张gallery20000张。
![icartoon](../../images/icartoon1.png)
值得注意的是相比于人脸识别任务动漫人物头像的配饰、道具、发型等因素可以显著提升识别的准确率因此在原数据集标注框的基础上长、宽各expand为之前的2倍并做截断处理得到了目前训练所有的数据集。
在此数据集上此方法Recall1 达到83.24%。
## 3 参考文献
[1] Cartoon Face Recognition: A Benchmark Dataset. 2020. [下载地址](https://github.com/luxiangju-PersonAI/iCartoonFace)

View File

@ -1,29 +0,0 @@
# 特征学习
此部分主要是针对特征学习的训练模式进行说明,即`RecModel`的训练模式。主要是为了支持车辆识别车辆细分类、ReID、Logo识别、动漫人物识别、商品识别等特征学习的应用。与在`ImageNet`上训练普通的分类网络不同的是,此特征学习部分,主要有以下特征
- 支持对`backbone`的输出进行截断,即支持提取任意中间层的特征信息
- 支持在`backbone`的feature输出层后添加可配置的网络层即`Neck`部分
- 支持`ArcFace Loss`等`metric learning` 相关loss函数提升特征学习能力
## 1 整体流程
![](../../images/recognition/rec_pipeline.png)
特征学习的整体结构如上图所示主要包括数据增强、Backbone的设置、Neck、Metric Learning等几大部分。其中`Neck`部分为自由添加的网络层如添加的embedding层等当然也可以不用此模块。训练时利用`Metric Learning`部分的Loss对模型进行优化。预测时一般来说默认以`Neck`部分的输出作为特征输出。
针对不同的应用可以根据需要对每一部分自由选择。每一部分的具体配置如数据增强、Backbone、Neck、Metric Learning相关Loss等设置详见具体应用[车辆识别](./vehicle_recognition.md)、[Logo识别](./logo_recognition.md)、[动漫人物识别](./cartoon_character_recognition.md)、[商品识别](./product_recognition.md)
## 2 配置文件说明
配置文件说明详见[yaml配置文件说明文档](../tutorials/config.md)。其中模型结构配置,详见文档中**识别模型结构配置**部分。
## 3 预训练模型
以下为各应用在不同数据集下的预训练模型
- 车辆细分类:[CompCars](https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/models/pretrain/vehicle_cls_ResNet50_CompCars_v1.2_pretrained.pdparams)
- 车辆ReID[VERI-Wild](https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/models/pretrain/vehicle_reid_ResNet50_VERIWild_v1.1_pretrained.pdparams)
- 动漫人物识别:[iCartoon](https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/models/pretrain/cartoon_rec_ResNet50_iCartoon_v1.0_pretrained.pdparams)
- Logo识别[Logo3K](https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/models/pretrain/logo_rec_ResNet50_Logo3K_v1.1_pretrained.pdparams)
- 商品识别: [Inshop](https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/models/pretrain/product_ResNet50_vd_Inshop_pretrained_v1.1.pdparams)、[Aliproduct](https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/models/pretrain/product_ResNet50_vd_Aliproduct_v1.0_pretrained.pdparams)

View File

@ -1,8 +0,0 @@
应用拓展
================================
.. toctree::
:maxdepth: 2
transfer_learning.md
object_detection.md

View File

@ -1,52 +0,0 @@
# Logo识别
Logo识别技术是现实生活中应用很广的一个领域比如一张照片中是否出现了Adidas或者Nike的商标Logo或者一个杯子上是否出现了星巴克或者可口可乐的商标Logo。通常Logo类别数量较多时往往采用检测+识别两阶段方式检测模块负责检测出潜在的Logo区域根据检测区域抠图后输入识别模块进行识别。识别模块多采用检索的方式根据查询图片和底库图片进行相似度排序获得预测类别。此文档主要对Logo图片的特征提取部分进行相关介绍。
## 1 算法介绍
算法整体流程,详见[特征学习](./feature_learning.md)整体流程。
整体设置详见: [ResNet50_ReID.yaml](../../../ppcls/configs/Logo/ResNet50_ReID.yaml)。
具体模块如下所示
### 1.1数据增强
与普通训练分类不同,此部分主要使用如下图像增强方式:
- 图像`Resize`到224。对于Logo而言使用的图像直接为检测器crop之后的图像因此直接resize到224
- [AugMix](https://arxiv.org/abs/1912.02781v1)模拟Logo图像形变变化等实际场景
- [RandomErasing](https://arxiv.org/pdf/1708.04896v2.pdf):模拟遮挡等实际情况
### 1.2 Backbone的具体设置
使用`ResNet50`作为backbone同时做了如下修改
- last stage stride=1, 保持最后输出特征图尺寸14x14。计算量增加较小但显著提高模型特征提取能力
具体代码:[ResNet50_last_stage_stride1](../../../ppcls/arch/backbone/variant_models/resnet_variant.py)
### 1.3 Neck部分
为了降低inferecne时计算特征距离的复杂度添加一个embedding 卷积层特征维度为512。
### 1.4 Metric Learning相关Loss的设置
在Logo识别中使用了[Pairwise Cosface + CircleMargin](https://arxiv.org/abs/2002.10857) 联合训练其中权重比例为1:1
具体代码详见:[PairwiseCosface](../../../ppcls/loss/pairwisecosface.py) 、[CircleMargin](../../../ppcls/arch/gears/circlemargin.py)
## 2 实验结果
<img src="../../images/logo/logodet3k.jpg" style="zoom:50%;" />
使用LogoDet-3K[1]数据集进行实验此数据集是具有完整标注的Logo数据集有3000个标识类别约20万个高质量的人工标注的标识对象和158652张图片。
由于原始的数据集中图像包含标注的检测框在识别阶段只考虑检测器抠图后的logo区域因此采用原始的标注框抠出Logo区域图像构成训练集排除背景在识别阶段的影响。对数据集进行划分产生155427张训练集覆盖3000个logo类别同时作为测试时gallery图库3225张测试集用于作为查询集。抠图后的训练集可[在此下载](https://arxiv.org/abs/2008.05359)
在此数据集上recall1 达到89.8%。
## 3 参考文献
[1] LogoDet-3K: A Large-Scale Image Dataset for Logo Detection[J]. arXiv preprint arXiv:2008.05359, 2020.

View File

@ -1,188 +0,0 @@
# 主体检测
主体检测技术是目前应用非常广泛的一种检测技术,它指的是检测出图片中一个或者多个主体的坐标位置,然后将图像中的对应区域裁剪下来,进行识别,从而完成整个识别过程。主体检测是识别任务的前序步骤,可以有效提升识别精度。
本部分主要从数据集、模型训练2个方面对该部分内容进行介绍。
## 1. 数据集
在PaddleClas的识别任务中训练主体检测模型时主要用到了以下几个数据集。
| 数据集 | 数据量 | 主体检测任务中使用的数据量 | 场景 | 数据集地址 |
| ------------ | ------------- | -------| ------- | -------- |
| Objects365 | 170W | 6k | 通用场景 | [地址](https://www.objects365.org/overview.html) |
| COCO2017 | 12W | 5k | 通用场景 | [地址](https://cocodataset.org/) |
| iCartoonFace | 2k | 2k | 动漫人脸检测 | [地址](https://github.com/luxiangju-PersonAI/iCartoonFace) |
| LogoDet-3k | 3k | 2k | Logo检测 | [地址](https://github.com/Wangjing1551/LogoDet-3K-Dataset) |
| RPC | 3k | 3k | 商品检测 | [地址](https://rpc-dataset.github.io/) |
在实际训练的过程中,将所有数据集混合在一起。由于是主体检测,这里将所有标注出的检测框对应的类别都修改为"前景"的类别最终融合的数据集中只包含1个类别即前景。
## 2. 模型选择
目标检测方法种类繁多比较常用的有两阶段检测器如FasterRCNN系列等单阶段检测器如YOLO、SSD等anchor-free检测器如FCOS等
PP-YOLO由[PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection)提出从骨干网络、数据增广、正则化策略、损失函数、后处理等多个角度对yolov3模型进行深度优化最终在"速度-精度"方面达到了业界领先的水平。具体地,优化的策略如下。
- 更优的骨干网络: ResNet50vd-DCN
- 更大的训练batch size: 8 GPUs每GPU batch_size=24对应调整学习率和迭代轮数
- [Drop Block](https://arxiv.org/abs/1810.12890)
- [Exponential Moving Average](https://www.investopedia.com/terms/e/ema.asp)
- [IoU Loss](https://arxiv.org/pdf/1902.09630.pdf)
- [Grid Sensitive](https://arxiv.org/abs/2004.10934)
- [Matrix NMS](https://arxiv.org/pdf/2003.10152.pdf)
- [CoordConv](https://arxiv.org/abs/1807.03247)
- [Spatial Pyramid Pooling](https://arxiv.org/abs/1406.4729)
- 更优的预训练模型
更多关于PP-YOLO的详细介绍可以参考[PP-YOLO 模型](https://github.com/PaddlePaddle/PaddleDetection/blob/release%2F2.1/configs/ppyolo/README_cn.md)
在主体检测任务中为了保证检测效果我们使用ResNet50vd-DCN的骨干网络使用配置文件[ppyolov2_r50vd_dcn_365e_coco.yml](https://github.com/PaddlePaddle/PaddleDetection/blob/release/2.1/configs/ppyolo/ppyolov2_r50vd_dcn_365e_coco.yml),更换为自定义的主体检测数据集,进行训练,最终得到检测模型。
主体检测模型的inference模型下载地址为[链接](https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/models/inference/ppyolov2_r50vd_dcn_mainbody_v1.0_infer.tar)。
## 3. 模型训练
本节主要介绍怎样基于PaddleDetection基于自己的数据集训练主体检测模型。
### 3.1 环境准备
下载PaddleDetection代码安装requirements。
```shell
cd <path/to/clone/PaddleDetection>
git clone https://github.com/PaddlePaddle/PaddleDetection.git
cd PaddleDetection
# 安装其他依赖
pip install -r requirements.txt
```
更多安装教程,请参考: [安装文档](https://github.com/PaddlePaddle/PaddleDetection/blob/release/2.1/docs/tutorials/INSTALL_cn.md)
### 3.2 数据准备
对于自定义数据集首先需要将自己的数据集修改为COCO格式可以参考[自定义检测数据集教程](https://github.com/PaddlePaddle/PaddleDetection/blob/release/2.1/static/docs/tutorials/Custom_DataSet.md)制作COCO格式的数据集。
主体检测任务中,所有的检测框均属于前景,在这里需要将标注文件中,检测框的`category_id`修改为1同时将整个标注文件中的`categories`映射表修改为下面的格式,即整个类别映射表中只包含`前景`类别。
```json
[{u'id': 1, u'name': u'foreground', u'supercategory': u'foreground'}]
```
### 3.3 配置文件改动和说明
我们使用 `configs/ppyolo/ppyolov2_r50vd_dcn_365e_coco.yml`配置进行训练,配置文件摘要如下:
<div align='center'>
<img src='../../images/det/PaddleDetection_config.png' width='400'/>
</div>
从上图看到 `ppyolov2_r50vd_dcn_365e_coco.yml` 配置需要依赖其他的配置文件,这些配置文件的含义如下:
```
coco_detection.yml主要说明了训练数据和验证数据的路径
runtime.yml主要说明了公共的运行参数比如是否使用GPU、每多少个epoch存储checkpoint等
optimizer_365e.yml主要说明了学习率和优化器的配置
ppyolov2_r50vd_dcn.yml主要说明模型和主干网络的情况
ppyolov2_reader.yml主要说明数据读取器配置如batch size并发加载子进程数等同时包含读取后预处理操作如resize、数据增强等等
```
在主体检测任务中,需要将`datasets/coco_detection.yml`中的`num_classes`参数修改为1只有1个前景类别同时将训练集和测试集的路径修改为自定义数据集的路径。
此外也可以根据实际情况修改上述文件比如如果显存溢出可以将batch size和学习率等比缩小等。
### 3.4 启动训练
PaddleDetection提供了单卡/多卡训练模式,满足用户多种训练需求。
* GPU 单卡训练
```bash
# windows和Mac下不需要执行该命令
export CUDA_VISIBLE_DEVICES=0
python tools/train.py -c configs/ppyolo/ppyolov2_r50vd_dcn_365e_coco.yml
```
* GPU多卡训练
```bash
export CUDA_VISIBLE_DEVICES=0,1,2,3
python -m paddle.distributed.launch --gpus 0,1,2,3 tools/train.py -c configs/ppyolo/ppyolov2_r50vd_dcn_365e_coco.yml --eval
```
--eval表示边训练边验证。
* (**推荐**)模型微调
如果希望加载PaddleClas中已经训练好的主体检测模型在自己的数据集上进行模型微调可以使用下面的命令进行训练。
```bash
export CUDA_VISIBLE_DEVICES=0
# 指定pretrain_weights参数加载通用的主体检测预训练模型
python tools/train.py -c configs/ppyolo/ppyolov2_r50vd_dcn_365e_coco.yml -o pretrain_weights=https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/models/pretrain/ppyolov2_r50vd_dcn_mainbody_v1.0_pretrained.pdparams
```
* 模型恢复训练
在日常训练过程中,有的用户由于一些原因导致训练中断,可以使用-r的命令恢复训练:
```bash
export CUDA_VISIBLE_DEVICES=0,1,2,3
python -m paddle.distributed.launch --gpus 0,1,2,3 tools/train.py -c configs/ppyolo/ppyolov2_r50vd_dcn_365e_coco.yml --eval -r output/ppyolov2_r50vd_dcn_365e_coco/10000
```
注意:如果遇到 "`Out of memory error`" 问题, 尝试在 `ppyolov2_reader.yml` 文件中调小`batch_size`
### 3.5 模型预测与调试
使用下面的命令完成PaddleDetection的预测过程。
```bash
export CUDA_VISIBLE_DEVICES=0
python tools/infer.py -c configs/ppyolo/ppyolov2_r50vd_dcn_365e_coco.yml --infer_img=your_image_path.jpg --output_dir=infer_output/ --draw_threshold=0.5 -o weights=output/ppyolov2_r50vd_dcn_365e_coco/model_final
```
`--draw_threshold` 是个可选参数. 根据 [NMS](https://ieeexplore.ieee.org/document/1699659) 的计算,不同阈值会产生不同的结果 `keep_top_k`表示设置输出目标的最大数量默认值为100用户可以根据自己的实际情况进行设定。
### 3.6 模型导出与预测部署。
执行导出模型脚本:
```bash
python tools/export_model.py -c configs/ppyolo/ppyolov2_r50vd_dcn_365e_coco.yml --output_dir=./inference -o weights=output/ppyolov2_r50vd_dcn_365e_coco/model_final.pdparams
```
预测模型会导出到`inference/ppyolov2_r50vd_dcn_365e_coco`目录下,分别为`infer_cfg.yml`(预测不需要), `model.pdiparams`, `model.pdiparams.info`,`model.pdmodel` 。
注意:`PaddleDetection`导出的inference模型的文件格式为`model.xxx`这里如果希望与PaddleClas的inference模型文件格式保持一致需要将其`model.xxx`文件修改为`inference.xxx`文件,用于后续主体检测的预测部署。
更多模型导出教程,请参考:[EXPORT_MODEL](https://github.com/PaddlePaddle/PaddleDetection/blob/release/2.1/deploy/EXPORT_MODEL.md)
最终,目录`inference/ppyolov2_r50vd_dcn_365e_coco`中包含`inference.pdiparams`, `inference.pdiparams.info` 以及 `inference.pdmodel` 文件,其中`inference.pdiparams`为保存的inference模型权重文件`inference.pdmodel`为保存的inference模型结构文件。
导出模型之后在主体检测与识别任务中就可以将检测模型的路径更改为该inference模型路径完成预测。
以商品识别为例,其配置文件为[inference_product.yaml](../../../deploy/configs/inference_product.yaml),修改其中的`Global.det_inference_model_dir`字段为导出的主体检测inference模型目录参考[图像识别快速开始教程](../tutorials/quick_start_recognition.md),即可完成商品检测与识别过程。
### FAQ
#### Q可以使用其他的主体检测模型结构吗
* A可以的但是目前的检测预处理过程仅适配yolo系列的预处理因此在使用的时候建议优先使用yolo系列的模型进行训练如果希望使用faster rcnn等其他系列的模型需要按照PaddleDetection的数据预处理修改下预处理逻辑这块如果您有需求或者有问题的话欢迎提issue或者在群里反馈。
#### Q可以修改主体检测的预测尺度吗
* A可以的但是需要注意2个地方
* PaddleClas中提供的主体检测模型是基于640x640的分辨率去训练的因此预测的时候也是默认使用640x640的分辨率进行预测使用其他分辨率预测的话精度会有所降低。
* 在模型导出的时候,建议也修改下模型导出的分辨率,保持模型导出、模型预测的分辨率一致。

View File

@ -1,39 +0,0 @@
# 通用目标检测
## 服务器端实用目标检测方案
### 简介
* 近年来学术界和工业界广泛关注图像中目标检测任务。基于SSLD蒸馏方案训练得到的ResNet50_vd预训练模型(ImageNet1k验证集上Top1 Acc为82.39%)结合PaddleDetection中的丰富算子飞桨提供了一种面向服务器端实用的目标检测方案PSS-DET(Practical Server Side Detection)。基于COCO2017目标检测数据集V100单卡预测速度为为61FPS时COCO mAP可达41.6%预测速度为20FPS时COCO mAP可达47.8%。
### 消融实验
* 我们以标准的Faster RCNN ResNet50_vd FPN为例下表给出了PSS-DET不同的模块的速度与精度收益。
| Trick | Train scale | Test scale | COCO mAP | Infer speed/FPS |
|- |:-: |:-: | :-: | :-: |
| `baseline` | 640x640 | 640x640 | 36.4% | 43.589 |
| +`test proposal=pre/post topk 500/300` | 640x640 | 640x640 | 36.2% | 52.512 |
| +`fpn channel=64` | 640x640 | 640x640 | 35.1% | 67.450 |
| +`ssld pretrain` | 640x640 | 640x640 | 36.3% | 67.450 |
| +`ciou loss` | 640x640 | 640x640 | 37.1% | 67.450 |
| +`DCNv2` | 640x640 | 640x640 | 39.4% | 60.345 |
| +`3x, multi-scale training` | 640x640 | 640x640 | 41.0% | 60.345 |
| +`auto augment` | 640x640 | 640x640 | 41.4% | 60.345 |
| +`libra sampling` | 640x640 | 640x640 | 41.6% | 60.345 |
基于该实验结论我们结合Cascade RCNN使用更大的训练与评估尺度(1000x1500)最终在单卡V100上速度为20FPSCOCO mAP达47.8%。下图给出了目前类似速度的目标检测方法的速度与精度指标。
![pssdet](../../images/det/pssdet.png)
**注意**
> 这里为了更方便地对比我们将V100的预测耗时乘以1.2倍近似转化为Titan V的预测耗时。
更加详细的代码、配置与预训练模型的地址可以参考[PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection/tree/master/configs/rcnn_server_side_det)。
## 移动端实用目标检测方案
* 目前正在更新中,敬请期待!

View File

@ -1,41 +0,0 @@
# 商品识别
商品识别技术,是现如今应用非常广的一个领域。拍照购物的方式已经被很多人所采纳,无人结算台已经走入各大超市,无人超市更是如火如荼,这背后都是以商品识别技术作为支撑。商品识别技术大概是"商品检测+商品识别"这样的流程,商品检测模块负责检测出潜在的商品区域,商品识别模型负责将商品检测模块检测出的主体进行识别。识别模块多采用检索的方式,根据查询图片和底库图片进行相似度排序获得预测类别。此文档主要对商品图片的特征提取部分进行相关介绍。
## 1 算法介绍
算法整体流程,详见[特征学习](./feature_learning.md)整体流程。
整体设置详见: [ResNet50_vd_Aliproduct.yaml](../../../ppcls/configs/Products/ResNet50_vd_Aliproduct.yaml)
具体细节如下所示。
### 1.1数据增强
- 图像`RandomCrop`到224x224
- 图像`RandomFlip`
- Normlize图像归一化
### 1.2 Backbone的具体设置
具体是用`ResNet50_vd`作为backbone使用ImageNet预训练模型
### 1.3 Neck部分
加入一个512维的embedding FC层没有做BatchNorm和激活。
### 1.4 Metric Learning相关Loss的设置
目前使用了[CELoss](../../../ppcls/loss/celoss.py)训练, 为了获得更加鲁棒的特征后续会使用其他Loss参与训练敬请期待。
## 2 实验结果
<img src="../../images/product/aliproduct.png" style="zoom:50%;" />
此方案在Aliproduct[1]数据集上进行实验。此数据集是天池竞赛开源的一个数据集也是目前开源的最大的商品数据集其有5万多个标识类别约250万训练图片。
在此数据上单模型Top 1 Acc85.67%。
## 3 参考文献
[1] Weakly Supervised Learning with Side Information for Noisy Labeled Images. ECCV, 2020.

View File

@ -1,86 +0,0 @@
# 图像分类迁移学习
迁移学习是机器学习领域的一个重要分支,广泛应用于文本、图像等各种领域,此处我们主要介绍的是图像分类领域的迁移学习,也就是我们常说的域迁移,比如将 ImageNet 分类模型迁移到我们自己场景的图像分类任务上,如花卉分类。
## 一、 超参搜索
ImageNet 作为业界常用的图像分类数据被大家广泛使用,已经总结出一系列经验性的超参,使用这些超参往往能够得到不错的训练精度,而这些经验性的参数在迁移到自己的业务中时,有时效果不佳。有两种常用的超参搜索方法可以用于获得更好的模型超参。
### 1.1 网格搜索
网格搜索,即穷举搜索,通过查找搜索空间内所有的点,确定最优值。方法简单有效,但当搜索空间较大时,需要消耗大量的计算资源。
### 1.2 贝叶斯搜索
贝叶斯搜索即贝叶斯优化在搜索空间中随机选取超参数点采用高斯过程即根据上一个超参数点的结果更新当前的先验信息计算前面n个超参数点的后验概率分布得到搜索空间中每一个超参数点的期望均值和方差其中期望均值越大表示接近最优指标的可能性越大方差越大表示不确定性越大。通常将选择期望均值大的超参数点称为`exporitation`,选择方差大的超参数点称为`exploration`。在贝叶斯优化中通过定义`acquisition function`权衡期望均值和方差。贝叶斯搜索认为当前选择的超参数点是处于最大值可能出现的位置。
------
基于上述两种搜索方案我们在8个开源数据集上将固定一组参数实验以及两种搜索方案做了对比实验参照[1]的实验方案我们对4个超参数进行搜索搜索空间及实验结果如下所示
- 固定参数:
```
初始学习率lr=0.003l2 decay=1e-4label smoothing=Falsemixup=False
```
- 超参搜索空间:
```
初始学习率lr: [0.1, 0.03, 0.01, 0.003, 0.001, 0.0003, 0.0001]
L2 decay: [1e-3, 3e-4, 1e-4, 3e-5, 1e-5, 3e-6, 1e-6]
Label smoothing: [False, True]
Mixup: [False, True]
```
网格搜索的搜索次数为196次而贝叶斯搜索通过设置最大迭代次数`max_iter`)和是否重复搜索(`de_duplication`来确定搜索次数。我们设计了系列实验baseline为ImageNet1k校验集Top1 Acc为79.12%的ResNet50_vd预训练模型并固定超参在新数据集上finetune得到的模型。下表给出了固定参数、网格搜索以及贝叶斯搜索的精度与搜索次数对比。
- 精度与搜索次数对比:
| 数据集 | 固定参数 | 网格搜索 | 网格搜索次数 | 贝叶斯搜索 | 贝叶斯搜索次数|
| ------------------ | -------- | -------- | -------- | -------- | ---------- |
| Oxford-IIIT-Pets | 93.64% | 94.55% | 196 | 94.04% | 20 |
| Oxford-102-Flowers | 96.08% | 97.69% | 196 | 97.49% | 20 |
| Food101 | 87.07% | 87.52% | 196 | 87.33% | 23 |
| SUN397 | 63.27% | 64.84% | 196 | 64.55% | 20 |
| Caltech101 | 91.71% | 92.54% | 196 | 92.16% | 14 |
| DTD | 76.87% | 77.53% | 196 | 77.47% | 13 |
| Stanford Cars | 85.14% | 92.72% | 196 | 92.72% | 25 |
| FGVC Aircraft | 80.32% | 88.45% | 196 | 88.36% | 20 |
- 上述实验验证了贝叶斯搜索相比网格搜索在减少搜索次数10倍左右条件下精度只下降0%~0.4%。
- 当搜索空间进一步扩大时例如将是否进行AutoAugmentRandAugmentCutout Cutmix以及Dropout这些正则化策略作为选择时贝叶斯搜索能够在获取较优精度的前提下有效地降低搜索次数。
## 二、 大规模分类模型
在实际应用中由于训练数据的匮乏往往将ImageNet1k数据集训练的分类模型作为预训练模型进行图像分类的迁移学习。为了进一步助力解决实际问题基于ResNet50_vd, 百度开源了自研的大规模分类预训练模型其中训练数据为10万个类别4300万张图片。10万类预训练模型的下载地址[**下载地址**](https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ResNet50_vd_10w_pretrained.pdparams)
我们在6个自有采集的数据集上进行迁移学习实验采用一组固定参数以及网格搜索方式其中训练轮数设置为20epochs选用ResNet50_vd模型ImageNet预训练精度为79.12%。实验数据集参数以及模型精度的对比结果如下:
固定参数:
```
初始学习率lr=0.001l2 decay=1e-4label smoothing=Falsemixup=False
```
| 数据集 | 数据统计 | **ImageNet预训练模型 <br />固定参数Top-1/参数搜索Top-1** | **大规模分类预训练模型<br />固定参数Top-1/参数搜索Top-1** |
| --------------- | ----------------------------------------- | -------------------------------------------------------- | --------------------------------------------------------- |
| 花卉 | class:102<br />train:5789<br />valid:2396 | 0.7779/0.9883 | 0.9892/0.9954 |
| 手绘简笔画 | Class:18<br />train:1007<br />valid:432 | 0.8795/0.9196 | 0.9107/0.9219 |
| 植物叶子 | class:6<br />train:5256<br />valid:2278 | 0.8212/0.8482 | 0.8385/0.8659 |
| 集装箱车辆 | Class:115<br />train:4879<br />valid:2094 | 0.6230/0.9556 | 0.9524/0.9702 |
| 椅子 | class:5<br />train:169<br />valid:78 | 0.8557/0.9688 | 0.9077/0.9792 |
| 地质 | class:4<br />train:671<br />valid:296 | 0.5719/0.8094 | 0.6781/0.8219 |
- 通过上述的实验验证了当使用一组固定参数时相比于ImageNet预训练模型使用大规模分类模型作为预训练模型在大多数情况下能够提升模型在新的数据集上得效果通过参数搜索可以进一步提升精度。
## 参考文献
[1] Kornblith, Simon, Jonathon Shlens, and Quoc V. Le. "Do better imagenet models transfer better?." *Proceedings of the IEEE conference on computer vision and pattern recognition*. 2019.
[2] Kolesnikov, Alexander, et al. "Large Scale Learning of General Visual Representations for Transfer." *arXiv preprint arXiv:1912.11370* (2019).

View File

@ -1,97 +0,0 @@
# 车辆识别
此部分主要包含两部分车辆细粒度分类、车辆ReID。
细粒度分类,是对属于某一类基础类别的图像进行子类别的细粉,如各种鸟、各种花、各种矿石之间。顾名思义,车辆细粒度分类是对车辆的不同子类别进行分类。
ReID也就是 Re-identification其定义是利用算法在图像库中找到要搜索的目标的技术所以它是属于图像检索的一个子问题。而车辆ReID就是给定一张车辆图像找出同一摄像头不同的拍摄图像或者不同摄像头下拍摄的同一车辆图像的过程。在此过程中如何提取鲁棒特征尤为重要。
此文档中,使用同一套训练方案对两个细方向分别做了尝试。
## 1 算法介绍
算法整体流程,详见[特征学习](./feature_learning.md)整体流程。
车辆ReID整体设置详见: [ResNet50_ReID.yaml](../../../ppcls/configs/Vehicle/ResNet50_ReID.yaml)。
车辆细分类整体设置详见:[ResNet50.yaml](../../../ppcls/configs/Vehicle/ResNet50.yaml)
具体细节如下所示。
### 1.1数据增强
与普通训练分类不同,此部分主要使用如下图像增强方式:
- 图像`Resize`到224。尤其对于ReID而言车辆图像已经是由检测器检测后crop出的车辆图像因此若再使用crop图像增强会丢失更多的车辆信息
- [AugMix](https://arxiv.org/abs/1912.02781v1):模拟光照变化、摄像头位置变化等实际场景
- [RandomErasing](https://arxiv.org/pdf/1708.04896v2.pdf):模拟遮挡等实际情况
### 1.2 Backbone的具体设置
使用`ResNet50`作为backbone同时做了如下修改
- last stage stride=1, 保持最后输出特征图尺寸14x14。计算量增加较小但显著提高模型特征提取能力
具体代码:[ResNet50_last_stage_stride1](../../../ppcls/arch/backbone/variant_models/resnet_variant.py)
### 1.3 Neck部分
为了降低inferecne时计算特征距离的复杂度添加一个embedding 卷积层特征维度为512。
### 1.4 Metric Learning相关Loss的设置
车辆ReID及细粒度分类中使用了[SupConLoss](../../../ppcls/loss/supconloss.py) + [ArcLoss](../../../ppcls/arch/gears/arcmargin.py)其中权重比例为1:1
## 2 实验结果
### 2.1 车辆ReID
<img src="../../images/recognition/vehicle/cars.JPG" style="zoom:50%;" />
此方法在VERI-Wild数据集上进行了实验。此数据集是在一个大型闭路电视监控系统在无约束的场景下一个月内30*24小时中捕获的。该系统由174个摄像头组成其摄像机分布在200多平方公里的大型区域。原始车辆图像集包含1200万个车辆图像经过数据清理和标注采集了416314张40671个不同的车辆图像。[具体详见论文](https://github.com/PKU-IMRE/VERI-Wild)
| **Methods** | **Small** | | |
| :--------------------------: | :-------: | :-------: | :-------: |
| | mAP | Top1 | Top5 |
| Strong baesline(Resnet50)[1] | 76.61 | 90.83 | 97.29 |
| HPGN(Resnet50+PGN)[2] | 80.42 | 91.37 | - |
| GLAMOR(Resnet50+PGN)[3] | 77.15 | 92.13 | 97.43 |
| PVEN(Resnet50)[4] | 79.8 | 94.01 | 98.06 |
| SAVER(VAE+Resnet50)[5] | 80.9 | 93.78 | 97.93 |
| PaddleClas baseline | 80.57 | **93.81** | **98.06** |
### 2.2 车辆细分类
车辆细分类中,使用[CompCars](http://mmlab.ie.cuhk.edu.hk/datasets/comp_cars/index.html)作为训练数据集。
![](../../images/recognition/vehicle/CompCars.png)
数据集中图像主要来自网络和监控数据其中网络数据包含163个汽车制造商、1716个汽车型号的汽车。共**136,726**张全车图像,**27,618**张部分车图像。其中网络汽车数据包含bounding box、视角、5个属性最大速度、排量、车门数、车座数、汽车类型。监控数据包含**50,000**张前视角图像。
值得注意的是此数据集中需要根据自己的需要生成不同的label如本demo中将不同年份生产的相同型号的车辆视为同一类因此类别总数为431类。
| **Methods** | Top1 Acc |
| :-----------------------------: | :--------: |
| ResNet101-swp[6] | 97.6% |
| Fine-Tuning DARTS[7] | 95.9% |
| Resnet50 + COOC[8] | 95.6% |
| A3M[9] | 95.4% |
| PaddleClas baseline (ResNet50) | **97.37**% |
## 3 参考文献
[1] Bag of Tricks and a Strong Baseline for Deep Person Re-Identification.CVPR workshop 2019.
[2] Exploring Spatial Significance via Hybrid Pyramidal Graph Network for Vehicle Re-identification. In arXiv preprint arXiv:2005.14684
[3] GLAMORous: Vehicle Re-Id in Heterogeneous Cameras Networks with Global and Local Attention. In arXiv preprint arXiv:2002.02256
[4] Parsing-based view-aware embedding network for vehicle re-identification. CVPR 2020.
[5] The Devil is in the Details: Self-Supervised Attention for Vehicle Re-Identification. In ECCV 2020.
[6] Deep CNNs With Spatially Weighted Pooling for Fine-Grained Car Recognition. IEEE Transactions on Intelligent Transportation Systems, 2017.
[7] Fine-Tuning DARTS for Image Classification. 2020.
[8] Fine-Grained Vehicle Classification with Unsupervised Parts Co-occurrence Learning. 2018
[9] Attribute-Aware Attention Model for Fine-grained Representation Learning. 2019.

View File

@ -1,79 +0,0 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import recommonmark
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# -- Project information -----------------------------------------------------
project = 'PaddleClas'
copyright = '2020, paddlepaddle'
author = 'paddlepaddle'
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.napoleon',
'sphinx.ext.coverage',
'sphinx.ext.viewcode',
'sphinx.ext.mathjax',
'sphinx.ext.githubpages',
'sphinx.ext.napoleon',
'recommonmark',
'sphinx_markdown_tables',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# md file can also be parased
source_suffix = ['.rst', '.md']
# The master toctree document.
master_doc = 'index'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = 'zh_CN'
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
# on_rtd is whether we are on readthedocs.org, this line of code grabbed from docs.readthedocs.org
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
if not on_rtd: # only import and set the theme if we're building docs locally
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# otherwise, readthedocs.org uses their theme by default, so no need to specify it
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_logo = '../images/logo.png'

View File

@ -0,0 +1,107 @@
# 图像分类任务数据集说明
本文档将介绍 PaddleClas 所使用的图像分类任务数据集格式,以及图像分类领域的常见数据集介绍。
---
## 1. 数据集格式说明
PaddleClas 使用 `txt` 格式文件指定训练集和测试集,以 `ImageNet1k` 数据集为例,其中 `train_list.txt``val_list.txt` 的格式形如:
```shell
# 每一行采用"空格"分隔图像路径与标注
# 下面是train_list.txt中的格式样例
train/n01440764/n01440764_10026.JPEG 0
...
# 下面是val_list.txt中的格式样例
val/ILSVRC2012_val_00000001.JPEG 65
...
```
## 2. 图像分类任务常见数据集介绍
这里整理了常用的图像分类任务数据集,持续更新中,欢迎各位小伙伴补充完善~
### 2.1 ImageNet1k
[ImageNet](https://image-net.org/)项目是一个大型视觉数据库,用于视觉目标识别研究任务,该项目已手动标注了 1400 多万张图像。ImageNet-1k 是 ImageNet 数据集的子集,其包含 1000 个类别。训练集包含 1281167 个图像数据,验证集包含 50000 个图像数据。2010 年以来ImageNet 项目每年举办一次图像分类竞赛,即 ImageNet 大规模视觉识别挑战赛ILSVRC。挑战赛使用的数据集即为 ImageNet-1k。到目前为止ImageNet-1k 已经成为计算机视觉领域发展的最重要的数据集之一,其促进了整个计算机视觉的发展,很多计算机视觉下游任务的初始化模型都是基于该数据集训练得到的。
数据集 | 训练集大小 | 测试集大小 | 类别数 | 备注|
:------:|:---------------:|:---------------------:|:-----------:|:-----------:
[ImageNet1k](http://www.image-net.org/challenges/LSVRC/2012/)|1.2M| 50k | 1000 |
从官方下载数据后,按如下格式组织数据,即可在 PaddleClas 中使用 ImageNet1k 数据集进行训练。
```bash
PaddleClas/dataset/ILSVRC2012/
|_ train/
| |_ n01440764
| | |_ n01440764_10026.JPEG
| | |_ ...
| |_ ...
| |
| |_ n15075141
| |_ ...
| |_ n15075141_9993.JPEG
|_ val/
| |_ ILSVRC2012_val_00000001.JPEG
| |_ ...
| |_ ILSVRC2012_val_00050000.JPEG
|_ train_list.txt
|_ val_list.txt
```
### 2.2 Flowers102
数据集 | 训练集大小 | 测试集大小 | 类别数 | 备注|
:------:|:---------------:|:---------------------:|:-----------:|:-----------:
[flowers102](https://www.robots.ox.ac.uk/~vgg/data/flowers/102/)|1k | 6k | 102 |
将下载的数据解压后,可以看到以下目录
```shell
jpg/
setid.mat
imagelabels.mat
```
将以上文件放置在 `PaddleClas/dataset/flowers102/`
通过运行 `generate_flowers102_list.py` 生成 `train_list.txt``val_list.txt`
```shell
python generate_flowers102_list.py jpg train > train_list.txt
python generate_flowers102_list.py jpg valid > val_list.txt
```
按照如下结构组织数据:
```shell
PaddleClas/dataset/flowers102/
|_ jpg/
| |_ image_03601.jpg
| |_ ...
| |_ image_02355.jpg
|_ train_list.txt
|_ val_list.txt
```
### 2.3 CIFAR10 / CIFAR100
CIFAR-10 数据集由 10 个类的 60000 个彩色图像组成,图像分辨率为 32x32每个类有 6000 个图像,其中训练集 5000 张,验证集 1000 张10 个不同的类代表飞机、汽车、鸟类、猫、鹿、狗、青蛙、马、轮船和卡车。CIFAR-100 数据集是CIFAR-10的扩展由 100 个类的 60000 个彩色图像组成,图像分辨率为 32x32每个类有 600 个图像,其中训练集 500 张,验证集 100 张。
数据集地址http://www.cs.toronto.edu/~kriz/cifar.html
### 2.4 MNIST
MMNIST是一个非常有名的手写体数字识别数据集在很多资料中这个数据集都会被用作深度学习的入门样例。其包含 60000 张图片数据50000 张作为训练集10000 张作为验证集,每张图片的大小为 28 * 28。
数据集地址http://yann.lecun.com/exdb/mnist/
### 2.5 NUS-WIDE
NUS-WIDE 是一个多分类数据集。该数据集包含 269648 张图片, 81 个类别, 每张图片被标记为该 81 个类别中的某一类或某几类。
数据集地址https://lms.comp.nus.edu.sg/wp-content/uploads/2019/research/nuswide/NUS-WIDE.html

View File

@ -0,0 +1,98 @@
# 图像分类任务数据集说明
本文档将介绍 PaddleClas 所使用的图像识别任务数据集格式,以及图像识别领域的常见数据集介绍。
---
## 1. 数据集格式说明
与分类任务数据集不同,图像检索任务的数据集分为以下三部分:
* 训练集合train dataset用来训练模型使模型能够学习该集合的图像特征。
* 底库数据集合gallery dataset用来提供图像检索任务中的底库数据该集合可与训练集或测试集相同也可以不同当与训练集相同时测试集的类别体系应与训练集的类别体系相同。
* 测试数据集合query dataset用来测试模型的好坏通常要对测试集的每一张测试图片进行特征提取之后和底库数据的特征进行距离匹配得到识别结果后根据识别结果计算整个测试集的指标。
训练集、底库数据集和测试数据集均使用 `txt` 文件指定,以 `CUB_200_2011` 数据集为例,训练数据集 `train_list.txt` 文件内容格式如下所示:
```shell
# 采用"空格"作为分隔符号
...
train/99/Ovenbird_0136_92859.jpg 99 2
...
train/99/Ovenbird_0128_93366.jpg 99 6
...
```
每行数据使用“空格”分割三列数据的含义分别是训练数据的路径、训练数据的label信息、训练数据的unique id。
**注意**当gallery dataset和query dataset相同时为了去掉检索得到的第一个数据检索图片本身无须评估每个数据需要对应一个unique id用于后续评测mAP、recall@1等指标。
## 2. 图像识别任务常见数据集介绍
这里整理了常用的图像识别任务数据集,持续更新中,欢迎各位小伙伴补充完善~
### 2.1 通用图像识别数据集
- SOP: SOP数据集是通用识别研究领域、MetricLearning技术研究方向常用的一个商品数据集, 其包含从eBay.com下载的22,634个产品的120,053张图片。其中, 训练集包含图片59551张, 类别数11318; 验证集包含图片60502张类别数11316个。
地址: https://cvgl.stanford.edu/projects/lifted_struct/
- Cars196:
Cars数据集包含了196类汽车的16185张图像。数据被分成8144张训练图像和8041张测试图像每个类大致以50-50的比例分割。级别通常是在制造模型例如2012特斯拉模型S或2012宝马M3双门跑车。
地址: https://ai.stanford.edu/~jkrause/cars/car_dataset.html
- CUB_200_2011: CUB_200_2011数据集是由加州理工学院在2010年提出的细粒度数据集也是目前细粒度分类识别研究的基准图像数据集。该数据集共有11788张鸟类图像包含200类鸟类子类其中训练数据集有5994张图像测试集有5794张图像每张图像均提供了图像类标记信息图像中鸟的bounding box鸟的关键part信息以及鸟类的属性信息数据集如下图所示。
地址: http://www.vision.caltech.edu/visipedia/CUB-200-2011.html
- In-shop Clothes In-shop Clothes 是DeepFashion数据集的4个子集之一, 它是一个卖家秀图片集每个商品id有多张不同角度的卖家秀放在同一个文件夹内。该数据集共包含7982件商品共52712张图像每张图片都有463中属性Bboxlandmarks以及店铺描述。
地址: http://mmlab.ie.cuhk.edu.hk/projects/DeepFashion.html
### 2.2 垂类图像识别数据集
#### 2.2.1 动漫人物识别
+ iCartoonFace: iCartoonFace是由爱奇艺开放的目前全球最大的手工标注卡通人物检测数据集与识别数据集它包含超过5013个卡通人物、389678张高质量实景图片。相比于其他数据集它具有大规模、高质量、多样性丰富、挑战难度大等特点是目前研究动漫人物识别最常用的数据集之一。
地址: http://challenge.ai.iqiyi.com/detail?raceId=5def69ace9fcf68aef76a75d
+ Manga109 Manga109是2020.5月发布的一个用于研究卡通人物检测和识别的数据集其包含21142张图片官方不允许用于商用。该数据集旗下的子集Manga109-s可以供工业使用 主要用于文本检测、基于线稿的任务检索、角色图像生成等任务。
地址http://www.manga109.org/en/
+ IIT-CFWIIF-CFW数据集共包含8928个带有标注的明星人物卡通头像覆盖100个人物形象每个人卡通头像数不等。 另外其还提供了1000张真实人脸照100个公众人物每个人10张真实头像。该数据集既可以用于研究动漫人物识别也经常被用于研究跨模态的检索任务。
地址: http://cvit.iiit.ac.in/research/projects/cvit-projects/cartoonfaces
#### 2.2.2 商品识别
+ AliProduct: AliProduct数据集是目前开源最大的商品数据集它是一个SKU级别的图像分类数据集 包含5万类别、300万张商品图像商品图像的类别和总量均为业界之最。此数据集中涵盖了大量的生活用品、食物等数据集中没有人工标注数据较脏数据分布较不均衡且有很多相似的商品图片。
地址: https://retailvisionworkshop.github.io/recognition_challenge_2020/
+ Product-10k: Products-10k数据集中的所有图片均来自京东商城。数据集中共包含1万个经常购买的SKU。所有SKU组织成一个层次结构。总共有近19万张图片。在实际应用场景中图像量的分布是不均衡的。所有图像都由生产专家团队手工检查/标记。
地址https://www.kaggle.com/c/products-10k/data?select=train.csv
+ DeepFashion-Inshop: 同通用图像识别数据集中的In-shop Clothes
### 2.2.3 Logo识别
+ Logo-2K+ Logo-2K+是一个仅用于logo图像识别的数据集其包含10个大类2341个小类和167140张图片。
地址: https://github.com/msn199959/Logo-2k-plus-Dataset
+ Tsinghua-Tencent 100K 该数据集是从10万张腾讯街景全景图中创建的一个大型交通标志基准数据集。它提供包含30000个交通标志实例的100000张图像。这些图像涵盖了照度和天气条件的巨大变化。基准测试中的每个交通标志都标注了类别标签、边界框和像素掩码。 它总共包含222个类别 (0 background + 221 traffic signs)
地址: https://cg.cs.tsinghua.edu.cn/traffic-sign/
### 2.2.4 车辆识别
+ CompCars 图像主要来自网络和监控数据其中网络数据包含163个汽车制造商、1716个汽车型号的汽车。共136,726张全车图像27,618张部分车图像。其中网络汽车数据包含bounding box、视角、5个属性最大速度、排量、车门数、车座数、汽车类型。监控数据包含50,000张前视角图像。
地址: http://mmlab.ie.cuhk.edu.hk/datasets/comp_cars/
+ BoxCars 此数据集共包含21250辆车、63750张图像、27个汽车制造商、148个细类别此数据集全部来自监控数据。
地址: https://github.com/JakubSochor/BoxCars
+ PKU-VD Dataset该数据集包含了两个大型车辆数据集VD1和VD2它们分别从两个城市的真实世界不受限制的场景拍摄图像。其中VD1是从高分辨率交通摄像头获得的VD2中的图像则是从监视视频中获取的。作者对原始数据执行车辆检测以确保每个图像仅包含一辆车辆。由于隐私保护的限制所有车牌号码都已被黑色覆盖遮挡。所有车辆图像均从前视图进行拍摄。 数据集中为每个图像提供了多样化的属性注释包括身份编号精确的车辆模型和车辆颜色。VD1原先包含1097649张图像1232种车俩模型11种车辆颜色但删除图像里面有多辆车辆以及从车辆后方拍摄的图片该数据集仅剩846358张图像141756辆车辆。 VD2包含807260张图像79763辆车辆1112种车辆模型11种车辆颜色。
地址: https://pkuml.org/resources/pku-vds.html

View File

@ -1,43 +0,0 @@
# 使用VisualDL可视化训练过程
## 前言
VisualDL是飞桨可视化分析工具以丰富的图表呈现训练参数变化趋势、模型结构、数据样本、高维数据分布等。可帮助用户更清晰直观地理解深度学习模型训练过程及模型结构进而实现高效的模型优化。更多细节请查看[VisualDL](https://github.com/PaddlePaddle/VisualDL/)。
## 在PaddleClas中使用VisualDL
现在PaddleClas支持在训练阶段使用VisualDL查看训练过程中学习率learning rate、损失值loss以及准确率accuracy的变化情况。
### 设置config文件并启动训练
在PaddleClas中使用VisualDL只需在训练配置文件config文件中设置字段 `Global.use_visualdl``True`
```yaml
# config.yaml
Global:
...
use_visualdl: True
...
```
PaddleClas 会将 VisualDL 的日志保存在 `Global.output_dir` 字段指定目录下的 `vdl/` 子目录下,然后正常启动训练即可:
```shell
python3 tools/train.py -c config.yaml
```
### 启动VisualDL
在启动训练程序后可以在新的终端session中启动VisualDL服务
```shell
visualdl --logdir ./output/vdl/
```
上述命令中,参数`--logdir`用于指定保存 VisualDL 日志的目录VisualDL将遍历并且迭代寻找指定目录的子目录将所有实验结果进行可视化。也同样可以使用下述参数设定VisualDL服务的ip及端口号
* `--host`设定IP默认为127.0.0.1
* `--port`设定端口默认为8040
更多参数信息,请查看[VisualDL](https://github.com/PaddlePaddle/VisualDL/blob/develop/README_CN.md#2-%E5%90%AF%E5%8A%A8%E9%9D%A2%E6%9D%BF)。
在启动VisualDL后即可在浏览器中查看训练过程输入地址`127.0.0.1:8840`
<div align="center">
<img src="../../images/VisualDL/train_loss.png" width="400">
</div>

View File

@ -1,5 +0,0 @@
# 代码结构概览
* 正在持续更新中!!!

View File

@ -1,12 +0,0 @@
实用工具
================================
.. toctree::
:maxdepth: 1
paddle_inference.md
paddle_mobile_inference.md
paddle_quantization.md
multi_machine_training.md
paddle_hub.md
paddle_serving.md

View File

@ -1,6 +0,0 @@
# 多机训练
分布式训练的高性能,是飞桨的核心优势技术之一,在分类任务上,分布式训练可以达到几乎线性的加速比。
[Fleet](https://github.com/PaddlePaddle/Fleet) 是用于 PaddlePaddle 分布式训练的高层 API基于这套接口用户可以很容易切换到分布式训练程序。
为了可以同时支持单机训练和多机训练,[PaddleClas](https://github.com/PaddlePaddle/PaddleClas) 采用 Fleet API 接口,更多的分布式训练可以参考 [Fleet API设计文档](https://github.com/PaddlePaddle/Fleet/blob/develop/README.md)。

View File

@ -1,4 +0,0 @@
# Paddle Hub
[PaddleHub](https://github.com/PaddlePaddle/PaddleHub) 是飞桨生态的预训练模型应用工具,开发者可以便捷地使用高质量的预训练模型结合 Fine-tune API 快速完成模型迁移到部署的全流程工作。
PaddleHub 收录了 [PaddleClas](https://github.com/PaddlePaddle/PaddleClas) 的所有预训练模型,更多使用细节请查看 [PaddleHub官网](https://www.paddlepaddle.org.cn/hub)。

View File

@ -1,119 +0,0 @@
# Paddle-Lite
## 一、简介
[Paddle-Lite](https://github.com/PaddlePaddle/Paddle-Lite) 是飞桨推出的一套功能完善、易用性强且性能卓越的轻量化推理引擎。
轻量化体现在使用较少比特数用于表示神经网络的权重和激活,能够大大降低模型的体积,解决终端设备存储空间有限的问题,推理性能也整体优于其他框架。
[PaddleClas](https://github.com/PaddlePaddle/PaddleClas) 使用 Paddle-Lite 进行了[移动端模型的性能评估](../models/Mobile.md),本部分以`ImageNet1k`数据集的`MobileNetV1`模型为例,介绍怎样使用`Paddle-Lite`,在移动端(基于骁龙855的安卓开发平台)对进行模型速度评估。
## 二、评估步骤
### 2.1 导出inference模型
* 首先需要将训练过程中保存的模型存储为用于预测部署的固化模型,可以使用`tools/export_model.py`导出inference模型具体使用方法如下。
```shell
python tools/export_model.py -m MobileNetV1 -p pretrained/MobileNetV1_pretrained/ -o inference/MobileNetV1
```
最终在`inference/MobileNetV1`文件夹下会保存得到`model`与`parmas`文件。
### 2.2 benchmark二进制文件下载
* 使用adb(Android Debug Bridge)工具可以连接Android手机与PC端并进行开发调试等。安装好adb并确保PC端和手机连接成功后使用以下命令可以查看手机的ARM版本并基于此选择合适的预编译库。
```shell
adb shell getprop ro.product.cpu.abi
```
* 下载benchmark_bin文件
```shell
wget -c https://paddle-inference-dist.bj.bcebos.com/PaddleLite/benchmark_0/benchmark_bin_v8
```
如果查看的ARM版本为v7则需要下载v7版本的benchmark_bin文件下载命令如下。
```shell
wget -c https://paddle-inference-dist.bj.bcebos.com/PaddleLite/benchmark_0/benchmark_bin_v7
```
### 2.3 模型速度benchmark
PC端和手机连接成功后使用下面的命令开始模型评估。
```
sh deploy/lite/benchmark/benchmark.sh ./benchmark_bin_v8 ./inference result_armv8.txt true
```
其中`./benchmark_bin_v8`为benchmark二进制文件路径`./inference`为所有需要评测的模型的路径,`result_armv8.txt`为保存的结果文件,最后的参数`true`表示在评估之后会首先进行模型优化。最终在当前文件夹下会输出`result_armv8.txt`的评估结果文件,具体信息如下。
```
PaddleLite Benchmark
Threads=1 Warmup=10 Repeats=30
MobileNetV1 min = 30.89100 max = 30.73600 average = 30.79750
Threads=2 Warmup=10 Repeats=30
MobileNetV1 min = 18.26600 max = 18.14000 average = 18.21637
Threads=4 Warmup=10 Repeats=30
MobileNetV1 min = 10.03200 max = 9.94300 average = 9.97627
```
这里给出了不同线程数下的模型预测速度单位为FPS以线程数为1为例MobileNetV1在骁龙855上的平均速度为`30.79750FPS`。
### 2.4 模型优化与速度评估
* 在2.3节中提到了在模型评估之前对其进行优化,在这里也可以首先对模型进行优化,再直接加载优化后的模型进行速度评估。
* Paddle-Lite 提供了多种策略来自动优化原始的训练模型其中包括量化、子图融合、混合调度、Kernel优选等等方法。为了使优化过程更加方便易用Paddle-Lite提供了opt 工具来自动完成优化步骤,输出一个轻量的、最优的可执行模型。可以在[Paddle-Lite模型优化工具页面](https://paddle-lite.readthedocs.io/zh/latest/user_guides/model_optimize_tool.html)下载。在这里以`MacOS`开发环境为例,下载[opt_mac](https://paddlelite-data.bj.bcebos.com/model_optimize_tool/opt_mac)模型优化工具,并使用下面的命令对模型进行优化。
```shell
model_file="../MobileNetV1/model"
param_file="../MobileNetV1/params"
opt_models_dir="./opt_models"
mkdir ${opt_models_dir}
./opt_mac --model_file=${model_file} \
--param_file=${param_file} \
--valid_targets=arm \
--optimize_out_type=naive_buffer \
--prefer_int8_kernel=false \
--optimize_out=${opt_models_dir}/MobileNetV1
```
其中`model_file`与`param_file`分别是导出的inference模型结构文件与参数文件地址转换成功后会在`opt_models`文件夹下生成`MobileNetV1.nb`文件。
使用benchmark_bin文件加载优化后的模型进行评估具体的命令如下。
```shell
bash benchmark.sh ./benchmark_bin_v8 ./opt_models result_armv8.txt
```
最终`result_armv8.txt`中结果如下。
```
PaddleLite Benchmark
Threads=1 Warmup=10 Repeats=30
MobileNetV1_lite min = 30.89500 max = 30.78500 average = 30.84173
Threads=2 Warmup=10 Repeats=30
MobileNetV1_lite min = 18.25300 max = 18.11000 average = 18.18017
Threads=4 Warmup=10 Repeats=30
MobileNetV1_lite min = 10.00600 max = 9.90000 average = 9.96177
```
以线程数为1为例MobileNetV1在骁龙855上的平均速度为`30.84173FPS`。
更加具体的参数解释与Paddle-Lite使用方法可以参考 [Paddle-Lite 文档](https://paddle-lite.readthedocs.io/zh/latest/)。

View File

@ -1,5 +0,0 @@
# 模型量化
模型量化是 [PaddleSlim](https://github.com/PaddlePaddle/PaddleSlim) 的特色功能之一,支持动态和静态两种量化训练方式,对权重全局量化和 Channel-Wise 量化,同时以兼容 Paddle-Lite 的格式保存模型。
[PaddleClas](https://github.com/PaddlePaddle/PaddleClas) 使用该量化工具量化了78.9%的mobilenet_v3_large_x1_0的蒸馏模型, 量化后SD855上预测速度从19.308ms加速到14.395ms存储大小从21M减小到10M top1识别准确率75.9%。
具体的训练方法可以参见 [PaddleSlim 量化训练](../../../deploy/slim/quant/README.md)。

View File

@ -1,65 +0,0 @@
# 模型服务化部署
## 一、简介
[Paddle Serving](https://github.com/PaddlePaddle/Serving) 旨在帮助深度学习开发者轻易部署在线预测服务,支持一键部署工业级的服务能力、客户端和服务端之间高并发和高效通信、并支持多种编程语言开发客户端。
该部分以HTTP预测服务部署为例介绍怎样在PaddleClas中使用PaddleServing部署模型服务。
## 二、Serving安装
Serving官网推荐使用docker安装并部署Serving环境。首先需要拉取docker环境并创建基于Serving的docker。
```shell
nvidia-docker pull hub.baidubce.com/paddlepaddle/serving:0.2.0-gpu
nvidia-docker run -p 9292:9292 --name test -dit hub.baidubce.com/paddlepaddle/serving:0.2.0-gpu
nvidia-docker exec -it test bash
```
进入docker后需要安装Serving相关的python包。
```shell
pip install paddlepaddle-gpu
pip install paddle-serving-client
pip install paddle-serving-server-gpu
```
* 如果安装速度太慢,可以通过`-i https://pypi.tuna.tsinghua.edu.cn/simple`更换源,加速安装过程。
* 如果希望部署CPU服务可以安装serving-server的cpu版本安装命令如下。
```shell
pip install paddle-serving-server
```
### 三、导出模型
使用`tools/export_serving_model.py`脚本导出Serving模型以`ResNet50_vd`为例,使用方法如下。
```shell
python tools/export_serving_model.py -m ResNet50_vd -p ./pretrained/ResNet50_vd_pretrained/ -o serving
```
最终在serving文件夹下会生成`ppcls_client_conf`与`ppcls_model`两个文件夹分别存储了client配置、模型参数与结构文件。
### 四、服务部署与请求
* 使用下面的方式启动Serving服务。
```shell
python tools/serving/image_service_gpu.py serving/ppcls_model workdir 9292
```
其中`serving/ppcls_model`为刚才保存的Serving模型地址`workdir`为为工作目录,`9292`为服务的端口号。
* 使用下面的脚本向Serving服务发送识别请求并返回结果。
```
python tools/serving/image_http_client.py 9292 ./docs/images/logo.png
```
`9292`为发送请求的端口号,需要与服务启动时的端口号保持一致,`./docs/images/logo.png`为待识别的图像文件。最终返回Top1识别结果的类别ID以及概率值。
* 更多的服务部署类型,如`RPC预测服务`等可以参考Serving的github官网[https://github.com/PaddlePaddle/Serving/tree/develop/python/examples/imagenet](https://github.com/PaddlePaddle/Serving/tree/develop/python/examples/imagenet)

View File

@ -1,32 +0,0 @@
# 图像分类昆仑模型介绍(持续更新中)
## 前言
* 本文档介绍了目前昆仑支持的模型以及如何在昆仑设备上训练这些模型。支持昆仑的PaddlePaddle安装参考install_kunlun(https://github.com/PaddlePaddle/FluidDoc/blob/develop/doc/paddle/install/install_Kunlun_zh.md)
## 昆仑训练
* 数据来源和预训练模型参考[quick_start](../tutorials/quick_start_new_user.md)。昆仑训练效果与CPU/GPU对齐。
### ResNet50
* 命令:
```python3.7 tools/static/train.py -c configs/quick_start/ResNet50_vd_finetune_kunlun.yaml -o use_gpu=False -o use_xpu=True -o is_distributed=False```
与cpu/gpu训练的区别是加上-o use_xpu=True, 表示执行在昆仑设备上。
### MobileNetV3
* 命令:
```python3.7 tools/static/train.py -c configs/quick_start/MobileNetV3_large_x1_0_finetune.yaml -o use_gpu=False -o use_xpu=True -o is_distributed=False```
### HRNet
* 命令:
```python3.7 tools/static/train.py -c configs/quick_start/HRNet_W18_C_finetune.yaml -o is_distributed=False -o use_cpu=False -o use_xpu=True -o use_gpu=False```
### VGG16/19
* 命令:
```python3.7 tools/static/train.py -c configs/quick_start/VGG16_finetune_kunlun.yaml -o use_gpu=False -o use_cpu=False -o use_xpu=True -o is_distributed=False```
```python3.7 tools/static/train.py -c configs/quick_start/VGG19_finetune_kunlun.yaml -o use_gpu=False -o use_cpu=False -o use_xpu=True -o is_distributed=False```

View File

@ -1,61 +0,0 @@
# 使用DALI加速训练
## 前言
[NVIDIA数据加载库](https://docs.nvidia.com/deeplearning/dali/user-guide/docs/index.html)The NVIDIA Data Loading LibraryDALI是用于数据加载和预处理的开源库用于加速深度学习训练、推理过程它可以直接构建飞桨Paddle的DataLoader数据读取器。
由于深度学习程序在训练阶段依赖大量数据这些数据需要经过加载、预处理等操作后才能送入训练程序而这些操作通常在CPU完成因此限制了训练速度进一步提高特别是在batch_size较大时数据读取可能成为训练速度的瓶颈。DALI可以基于GPU的高并行特性实现数据加载及预处理操作可以进一步提高训练速度。
## 安装DALI
目前DALI仅支持Linux x64平台且CUDA版本大于等于10.2。
* 对于CUDA 10:
pip install --extra-index-url https://developer.download.nvidia.com/compute/redist nvidia-dali-cuda100
* 对于CUDA 11.0:
pip install --extra-index-url https://developer.download.nvidia.com/compute/redist nvidia-dali-cuda110
关于更多DALI安装的信息可以参考[DALI官方](https://docs.nvidia.com/deeplearning/dali/user-guide/docs/installation.html)。
## 使用DALI
PaddleClas支持在静态图训练方式中使用DALI加速由于DALI仅支持GPU训练因此需要设置GPU且DALI需要占用GPU显存需要为DALI预留显存。使用DALI训练只需在训练配置文件中设置字段`use_dali=True`,或通过以下命令启动训练即可:
```shell
# 设置用于训练的GPU卡号
export CUDA_VISIBLE_DEVICES="0"
# 设置用于神经网络训练的显存大小可根据具体情况设置一般可设置为0.8或0.7剩余显存则预留DALI使用
export FLAGS_fraction_of_gpu_memory_to_use=0.80
python tools/static/train.py -c configs/ResNet/ResNet50.yaml -o use_dali=True
```
也可以使用多卡训练:
```shell
# 设置用于训练的GPU卡号
export CUDA_VISIBLE_DEVICES="0,1,2,3,4,5,6,7"
# 设置用于神经网络训练的显存大小可根据具体情况设置一般可设置为0.8或0.7剩余显存则预留DALI使用
export FLAGS_fraction_of_gpu_memory_to_use=0.80
python -m paddle.distributed.launch \
--gpus="0,1,2,3,4,5,6,7" \
tools/static/train.py \
-c ./configs/ResNet/ResNet50.yaml \
-o use_dali=True
```
## 使用FP16训练
在上述基础上使用FP16半精度训练可以进一步提高速度可以参考下面的配置与运行命令。
```shell
export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
export FLAGS_fraction_of_gpu_memory_to_use=0.8
python -m paddle.distributed.launch \
--gpus="0,1,2,3,4,5,6,7" \
tools/static/train.py \
-c configs/ResNet/ResNet50_fp16.yaml
```

View File

@ -1,11 +0,0 @@
# 图像分类FAQ持续更新
## 前言
* 本文档收集了大家在使用PaddleClas或者学习图像分类时遇到的一些问题旨在为图像分类任务的开发者提供一些参考如果问题欢迎帮忙补充和修正不胜感激。
## 目录
* [【精选】图像分类30个问题及PaddleClas常见使用问题](./faq.md)
* [2020 FAQ第一季](./faq_series/faq_2020_s1.md)(最近更新2020.12.31)
* [2021 FAQ第一季](./faq_series/faq_2021_s1.md)(最近更新2021.02.03)

View File

@ -31,7 +31,7 @@
>>
* Q: 怎样根据自己的任务选择合适的模型进行训练?
* A: 如果希望在服务器部署或者希望精度尽可能地高对模型存储大小或者预测速度的要求不是很高那么推荐使用ResNet_vd、Res2Net_vd、DenseNet、Xception等适合于服务器端的系列模型如果希望在移动端侧部署则推荐使用MobileNetV3、GhostNet等适合于移动端的系列模型。同时我们推荐在选择模型的时候可以参考[模型库](https://github.com/PaddlePaddle/PaddleClas/tree/master/docs/zh_CN/models)中的速度-精度指标图。
* A: 如果希望在服务器部署或者希望精度尽可能地高对模型存储大小或者预测速度的要求不是很高那么推荐使用ResNet_vd、Res2Net_vd、DenseNet、Xception等适合于服务器端的系列模型如果希望在移动端侧部署则推荐使用MobileNetV3、GhostNet等适合于移动端的系列模型。同时我们推荐在选择模型的时候可以参考[模型库](../models)中的速度-精度指标图。
>>
* Q: 如何进行参数初始化,什么样的初始化可以加快模型收敛?
@ -67,7 +67,7 @@
>>
* Q: 当前主流的学习率下降策略有哪些?一般需要怎么选择呢?
* A: 学习率是通过损失函数的梯度调整网络权重的超参数的速度。学习率越低损失函数的变化速度就越慢。虽然使用低学习率可以确保不会错过任何局部极小值但也意味着将花费更长的时间来进行收敛特别是在被困在高原区域的情况下。在整个训练过程中我们不能使用同样的学习率来更新权重否则无法到达最优点所以需要在训练过程中调整学习率的大小。在训练初始阶段由于权重处于随机初始化的状态损失函数相对容易进行梯度下降所以可以设置一个较大的学习率。在训练后期由于权重参数已经接近最优值较大的学习率无法进一步寻找最优值所以需要设置一个较小的学习率。在训练整个过程中很多研究者使用的学习率下降方式是piecewise_decay即阶梯式下降学习率如在ResNet50标准的训练中我们设置的初始学习率是0.1每30epoch学习率下降到原来的1/10一共迭代120epoch。除了piecewise_decay很多研究者也提出了学习率的其他下降方式如polynomial_decay多项式下降、exponential_decay指数下降,cosine_decay余弦下降其中cosine_decay无需调整超参数鲁棒性也比较高所以成为现在提高模型精度首选的学习率下降方式。Cosine_decay和piecewise_decay的学习率变化曲线如下图所示容易观察到在整个训练过程中cosine_decay都保持着较大的学习率所以其收敛较为缓慢但是最终的收敛效果较peicewise_decay更好一些。
![](../images/models/lr_decay.jpeg)
![](../../images/models/lr_decay.jpeg)
>>
* Q: Warmup学习率策略是什么一般用在什么样的场景中
* A: Warmup策略顾名思义就是让学习率先预热一下在训练初期我们不直接使用最大的学习率而是用一个逐渐增大的学习率去训练网络当学习率增大到最高点时再使用学习率下降策略中提到的学习率下降方式衰减学习率的值。如果使用较大的batch_size训练神经网络时我们建议您使用warmup策略。实验表明在batch_size较大时warmup可以稳定提升模型的精度。在训练MobileNetV3等batch_size较大的实验中我们默认将warmup中的epoch设置为5即先用5epoch将学习率从0增加到最大值再去做相应的学习率衰减。
@ -125,7 +125,7 @@
>>
* Q: 数据量不足的情况下,目前有哪些常见的数据增广方法来增加训练样本的丰富度呢?
* A: PaddleClas中将目前比较常见的数据增广方法分为了三大类分别是图像变换类、图像裁剪类和图像混叠类图像变换类主要包括AutoAugment和RandAugment图像裁剪类主要包括CutOut、RandErasing、HideAndSeek和GridMask图像混叠类主要包括Mixup和Cutmix更详细的关于数据增广的介绍可以参考[数据增广章节](./advanced_tutorials/image_augmentation/ImageAugment.md)。
* A: PaddleClas中将目前比较常见的数据增广方法分为了三大类分别是图像变换类、图像裁剪类和图像混叠类图像变换类主要包括AutoAugment和RandAugment图像裁剪类主要包括CutOut、RandErasing、HideAndSeek和GridMask图像混叠类主要包括Mixup和Cutmix更详细的关于数据增广的介绍可以参考[数据增广章节](../algorithm_introduction/DataAugmentation.md)。
>>
* Q: 对于遮挡情况比较常见的图像分类场景,该使用什么数据增广方法去提升模型的精度呢?
* A: 在训练的过程中可以尝试对训练集使用CutOut、RandErasing、HideAndSeek和GridMask等裁剪类数据增广方法让模型也能够不止学习到显著区域也能关注到非显著性区域从而在遮挡的情况下也能较好地完成识别任务。

View File

@ -84,7 +84,7 @@ pip install paddle2onnx
```
其中:
* `InputSpec()` 函数用于描述模型输入的签名信息,包括输入数据的 `shape`、`type` 和 `name`(可省略);
* `paddle.onnx.export()` 函数需要指定模型组网对象 `net`,导出模型的保存路径 `save_path`,模型的输入数据描述 `input_spec`
* `paddle.onnx.export()` 函数需要指定模型组网对象 `net`,导出模型的保存路径 `save_path`,模型的输入数据描述 `input_spec`
需要注意,`paddlepaddle` 版本需大于 `2.0.0`。关于 `paddle.onnx.export()` 函数的更多参数说明请参考[paddle.onnx.export](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/onnx/export_cn.html#export)。
@ -337,6 +337,6 @@ pip install paddle2onnx
```
其中:
* `InputSpec()` 函数用于描述模型输入的签名信息,包括输入数据的 `shape`、`type` 和 `name`(可省略);
* `paddle.onnx.export()` 函数需要指定模型组网对象 `net`,导出模型的保存路径 `save_path`,模型的输入数据描述 `input_spec`
* `paddle.onnx.export()` 函数需要指定模型组网对象 `net`,导出模型的保存路径 `save_path`,模型的输入数据描述 `input_spec`
需要注意,`paddlepaddle` 版本需大于 `2.0.0`。关于 `paddle.onnx.export()` 函数的更多参数说明请参考[paddle.onnx.export](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/onnx/export_cn.html#export)。

View File

@ -1,84 +0,0 @@
# 特征图可视化指南
## 一、概述
特征图是输入图片在卷积网络中的特征表达,对特征图的研究可以有利于我们对于模型的理解与设计,所以基于动态图我们使用本工具来可视化特征图。
## 二、准备工作
首先需要选定研究的模型本文设定ResNet50作为研究模型将resnet.py从[模型库](../../../ppcls/arch/architecture/)拷贝到当前目录下,并下载预训练模型[预训练模型](../../zh_CN/models/models_intro), 复制resnet50的模型链接使用下列命令下载并解压预训练模型。
```bash
wget The Link for Pretrained Model
tar -xf Downloaded Pretrained Model
```
以resnet50为例
```bash
wget https://paddle-imagenet-models-name.bj.bcebos.com/ResNet50_pretrained.tar
tar -xf ResNet50_pretrained.tar
```
## 三、修改模型
找到我们所需要的特征图位置设置self.fm将其fetch出来本文以resnet50中的stem层之后的特征图为例。
在fm_vis.py中修改模型的名字。
在ResNet50的__init__函数中定义self.fm
```python
self.fm = None
```
在ResNet50的forward函数中指定特征图
```python
def forward(self, inputs):
y = self.conv(inputs)
self.fm = y
y = self.pool2d_max(y)
for bottleneck_block in self.bottleneck_block_list:
y = bottleneck_block(y)
y = self.avg_pool(y)
y = fluid.layers.reshape(y, shape=[-1, self.pool2d_avg_output])
y = self.out(y)
return y, self.fm
```
执行函数
```bash
python tools/feature_maps_visualization/fm_vis.py -i the image you want to test \
-c channel_num -p pretrained model \
--show whether to show \
--interpolation interpolation method\
--save_path where to save \
--use_gpu whether to use gpu
```
参数说明:
+ `-i`:待预测的图片文件路径,如 `./test.jpeg`
+ `-c`:特征图维度,如 `./resnet50_vd/model`
+ `-p`:权重文件路径,如 `./ResNet50_pretrained/`
+ `--interpolation`: 图像插值方式, 默认值 1
+ `--save_path`:保存路径,如:`./tools/`
+ `--use_gpu`:是否使用 GPU 预测默认值True
## 四、结果
* 输入图片:
![](../../../docs/images/feature_maps/feature_visualization_input.jpg)
* 运行下面的特征图可视化脚本
```
python tools/feature_maps_visualization/fm_vis.py \
-i ./docs/images/feature_maps/feature_visualization_input.jpg \
-c 5 \
-p pretrained/ResNet50_pretrained/ \
--show=True \
--interpolation=1 \
--save_path="./output.png" \
--use_gpu=False \
--load_static_weights=True
```
* 输出特征图保存为`output.png`,如下所示。
![](../../../docs/images/feature_maps/feature_visualization_output.jpg)

View File

@ -0,0 +1,120 @@
# 特征提取
## 1. 特征提取简介
特征提取是图像识别中的关键一环,它的作用是将输入的图片转化为固定维度的特征向量,用于后续的[向量检索](./vector_search.md)。好的特征需要具备相似度保持性,即在特征空间中,相似度高的图片对其特征相似度要比较高(距离比较近);相似度低的图片,其特征相似度要比较小(距离比较远)。依据应用场景的不同, 我们可以选用不同长度的实值特征(real-valued feature)或者是二值特征binary feature)。顾名思义实值特征的每个元素都是一个实数而二值特征每个元素为非0即1或者表示为-1和1二者的差异见下表所示。
![image](https://user-images.githubusercontent.com/17264083/139409293-772ffc53-2bee-4736-8fa2-32d99a916572.png)
[Deep Metric Learning](../algorithm_introduction/metric_learning.md)和 DeepHash分别用以研究如何通过深度学习的方法获得好的实值和二值特征表示。本文主要介绍如何使用PaddleClas构建一个特征学习网络 如何进行训练、评估和推理。
## 2. 网络结构
![](./framework.png)
为了图像识别任务的灵活定制我们将整个网络分为Backbone, Neck, Head以及Loss部分整体结构如上图所示下面分别介绍各自的功能:
- Backbone: 指定所使用的骨干网络。值得注意的是PaddleClas提供的基于ImageNet的预训练模型最后一层的输出为1000 我们需要依据所需的特征维度定制最后一层的输出。
- Neck: 用以特征增强及特征维度变换; 这儿的Neck可以是一个简单的Linear Layer用来做特征维度变换也可以是较复杂的FPN结构用以做特征增强。
- Head: 用来将feature转化为logits; 除了常用的Fc Layer外我们还提供了cosmargin, arcmargin, circlemargin模块
- Loss: 指定所所用的Loss函数 Loss是特征提取能力的关键 Deep Metric Learing和Deep Hash很多的研究工作都聚焦在loss设计上。 我们将Loss设计为组合loss的形式 可以方便得将Classification Loss和Similarity Preserving Loss组合在一起
## 3. 配置文件介绍
下面以商品识别模型为例,介绍配置文件的含义:
## 网络结构
```
Arch:
name: RecModel
infer_output_key: features
infer_add_softmax: False
Backbone:
name: PPLCNet_x2_5
pretrained: True
use_ssld: True
BackboneStopLayer:
name: flatten_0
Neck:
name: FC
embedding_size: 1280
class_num: 512
Head:
name: ArcMargin
embedding_size: 512
class_num: 185341
margin: 0.2
scale: 30
```
- **name**: 模型的名字有别于PaddleClas提供的标准分类模型定制化的识别模型统一命名为RecModel
- **infer_output_key**: 推理时需要用到的Tensor的key, 训练模型下网络会以字典的形式输出features和logits. 识别任务中推理时只需要用到features即可
- **infer_output_key** 推理时是否需要加softmax。为了和分类任务的统一分类任务推理时需要加softmax操作识别任务不需要
- **Backbone**: 骨干网络, 此处选用的是经过SSLD蒸馏之后的预训练模型
- **BackboneStopLayer**: 该处用以指示在何处截断网络关于TheseLayer的用法请参考文档xxx
- **Neck**: 用以进行特征维度转换此处输出512维的特征向量
- **Head**: 采用ArcMargin, 此处可以依据训练数据修改类别数class_num, 以及超参数margin和scale
## Loss构成
### 单Loss示例
```
Loss:
Train:
- CELoss:
weight: 1.0
Eval:
- CELoss:
weight: 1.0
```
可以看到此处选用的是CELoss 结合Head部分的ArcMargin, 因此使用的是[ArcFace](https://arxiv.org/abs/1801.07698)中的算法
### 组合Loss示例
```
Loss:
Train:
- CELoss:
weight: 1.0
- TripletLossV2:
weight: 1.0
margin: 0.5
Eval:
- CELoss:
weight: 1.0
```
可以看到此处选用的是CELoss和TripletLoss的一个组合两者的比例为11.
# 4.训练、评估、推理
下面以`ppcls/configs/Products/ResNet50_vd_SOP.yaml`为例,介绍模型的训练、评估、推理过程
## 4.1 数据准备
首先下载SOP数据集 数据链接: https://cvgl.stanford.edu/projects/lifted_struct/
## 4.2 训练
- 单机单卡训练
```
python tools/train.py -c ppcls/configs/ResNet50_vd_SOP.yaml
```
- 单机多卡训练
```
python -m paddle.distributed.launch
--gpus="0,1,2,3" tools/train.py
-c ppcls/configs/ResNet50_vd_SOP.yaml
```
训练完成之后,会在`output`目录下生成`best_model`
## 4.3 评估
- 单卡评估
```
python tools/eval.py -c ppcls/configs/ResNet50_vd_SOP.yaml -o Global.pretrained_model="output/ReModel/best_model"
```
- 多卡评估
```
python -m paddle.distributed.launch
--gpus="0,1,2,3" tools/eval.py
-c ppcls/configs/ResNet50_vd_SOP.yaml
-o Global.pretrained_model="output/ReModel/best_model"
```
## 4.4 推理
推理过程包括两个步骤: 1 导出推理模型; 2 获取特征向量
### 4.4.1 导出推理模型
```
python tools/export_model -c ppcls/configs/ResNet50_vd_SOP.yaml -o Global.pretrained_model="output/ReModel/best_model"
```
生成的推理模型位于`inference`目录,名字为`inference.pd*`
### 4.4.2 获取特征向量
```
cd deploy
python python/inference_rec.py -c configs/inference_product.yaml -o rec_inference_model_dir="../inference/inference"
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 KiB

View File

@ -0,0 +1,76 @@
# 向量检索
向量检索技术在图像识别、图像检索中应用比较广泛。其主要目标是,对于给定的查询向量,在已经建立好的向量库中,与库中所有的待查询向量,进行特征向量的相似度或距离计算,得到相似度排序。在图像识别系统中,我们使用[Faiss](https://github.com/facebookresearch/faiss)对此部分进行支持,具体信息请详查[Faiss官网](https://github.com/facebookresearch/faiss)。`Faiss`主要有以下优势
- 适配性好支持Windos、Linux、MacOS系统
- 安装方便: 支持`python`接口,直接使用`pip`安装
- 算法丰富:支持多种检索算法,满足不同场景的需求
- 同时支持CPU、GPU能够加速检索过程
值得注意的是,为了更好是适配性,目前版本,`PaddleClas`中暂时**只使用CPU进行向量检索**。
本文档主要主要介绍PaddleClas中检索模块的安装、使用的检索算法及使用过程中的相关配置文件中参数介绍。
## 一、检索库安装
`Faiss`具体安装方法如下:
```python
pip install faiss-cpu==1.7.1post2
```
若使用时,不能正常引用,则`uninstall` 之后,重新`install`,尤其是`windows`下。
## 二、使用的检索算法
目前`PaddleClas`中检索模块,支持如下三种检索算法
- **HNSW32**: 一种图索引方法。检索精度较高,速度较快。但是特征库只支持添加图像功能,不支持删除图像特征功能。(默认方法)
- **IVF**:倒排索引检索方法。速度较快,但是精度略低。特征库支持增加、删除图像特征功能。
- **FLAT** 暴力检索算法。精度最高,但是数据量大时,检索速度较慢。特征库支持增加、删除图像特征功能。
每种检索算法,满足不同场景。其中`HNSW32`为默认方法,此方法的检索精度、检索速度可以取得一个较好的平衡,具体算法介绍可以查看[官方文档](https://github.com/facebookresearch/faiss/wiki)。
## 三、相关配置文档参数介绍
涉及检索模块配置文件位于:`deploy/configs/`下,其中`build_*.yaml`是建立特征库的相关配置文件,`inference_*.yaml`是检索或者分类的推理配置文件。
### 3.1 建库配置文件参数
示例建库的配置如下
```yaml
# indexing engine config
IndexProcess:
index_method: "HNSW32" # supported: HNSW32, IVF, Flat
index_dir: "./recognition_demo_data_v1.1/gallery_product/index"
image_root: "./recognition_demo_data_v1.1/gallery_product/"
data_file: "./recognition_demo_data_v1.1/gallery_product/data_file.txt"
index_operation: "new" # suported: "append", "remove", "new"
delimiter: "\t"
dist_type: "IP"
embedding_size: 512
```
- **index_method**使用的检索算法。目前支持三种HNSW32、IVF、Flat
- **index_dir**:构建的特征库所存放的文件夹
- **image_root**:构建特征库所需要的标注图像所存储的文件夹位置
- **data_file**构建特征库所需要的标注图像的数据列表每一行的格式relative_path label
- **index_operation** 此次运行建库的操作:`new`新建,`append`将data_file的图像特征添加到特征库中`remove`将data_file的图像从特征库中删除
- **delimiter****data_file**中每一行的间隔符
- **dist_type**: 特征匹配过程中使用的相似度计算方式。`IP`内积相似度计算方式,`L2`欧式距离计算方法
- **embedding_size**:特征维度
### 3.2 检索配置文件参数
```yaml
IndexProcess:
index_dir: "./recognition_demo_data_v1.1/gallery_logo/index/"
return_k: 5
score_thres: 0.5
```
与建库配置文件不同,新参数主要如下:
- `return_k`: 检索结果返回`k`个结果
- `score_thres`: 检索匹配的阈值

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 899 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 973 KiB

Some files were not shown because too many files have changed in this diff Show More