未验证 提交 987ea608 编写于 作者: W whs 提交者: GitHub

[Document] Add doc for Light-NAS and auto filter pruning (#2421)

* Add doc for Light-NAS and auto filter pruning

* Add demo doc for Light-NAS and auto filter pruning.

* Fix usage.

* Add tutorial

* Refine the doc.
上级 ee078f8f
......@@ -23,7 +23,7 @@
---
# PaddleSlim模型压缩工具库
PaddleSlim是PaddlePaddle框架的一个子模块。PaddleSlim首次在PaddlePaddle 1.4版本中发布。在PaddleSlim中,实现了目前主流的网络剪枝、量化、蒸馏三种压缩策略,主要用于压缩图像领域模型。在后续版本中,会添加更多的压缩策略,以及完善对NLP领域模型的支持。
PaddleSlim是PaddlePaddle框架的一个子模块,主要用于压缩图像领域模型。在PaddleSlim中,不仅实现了目前主流的网络剪枝、量化、蒸馏三种压缩策略,还实现了超参数搜索和小模型网络结构搜索功能。在后续版本中,会添加更多的压缩策略,以及完善对NLP领域模型的支持。
## 目录
- [特色](#特色)
......@@ -45,7 +45,7 @@ Paddle-Slim工具库有以下特点:
### 效果好
- 对于冗余信息较少的MobileNetV1模型,卷积核剪切策略依然可缩减模型大小,并保持尽量少的精度损失。
- 对于冗余信息较少的MobileNetV1模型,模型通道剪裁策略依然可缩减模型大小,并保持尽量少的精度损失。
- 蒸馏压缩策略可明显提升原始模型的精度。
- 量化训练与蒸馏的组合使用,可同时做到缩减模型大小和提升模型精度。
......@@ -53,8 +53,8 @@ Paddle-Slim工具库有以下特点:
### 功能更强更灵活
- 剪切压缩过程自动化
- 剪切压缩策略支持更多网络结构
- 模型剪裁压缩过程自动化
- 模型剪裁压缩策略支持更多网络结构
- 蒸馏支持多种方式,用户可自定义组合loss
- 支持快速配置多种压缩策略组合使用
......@@ -63,10 +63,10 @@ Paddle-Slim工具库有以下特点:
## 架构介绍
这里简要介绍模型压缩工具实现的整体原理,便于理解使用流程。
**图 1**为模型压缩工具的架构图,从上到下为API依赖关系。蒸馏模块、量化模块和剪模块都间接依赖底层的paddle框架。目前,模型压缩工具作为了PaddlePaddle框架的一部分,所以已经安装普通版本paddle的用户需要重新下载安装支持模型压缩功能的paddle,才能使用压缩功能。
**图 1**为模型压缩工具的架构图,从上到下为API依赖关系。蒸馏模块、量化模块和剪模块都间接依赖底层的paddle框架。目前,模型压缩工具作为了PaddlePaddle框架的一部分,所以已经安装普通版本paddle的用户需要重新下载安装支持模型压缩功能的paddle,才能使用压缩功能。
<p align="center">
<img src="docs/images/framework_0.png" height=452 width=706 hspace='10'/> <br />
<img src="docs/images/framework_0.png" height=452 width=900 hspace='10'/> <br />
<strong>图 1</strong>
</p>
......@@ -82,11 +82,11 @@ Paddle-Slim工具库有以下特点:
## 功能列表
### 剪切
### 模型剪裁
- 支持敏感度和uniform两种方式
- 支持通道均匀模型剪裁(uniform pruning)、基于敏感度的模型剪裁、基于进化算法的自动模型剪裁三种方式
- 支持VGG、ResNet、MobileNet等各种类型的网络
- 支持用户自定义剪范围
- 支持用户自定义剪范围
### 量化训练
......@@ -103,11 +103,15 @@ Paddle-Slim工具库有以下特点:
- 支持L2 loss
- 支持softmax with cross-entropy loss
### 轻量神经网络结构自动搜索(Light-NAS)
- 支持基于进化算法的轻量神经网络结构自动搜索(Light-NAS)
### 其它功能
- 支持配置文件管理压缩任务超参数
- 支持多种压缩策略组合使用
- 蒸馏和剪切压缩过程支持checkpoints功能
- 蒸馏和模型剪裁压缩过程支持checkpoints功能
## 简要实验结果
......@@ -131,14 +135,14 @@ Paddle-Slim工具库有以下特点:
注:abs_max为动态量化,moving_average_abs_max为静态量化, channel_wise_abs_max是对卷积权重进行分channel量化。
### 卷积核剪切
### 模型通道剪裁
数据:ImageNet 1000类
模型:MobileNetV1
原始模型大小:17M
原始精度(top5/top1): 89.54% / 70.91%
#### Uniform剪切
#### 模型通道均匀剪裁
| FLOPS |model size| 精度损失(top5/top1)|精度(top5/top1) |
|---|---|---|---|
......@@ -146,7 +150,7 @@ Paddle-Slim工具库有以下特点:
| -60%|-55.9%(7.5M)|-1.34% / -2.67%|88.22% / 68.24%|
| -70%|-65.3%(5.9M)|-2.55% / -4.34%|86.99% / 66.57%|
#### 基于敏感度迭代剪
#### 基于敏感度迭代剪
| FLOPS |精度(top5/top1)|
|---|---|
......@@ -175,12 +179,22 @@ Paddle-Slim工具库有以下特点:
| Baseline|89.54% / 70.91%|17.0M|
| ResNet50蒸馏|90.92% / 71.97%|17.0M|
| ResNet50蒸馏训练 + 量化|90.94% / 72.01%|4.8M|
| 剪切-50% FLOPS|89.13% / 69.83%|9.0M|
| 剪切-50% FLOPS + 量化|89.11% / 69.20%|2.3M|
| 剪裁-50% FLOPS|89.13% / 69.83%|9.0M|
| 剪裁-50% FLOPS + 量化|89.11% / 69.20%|2.3M|
### 模型结构搜索实验
数据:ImageNet 1000类
| |Light-NAS-model0 |Light-NAS-model1 |MobileNetV2 |
|---|---|---|---|
|FLOPS|-3%|-17%|-0%|
|top1/top5 accuracy|72.45%/90.70%|71.84%/90.45%|71.90%/90.55% |
|GPU cost|1.2K GPU hours|1.2K GPU hours|-|
## 模型导出格式
压缩框架支持导出以下格式的模型
模型压缩框架支持以下格式模型导出
- **Paddle Fluid模型格式:** Paddle Fluid模型格式,可通过Paddle框架加载使用。
- **Paddle Mobile模型格式:** 仅在量化训练策略时使用,兼容[Paddle Mobile](https://github.com/PaddlePaddle/paddle-mobile)的模型格式。
......@@ -25,18 +25,20 @@
- [压缩脚本准备](#2-压缩脚本介绍)
- [蒸馏示例](#31-蒸馏)
- [剪切示例](#32-uniform剪切)
- [量化示例](#34-int8量化训练)
- [蒸馏后量化示例](#35-蒸馏后int8量化)
- [剪切后量化示例](#36-剪切后int8量化)
- [量化示例](#35-int8量化训练)
- [蒸馏后量化示例](#36-蒸馏后int8量化)
- [剪切后量化示例](#37-剪切后int8量化)
- [小模型结构搜索示例](#38-小模型结构搜索示例)
## 0. 概述
该示例参考[PaddlePaddle/models/fluid/PaddleCV/image_classification](https://github.com/PaddlePaddle/models/tree/develop/fluid/PaddleCV/image_classification)下代码,分别实现了以下策略:
1. <a href="#31-蒸馏">蒸馏</a>:用ResNet50对MobileNetV1的在ImageNet 1000数据上的蒸馏训练。
2. <a href="#32-uniform剪切">剪切</a>:对预训练好的MobileNetV1进行剪切
3. <a href="#34-int8量化训练">量化</a>:对预训练好的MobileNetV1进行int8量化训练
4. <a href="#35-蒸馏后int8量化">蒸馏量化组合</a>:先用ResNet50对MobileNetV1进行蒸馏,再对蒸馏后得到的模型进行int8量化训练。
5. <a href="#36-剪切后int8量化">剪切量化组合</a>:先用Uniform剪切策略对MobileNetV1进行剪切,再对剪切后的模型进行int8量化训练
3. <a href="#35-int8量化训练">量化</a>:对预训练好的MobileNetV1进行int8量化训练
4. <a href="#36-蒸馏后int8量化">蒸馏量化组合</a>:先用ResNet50对MobileNetV1进行蒸馏,再对蒸馏后得到的模型进行int8量化训练。
5. <a href="#37-剪切后int8量化">剪切量化组合</a>:先用Uniform剪切策略对MobileNetV1进行剪切,再对剪切后的模型进行int8量化训练
5. <a href="#38-小模型结构搜索示例">小模型结构搜索示例</a>: 先用模拟退火策略搜索出一组tokens, 再用该tokens构建网络进行训练。
本示例完整代码链接:https://github.com/PaddlePaddle/models/tree/develop/PaddleSlim
......@@ -212,7 +214,64 @@ python compress.py \
<strong>图3</strong>
</p>
### 3.4 int8量化训练
### 3.4 剪切率超参搜索
在该示例中,使用模拟退火策略搜索出一组最优的剪切率,将MobileNetV1模型剪掉50%的FLOPS.
修改run.sh, 执行以下命令,搜索一组剪切率:
```
# for auto filter pruning
#---------------------------
export CUDA_VISIBLE_DEVICES=0
python compress.py \
--model "MobileNet" \
--pretrained_model ./pretrain/MobileNetV1_pretrained \
--compress_config ./configs/auto_prune.yaml
```
通过上述步骤,得到一组最优的tokens, 将其按以下方式设置到`auto_prune.yaml`文件中:
```
strategies:
auto_pruning_strategy:
class: 'AutoPruneStrategy'
pruner: 'pruner_1'
controller: 'sa_controller'
start_epoch: 0
end_epoch: 200
retrain_epoch: 200
max_ratio: 0.50
min_ratio: 0.48
uniform_range: 0.4
init_tokens: [39, 38, 38, 24, 21, 34, 24, 29, 19, 11, 33, 36, 39]
pruned_params: '.*_sep_weights'
metric_name: 'acc_top1'
compressor:
epoch: 200
checkpoint_path: './checkpoints_auto_pruning/'
strategies:
- auto_pruning_strategy
```
其中,需要修改的选项有:
- end_epoch: 将其修改为200,训练任务共执行200个epochs
- retrain_epoch: 将其修改为200,当前任务的200个epochs全为训练,不做搜索。
- init_tokens: 在auto_pruning_strategy下新增init_tokens, 为上一步骤中搜索出的最优tokens.
- compressor::epoch: 修改为200,整个压缩任务执行200个epochs后退出。
该示例在评估数据集上的准确率结果如下:
| FLOPS |模型大小| 精度(top5/top1) |pruned ratios|
|---|---|---|---|
| -50%|- |88.86% / 69.64%|[0.39, 0.38, 0.38, 0.24, 0.21, 0.34, 0.24, 0.29, 0.19, 0.11, 0.33, 0.36, 0.39]|
>该搜索策略有一定的随机性,用上述搜索参数,不一定能搜索完全一样的结果。
### 3.5 int8量化训练
修改run.sh, 执行以下命令,执行int8量化训练示例:
......@@ -234,7 +293,7 @@ python compress.py \
|MobileNetV1|-71.76%(4.8M)|89.64% / 71.01%|
### 3.5 蒸馏后int8量化
### 3.6 蒸馏后int8量化
本示例先用ResNet50模型对MobileNetV1蒸馏训练120个epochs,然后再对MobileNetV1模型进行动态int8量化训练。
修改run.sh, 执行以下命令,执行蒸馏与int8量化训练结合的模型压缩示例:
......@@ -256,7 +315,7 @@ python compress.py \
| --- | --- | --- |
| MobileNet v1 | -71.76%(4.8M)| 72.01% |
### 3.6 剪切后int8量化
### 3.7 剪切后int8量化
本示例先将预训练好的MobileNetV1模型剪掉50% FLOPS, 让后再对其进行动态int8量化训练。
修改run.sh, 执行以下命令,执行剪切与int8量化训练结合的模型压缩示例:
......@@ -276,3 +335,36 @@ python compress.py \
| 模型(剪切FLOPS+动态int8量化) | 模型大小 | 精度(top1) |
| --- | --- | --- |
| MobileNet v1(剪切FLOPS -50%) | -86.47%(2.3M) | 69.20% |
### 3.7 小模型结构搜索示例
本示例先用模拟退火策略搜索出一组tokens, 再用搜索出的tokens初始化构建模型进行训练。
step1: 进入路径`PaddlePaddle/models/PaddleSlim/light_nas/`
step2: 在当前路径下,新建软链接指向上级目录的data: `ln -s ../data data`
step3: 修改`compress.xml`文件, 将参数server_ip设置为当前机器的ip。
step4: 执行`sh run.sh`, 可根据实际情况修改`run.sh`中的`CUDA_VISIBLE_DEVICES`
step5: 修改`light_nas_space.py`文件中的`LightNASSpace::init_tokens`, 使其返回step4中搜到的最优tokens。
step6: 修改compress.xml文件,将compressor下的`strategies`去掉。
step7: 执行`sh run.sh`进行训练任务。
该示例两组结果如下:
| - | Light-NAS-model0| Light-NAS-model1 | MobileNetV2 |
|---|---|---|---|
| FLOPS|-3% | -17% | -0% |
| top1 accuracy| 72.45%| 71.84%| 71.90% |
|GPU cost|1.2K GPU hours(V100)|1.2K GPU hours(V100)|-|
|tokens|tokens1|tokens2||
| token name | tokens|
|---|---|
|tokens1|[3, 1, 1, 0, 1, 0, 3, 2, 1, 0, 1, 0, 3, 1, 1, 0, 1, 0, 2, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0]|
|tokens2|[3, 1, 1, 0, 1, 0, 3, 2, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 2, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1]|
PaddleSlim/docs/images/framework_0.png

182.2 KB | W: | H:

PaddleSlim/docs/images/framework_0.png

174.5 KB | W: | H:

PaddleSlim/docs/images/framework_0.png
PaddleSlim/docs/images/framework_0.png
PaddleSlim/docs/images/framework_0.png
PaddleSlim/docs/images/framework_0.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -20,8 +20,9 @@
## 目录
- [量化原理介绍](#1-quantization-aware-training量化介绍)
- [切原理介绍](#2-卷积核剪切原理)
- [裁原理介绍](#2-卷积核剪裁原理)
- [蒸馏原理介绍](#3-蒸馏)
- [轻量级模型结构搜索原理介绍](#4-轻量级模型结构搜索)
## 1. Quantization Aware Training量化介绍
......@@ -119,16 +120,16 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$
## 2. 卷积核剪原理
## 2. 卷积核剪原理
该策略参考paper: [Pruning Filters for Efficient ConvNets](https://arxiv.org/pdf/1608.08710.pdf)
该策略通过减少卷积层中卷积核的数量,来减小模型大小和降低模型计算复杂度。
### 2.1 剪卷积核
### 2.1 剪卷积核
**剪注意事项1**
一个conv layer的filter,需要修改后续conv layer的filter. 如**图4**所示,剪掉Xi的一个filter,会导致$X_{i+1}$少一个channel, $X_{i+1}$对应的filter在input_channel纬度上也要减1.
**剪注意事项1**
一个conv layer的filter,需要修改后续conv layer的filter. 如**图4**所示,剪掉Xi的一个filter,会导致$X_{i+1}$少一个channel, $X_{i+1}$对应的filter在input_channel纬度上也要减1.
<p align="center">
......@@ -137,9 +138,9 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$
</p>
**剪注意事项2**
**剪注意事项2**
**图5**所示,剪完$X_i$之后,根据注意事项1我们从$X_{i+1}$的filter中删除了一行(图中蓝色行),在计算$X_{i+1}$的filters的l1_norm(图中绿色一列)的时候,有两种选择:
**图5**所示,剪完$X_i$之后,根据注意事项1我们从$X_{i+1}$的filter中删除了一行(图中蓝色行),在计算$X_{i+1}$的filters的l1_norm(图中绿色一列)的时候,有两种选择:
算上被删除的一行:independent pruning
减去被删除的一行:greedy pruning
......@@ -148,9 +149,9 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$
<strong>图5</strong>
</p>
**剪注意事项3**
在对ResNet等复杂网络剪的时候,还要考虑到后当前卷积层的修改对上一层卷积层的影响。
**图6**所示,在对residual block剪切时,$X_{i+1}$层如何剪切取决于project shortcut的剪切结果,因为我们要保证project shortcut的output和$X_{i+1}$的output能被正确的concat.
**剪注意事项3**
在对ResNet等复杂网络剪的时候,还要考虑到后当前卷积层的修改对上一层卷积层的影响。
**图6**所示,在对residual block剪裁时,$X_{i+1}$层如何剪裁取决于project shortcut的剪裁结果,因为我们要保证project shortcut的output和$X_{i+1}$的output能被正确的concat.
<p align="center">
......@@ -158,25 +159,25 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$
<strong>图6</strong>
</p>
### 2.2 Uniform剪卷积网络
### 2.2 Uniform剪卷积网络
每层剪一样比例的卷积核。
在剪一个卷积核之前,按l1_norm对filter从高到低排序,越靠后的filter越不重要,优先剪掉靠后的filter.
每层剪一样比例的卷积核。
在剪一个卷积核之前,按l1_norm对filter从高到低排序,越靠后的filter越不重要,优先剪掉靠后的filter.
### 2.3 基于敏感度剪卷积网络
### 2.3 基于敏感度剪卷积网络
根据每个卷积层敏感度的不同,剪掉不同比例的卷积核。
#### 两个假设
- 在一个conv layer的parameter内部,按l1_norm对filter从高到低排序,越靠后的filter越不重要。
- 两个layer剪相同的比例的filters,我们称对模型精度影响更大的layer的敏感度相对高。
- 两个layer剪相同的比例的filters,我们称对模型精度影响更大的layer的敏感度相对高。
#### 剪filter的指导原则
#### 剪filter的指导原则
- layer的剪比例与其敏感度成反比
- 优先剪layer内l1_norm相对低的filter
- layer的剪比例与其敏感度成反比
- 优先剪layer内l1_norm相对低的filter
#### 敏感度的理解
......@@ -185,21 +186,21 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$
<strong>图7</strong>
</p>
**图7**所示,横坐标是将filter剪掉的比例,竖坐标是精度的损失,每条彩色虚线表示的是网络中的一个卷积层。
以不同的剪切比例**单独**剪切一个卷积层,并观察其在验证数据集上的精度损失,并绘出**图7**中的虚线。虚线上升较慢的,对应的卷积层相对不敏感,我们优先剪不敏感的卷积层的filter.
**图7**所示,横坐标是将filter剪掉的比例,竖坐标是精度的损失,每条彩色虚线表示的是网络中的一个卷积层。
以不同的剪裁比例**单独**剪裁一个卷积层,并观察其在验证数据集上的精度损失,并绘出**图7**中的虚线。虚线上升较慢的,对应的卷积层相对不敏感,我们优先剪不敏感的卷积层的filter.
#### 选择最优的剪率组合
#### 选择最优的剪率组合
我们将**图7**中的折线拟合为**图8**中的曲线,每在竖坐标轴上选取一个精度损失值,就在横坐标轴上对应着一组剪率,如**图8**中黑色实线所示。
用户给定一个模型整体的剪切率,我们通过移动**图5**中的黑色实线来找到一组满足条件的且合法的剪切率。
我们将**图7**中的折线拟合为**图8**中的曲线,每在竖坐标轴上选取一个精度损失值,就在横坐标轴上对应着一组剪率,如**图8**中黑色实线所示。
用户给定一个模型整体的剪裁率,我们通过移动**图5**中的黑色实线来找到一组满足条件的且合法的剪裁率。
<p align="center">
<img src="images/tutorial/pruning_4.png" height=200 width=400 hspace='10'/> <br />
<strong>图8</strong>
</p>
#### 迭代剪
考虑到多个卷积层间的相关性,一个卷积层的修改可能会影响其它卷积层的敏感度,我们采取了多次剪的策略,步骤如下:
#### 迭代剪
考虑到多个卷积层间的相关性,一个卷积层的修改可能会影响其它卷积层的敏感度,我们采取了多次剪的策略,步骤如下:
- step1: 统计各卷积层的敏感度信息
- step2: 根据当前统计的敏感度信息,对每个卷积层剪掉少量filter, 并统计FLOPS,如果FLOPS已满足要求,进入step4,否则进行step3。
......@@ -222,9 +223,53 @@ Fast Optimization, Network Minimization and Transfer Learning](http://openaccess
由于小模型和大模型之间通过L2 loss进行监督,必须保证两个FSP矩阵的维度必须相同,而FSP矩阵的维度为M*N,其中M、N分别为输入和输出特征的channel数,因此大模型和小模型的FSP矩阵需要一一对应。
## 4. 轻量级模型结构搜索
深度学习模型在很多任务上都取得了不错的效果,网络结构的好坏对最终模型的效果有非常重要的影响。手工设计网络需要非常丰富的经验和众多尝试,并且众多的超参数和网络结构参数会产生爆炸性的组合,常规的random search几乎不可行,因此最近几年自动模型搜索技术(Neural Architecture Search)成为研究热点。区别于传统NAS,我们专注在搜索精度高并且速度快的模型结构,我们将该功能统称为Light-NAS.
## 4. 参考文献
### 4.1 搜索策略
搜索策略定义了使用怎样的算法可以快速、准确找到最优的网络结构参数配置。常见的搜索方法包括:强化学习、贝叶斯优化、进化算法、基于梯度的算法。我们当前的实现以模拟退火算法为主。
#### 4.1.1 模拟退火
模拟退火算法来源于固体退火原理,将固体加温至充分高,再让其徐徐冷却,加温时,固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温度都达到平衡态,最后在常温时达到基态,内能减为最小。
鉴于物理中固体物质的退火过程与一般组合优化问题之间的相似性,我们将其用于网络结构的搜索。
使用模拟退火算法搜索模型的过程如下:
$$
T_k = T_0*\theta^k
$$
\begin{equation}
P(r_k) =
\begin{cases}
e^{\frac{(r_k-r)}{T_k}} & r_k < r\\
1 & r_k>=r
\end{cases}
\end{equation}
在第k次迭代,搜到的网络为$N_k$, 对$N_k$训练若干epoch后,在测试集上得到reward为$r_k$, 以概率$P(r_k)$接受$r_k$,即执行$r=r_k$。$r$在搜索过程起始时被初始化为0. $T_0$为初始化温度,$\theta$为温度衰减系数,$T_k$为第k次迭代的温度。
在我们的NAS任务中,区别于RL每次重新生成一个完整的网络,我们将网络结构映射成一段编码,第一次随机初始化,然后每次随机修改编码中的一部分(对应于网络结构的一部分)生成一个新的编码,然后将这个编码再映射回网络结构,通过在训练集上训练一定的epochs后的精度以及网络延时融合获得reward,来指导退火算法的收敛。
### 4.2 搜索空间
搜索空间定义了优化问题的变量,变量规模决定了搜索算法的难度和搜索时间。因此为了加快搜索速度,定义一个合理的搜索空间至关重要。在Light-NAS中,为了加速搜索速度,我们将一个网络划分为多个block,先手动按链状层级结构堆叠c,再 使用搜索算法自动搜索每个block内部的结构。
因为要搜索出在移动端运行速度快的模型,我们参考了MobileNetV2中的Linear Bottlenecks和Inverted residuals结构,搜索每一个Inverted residuals中的具体参数,包括kernelsize、channel扩张倍数、重复次数、channels number。如图10所示:
<p align="center">
<img src="images/tutorial/light-nas-block.png" height=300 width=600 hspace='10'/> <br />
<strong>图10</strong>
</p>
## 5. 参考文献
1. [High-Performance Hardware for Machine Learning](https://media.nips.cc/Conferences/2015/tutorialslides/Dally-NIPS-Tutorial-2015.pdf)
......
......@@ -18,7 +18,7 @@
---
# Paddle模型压缩工具库使用说明
本文第一章介绍PaddleSlim模块通用功能的使用,不涉及具体压缩策略的细节。第二、三、四章分别介绍量化训练、剪切、蒸馏三种压缩策略的使用方式。
本文第一章介绍PaddleSlim模块通用功能的使用,不涉及具体压缩策略的细节。第二章分别用4小节介绍量化训练、剪裁、蒸馏和轻量级模型结构搜索四种压缩策略的使用方式。
建议在看具体策略使用方式之前,先浏览下对应的原理介绍:<a href="tutorial.md">算法原理介绍</a>
>在本文中不区分operator和layer的概念。不区分loss和cost的概念。
......@@ -27,8 +27,9 @@
- [通用功能使用说明](#1-paddleslim通用功能使用介绍)
- [量化使用说明](#21-量化训练)
- [切使用说明](#22-卷积核剪切)
- [裁使用说明](#22-模型通道剪裁)
- [蒸馏使用说明](#23-蒸馏)
- [轻量级模型结构搜索使用说明](#24-轻量级模型结构搜索)
## 1. PaddleSlim通用功能使用介绍
......@@ -85,7 +86,7 @@
#### 1.1.2.4. load pretrain model
-:需要加载pretrain model
-:需要加载pretrain model
- 蒸馏:根据需要选择是否加载pretrain model
- 量化训练:需要加载pretrain model
......@@ -171,8 +172,8 @@ pruners:
'*': 'l1_norm'
```
第二步:注册剪策略
如下所示,我们注册两个uniform剪策略,分别在第0个epoch和第10个epoch将模型的FLOPS剪掉10%.
第二步:注册剪策略
如下所示,我们注册两个uniform剪策略,分别在第0个epoch和第10个epoch将模型的FLOPS剪掉10%.
```python
strategies:
pruning_strategy_0:
......@@ -207,10 +208,10 @@ compress_pass:
## 2. 模型压缩策略使用介绍
本章依次介绍量化训练、卷积核剪切和蒸馏三种策略的使用方式,在此之前建议先浏览相应策略的原理介绍:
本章依次介绍量化训练、模型通道剪裁和蒸馏三种策略的使用方式,在此之前建议先浏览相应策略的原理介绍:
- [量化训练原理](tutorial.md#1-quantization-aware-training量化介绍)
- [卷积核剪切原理](tutorial.md#2-卷积核剪切原理)
- [模型通道剪裁原理](tutorial.md#2-模型通道剪裁原理)
- [蒸馏原理](tutorial.md#3-蒸馏)
### 2.1 量化训练
......@@ -288,14 +289,14 @@ strategies:
量化训练High-Level API是对Low-Level API的高层次封装,这使得用户仅需编写少量的代码和配置文件即可进行量化训练。然而,封装必然会带来使用灵活性的降低。因此,若用户在进行量化训练时需要更多的灵活性,可参考 [量化训练Low-Level API使用示例](../quant_low_level_api/README.md)
### 2.2 卷积核剪切
该策略通过减少指定卷积层中卷积核的数量,达到缩减模型大小和计算复杂度的目的。根据选取剪比例的策略的不同,又细分为以下两个方式:
### 2.2 模型通道剪裁
该策略通过减少指定卷积层中卷积核的数量,达到缩减模型大小和计算复杂度的目的。根据选取剪比例的策略的不同,又细分为以下两个方式:
- uniform pruning: 每层剪掉相同比例的卷积核数量。
- sensitive pruning: 根据每层敏感度,剪掉不同比例的卷积核数量。
- uniform pruning: 每层剪掉相同比例的卷积核数量。
- sensitive pruning: 根据每层敏感度,剪掉不同比例的卷积核数量。
两种剪方式都需要加载预训练模型。
卷积核剪切是基于结构剪切,所以在配置文件中需要注册一个`StructurePruner`, 如下所示:
两种剪方式都需要加载预训练模型。
通道剪裁是基于结构剪裁,所以在配置文件中需要注册一个`StructurePruner`, 如下所示:
```
pruners:
......@@ -310,13 +311,13 @@ pruners:
其中,一个配置文件可注册多个pruners, 所有pruner需要放在`pruners`关键字下, `pruner`的可配置参数有:
- **class:** pruner 的类型,目前只支持`StructurePruner`
- **pruning_axis:**切的纬度;'`conv*': 0`表示对所有的卷积层filter weight的第0维进行剪切,即对卷积层filter的数量进行剪切
- **criterions**: 通过通配符指定剪不同parameter时用的排序方式。目前仅支持`l1_norm`.
- **pruning_axis:**裁的纬度;'`conv*': 0`表示对所有的卷积层filter weight的第0维进行剪裁,即对卷积层filter的数量进行剪裁
- **criterions**: 通过通配符指定剪不同parameter时用的排序方式。目前仅支持`l1_norm`.
#### 2.2.1 uniform pruning
uniform pruning剪策略需要在配置文件的`strategies`关键字下注册`UniformPruneStrategy`实例,并将其添加至compressor的strategies列表中。
uniform pruning剪策略需要在配置文件的`strategies`关键字下注册`UniformPruneStrategy`实例,并将其添加至compressor的strategies列表中。
如下所示:
```
strategies:
......@@ -333,17 +334,17 @@ compressor:
```
UniformPruneStrategy的可配置参数有:
- **class:** 如果使用Uniform剪策略,请设置为`UniformPruneStrategy`
- **pruner:** StructurePruner实例的名称,需要在配置文件中注册。在pruner中指定了对单个parameter的剪方式。
- **start_epoch:** 开始剪切策略的epoch. 在start_epoch开始之前,该策略会对网络中的filter数量进行剪切,从start_epoch开始对被剪切的网络进行fine-tune训练,直到整个压缩任务结束。
- **class:** 如果使用Uniform剪策略,请设置为`UniformPruneStrategy`
- **pruner:** StructurePruner实例的名称,需要在配置文件中注册。在pruner中指定了对单个parameter的剪方式。
- **start_epoch:** 开始剪裁策略的epoch. 在start_epoch开始之前,该策略会对网络中的filter数量进行剪裁,从start_epoch开始对被剪裁的网络进行fine-tune训练,直到整个压缩任务结束。
- **target_ratio:** 将目标网络的FLOPS剪掉的比例。
- **pruned_params:** 被剪切的parameter的名称,支持通配符。如,‘*’为对所有parameter进行剪切,‘conv*’意为对所有名义以‘conv’开头的parameter进行剪切
- **pruned_params:** 被剪裁的parameter的名称,支持通配符。如,‘*’为对所有parameter进行剪裁,‘conv*’意为对所有名义以‘conv’开头的parameter进行剪裁
#### 2.2.2 sensitive pruning
sensitive剪策略需要在配置文件的`strategies`关键字下注册`SensitivePruneStrategy`实例,并将其添加至compressor的strategies列表中。
sensitive剪策略需要在配置文件的`strategies`关键字下注册`SensitivePruneStrategy`实例,并将其添加至compressor的strategies列表中。
如下所示:
```
strategies:
......@@ -365,14 +366,70 @@ compressor:
```
SensitivePruneStrategy可配置的参数有:
- **class:** 如果使用敏感度剪策略,请设置为`SensitivePruneStrategy`
- **pruner:** StructurePruner实例的名称,需要在配置文件中注册。在pruner中指定了对单个parameter的剪方式。
- **start_epoch:** 开始剪切策略的epoch。 在start_epoch开始之前,该策略会对网络中的filter数量进行第一次剪切
- **delta_rate:** 统计敏感度信息时,剪率从0到1,依次递增delta_rate. 具体细节可参考[原理介绍文档]()
- **class:** 如果使用敏感度剪策略,请设置为`SensitivePruneStrategy`
- **pruner:** StructurePruner实例的名称,需要在配置文件中注册。在pruner中指定了对单个parameter的剪方式。
- **start_epoch:** 开始剪裁策略的epoch。 在start_epoch开始之前,该策略会对网络中的filter数量进行第一次剪裁
- **delta_rate:** 统计敏感度信息时,剪率从0到1,依次递增delta_rate. 具体细节可参考[原理介绍文档]()
- **target_ratio:** 将目标网络的FLOPS剪掉的比例。
- **num_steps:** 整个剪过程的步数。每次迭代剪掉的比例为:$step = 1 - (1-target\_ratio)^{\frac{1}{num\_steps}}$
- **eval_rate:** 计算敏感度时,随机抽取使用的验证数据的比例。在迭代剪中,为了快速重新计算每一步的每个parameter的敏感度,建议随机选取部分验证数据进行计算。当`num_steps`等于1时,建议使用全量数据进行计算。
- **num_steps:** 整个剪过程的步数。每次迭代剪掉的比例为:$step = 1 - (1-target\_ratio)^{\frac{1}{num\_steps}}$
- **eval_rate:** 计算敏感度时,随机抽取使用的验证数据的比例。在迭代剪中,为了快速重新计算每一步的每个parameter的敏感度,建议随机选取部分验证数据进行计算。当`num_steps`等于1时,建议使用全量数据进行计算。
#### 2.2.3 auto filter pruning
该策略使用模拟退火算法搜索得到一组剪裁率,按搜索到的这组剪裁率剪裁网络,并对剪裁后的网络进行训练。
自动通道剪裁策略需要在配置文件的`strategies`关键字下注册`AutoPruneStrategy`实例,并将其添加至compressor的strategies列表中。
如下所示:
```
strategies:
auto_pruning_strategy:
class: 'AutoPruneStrategy'
pruner: 'pruner_1'
controller: 'sa_controller'
start_epoch: 0
end_epoch: 500
retrain_epoch: 0
max_ratio: 0.50
min_ratio: 0.48
uniform_range: 0.4
pruned_params: '.*_sep_weights'
metric_name: 'acc_top1'
compressor:
epoch: 500
checkpoint_path: './checkpoints/'
strategies:
- auto_pruning_strategy
```
AutoPruneStrategy可配置的参数有:
- **class:** 如果使用自动通道剪裁策略,请设置为`AutoPruneStrategy`
- **pruner:** StructurePruner实例的名称,需要在配置文件中注册。在pruner中指定了对单个parameter的剪裁方式。
- **controller:** 用于搜索的controller, 需要在当前配置文件提前注册,下文会详细介绍其注册方法。
- **start_epoch:** 开始搜索剪裁率组合的的epoch。
- **end_epoch:** 结束搜索剪裁率组合的epoch。 在end_epoch,该策略会根据当前搜索到的最好的剪裁率组合对网络进行剪裁。
- **retrain_epoch:** 评估一个模型性能之前,需要训练的epoch的数量。默认为0。
- **max_ratio:** 剪掉FLOPS的最高比例。
- **target_ratio:** 剪掉FLOPS的最低比例。
- **uniform_range:** 每个Parameter最多允许被剪掉的比例。
- **pruned_params:** 被剪裁的parameter的名称,支持通配符。如,‘*’为对所有parameter进行剪裁,‘conv*’意为对所有名义以‘conv’开头的parameter进行剪裁。
- **metric_name:** 评估模型性能的指标。
controller的配置方式如下:
```
controllers:
sa_controller:
class: 'SAController'
reduce_rate: 0.85
init_temperature: 10.24
max_iter_number: 300
```
- **class:** distiller类名称,当前可选:`SAController`
- **reduce_rate:** float类型;温度的衰减率。
- **init_temperature:** float类型;初始化温度。
- **max_iter_number:** int类型;在得到一个满足FLOPS限制的tokens之前,最多尝试的次数。
### 2.3 蒸馏
......@@ -452,3 +509,92 @@ distillers:
- **student_temperature:** 在计算softmax_with_cross_entropy之前,用该系数除student_feature_map。
- **teacher_temperature:** 在计算softmax_with_cross_entropy之前,用该系数除teacher_feature_map。
- **distillation_loss_weight:** 当前定义的loss对应的权重。默认为1.0
### 2.4 轻量级模型结构搜索
该功能基于模拟退火算法,实现了轻量级模型结构的快速搜索,简称为LightNAS(Light Network Architecture Search).
使用改功能,需要用户做两个工作:
- 定义搜索空间
- 配置LightNASStrategy,并启动压缩任务
#### 2.4.1 定义搜索空间
用户需要通过继承[SearchSpace类](https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/contrib/slim/nas/search_space.py#L19)并重写其方法来定义搜索空间。用户需要重写实现的方法有:
- init_tokens: tokens以数组的形式格式表示网络结构,一个tokens对应一个网络结构。init_tokens指搜索的初始化tokens.
- range_table: 以数组的形式指定tokens数组中每个位置的取值范围,其长度与tokens长度相同。tokens[i]的取值范围为[0, range_table[i]).
- create_net: 根据指定的tokens构造初始化Program、训练Program和测试Program.
[PaddlePaddle/models/light_nas](https://github.com/PaddlePaddle/models/blob/develop/PaddleSlim/light_nas/light_nas_space.py)下,定义了经过验证的一个搜索空间,建议一般用户直接用该搜索空间。
在构造Compressor对象时,按以下方式将SearchSpace实例传入:
```
...
space = LightNASSpace()
...
com_pass = Compressor(
place,
fluid.global_scope(),
train_prog,
train_reader=train_reader,
train_feed_list=None,
train_fetch_list=train_fetch_list,
eval_program=test_prog,
eval_reader=test_reader,
eval_feed_list=None,
eval_fetch_list=val_fetch_list,
train_optimizer=None,
search_space=space)
```
#### 2.4.2 配置LightNASStrategy
在配置文件中,配置搜索策略方式如下:
```
strategies:
light_nas_strategy:
class: 'LightNASStrategy'
controller: 'sa_controller'
target_flops: 592948064
end_epoch: 500
retrain_epoch: 5
metric_name: 'acc_top1'
server_ip: ''
server_port: 8871
is_server: True
search_steps: 100
```
其中, 需要在关键字`strategies`下注册策略实例,可配置参数有:
- **class:** 策略类的名称,轻量级模型结构搜索策略请设置为LightNASStrategy。
- **controller:** 用于搜索的controller, 需要在当前配置文件提前注册,下文会详细介绍其注册方法。
- **target_flops:** FLOPS限制,搜索出的网络结构的FLOPS不超过该数值。
- **end_epoch:** 当前client结束搜索策略的epoch。
- **retrain_epoch:** 在评估模型结构性能之前,需要训练的epoch数量。(end_epoch-0)/retrain_epoch为当前client搜索出的网络结构的数量。
- **metric_name:** 评估模型性能的指标。
- **server_ip:** 指定controller server的ip。默认为空,即自动获取当前机器的ip。
- **server_port:** 指定controller server监听的端口。
- **is_server:** 以当前配置文件启动的进程是否包含controller server. 整个搜索任务必须有且只有一个controller server。
- **search_steps:** controller server搜索的步数,也就是server产出的网络结构的数量。
controller的配置方式如下:
```
controllers:
sa_controller:
class: 'SAController'
reduce_rate: 0.85
init_temperature: 10.24
max_iter_number: 300
```
- **class:** distiller类名称,当前可选:`SAController`
- **reduce_rate:** float类型;温度的衰减率。
- **init_temperature:** float类型;初始化温度。
- **max_iter_number:** int类型;在得到一个满足FLOPS限制的tokens之前,最多尝试的次数。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册