diff --git a/PaddleSlim/README.md b/PaddleSlim/README.md
index b12b3c3e488b066048b08abac0606a7bc5bf73a3..561e7ef1016a558f4aa1b20bb310645098ed31a4 100644
--- a/PaddleSlim/README.md
+++ b/PaddleSlim/README.md
@@ -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,才能使用压缩功能。
-
+
图 1
@@ -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)的模型格式。
diff --git a/PaddleSlim/docs/demo.md b/PaddleSlim/docs/demo.md
index 8090fb736f3c15fdfb229d607cd488e0a554ecee..f09a7997f1492c0af260e3d863334258fd860313 100644
--- a/PaddleSlim/docs/demo.md
+++ b/PaddleSlim/docs/demo.md
@@ -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. 蒸馏:用ResNet50对MobileNetV1的在ImageNet 1000数据上的蒸馏训练。
2. 剪切:对预训练好的MobileNetV1进行剪切
-3. 量化:对预训练好的MobileNetV1进行int8量化训练
-4. 蒸馏量化组合:先用ResNet50对MobileNetV1进行蒸馏,再对蒸馏后得到的模型进行int8量化训练。
-5. 剪切量化组合:先用Uniform剪切策略对MobileNetV1进行剪切,再对剪切后的模型进行int8量化训练
+3. 量化:对预训练好的MobileNetV1进行int8量化训练
+4. 蒸馏量化组合:先用ResNet50对MobileNetV1进行蒸馏,再对蒸馏后得到的模型进行int8量化训练。
+5. 剪切量化组合:先用Uniform剪切策略对MobileNetV1进行剪切,再对剪切后的模型进行int8量化训练
+5. 小模型结构搜索示例: 先用模拟退火策略搜索出一组tokens, 再用该tokens构建网络进行训练。
本示例完整代码链接:https://github.com/PaddlePaddle/models/tree/develop/PaddleSlim
@@ -212,7 +214,64 @@ python compress.py \
图3
-### 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]|
diff --git a/PaddleSlim/docs/images/framework_0.png b/PaddleSlim/docs/images/framework_0.png
index 82d6f8bf1d0439e29d12d7a2bf81f109dbe95b71..223f384f23775403129a69967bbe9e891dfa77ff 100644
Binary files a/PaddleSlim/docs/images/framework_0.png and b/PaddleSlim/docs/images/framework_0.png differ
diff --git a/PaddleSlim/docs/images/light-nas-block.png b/PaddleSlim/docs/images/light-nas-block.png
new file mode 100644
index 0000000000000000000000000000000000000000..c469c1b634cef2dcf4c6e4f6c7907e7d7e9aaf09
Binary files /dev/null and b/PaddleSlim/docs/images/light-nas-block.png differ
diff --git a/PaddleSlim/docs/tutorial.md b/PaddleSlim/docs/tutorial.md
index e4dd13d29d16916dcbf6d637edf510d30693e68d..3f2ec6e536337d1fec24a08c2479397575180106 100644
--- a/PaddleSlim/docs/tutorial.md
+++ b/PaddleSlim/docs/tutorial.md
@@ -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.
@@ -137,9 +138,9 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$
-**剪切注意事项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} $$
图5
-**剪切注意事项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.
@@ -158,25 +159,25 @@ $$ Vt = (1 - k) * V + k * V_{t-1} $$
图6
-### 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} $$
图7
-如**图7**所示,横坐标是将filter剪切掉的比例,竖坐标是精度的损失,每条彩色虚线表示的是网络中的一个卷积层。
-以不同的剪切比例**单独**剪切一个卷积层,并观察其在验证数据集上的精度损失,并绘出**图7**中的虚线。虚线上升较慢的,对应的卷积层相对不敏感,我们优先剪不敏感的卷积层的filter.
+如**图7**所示,横坐标是将filter剪裁掉的比例,竖坐标是精度的损失,每条彩色虚线表示的是网络中的一个卷积层。
+以不同的剪裁比例**单独**剪裁一个卷积层,并观察其在验证数据集上的精度损失,并绘出**图7**中的虚线。虚线上升较慢的,对应的卷积层相对不敏感,我们优先剪不敏感的卷积层的filter.
-#### 选择最优的剪切率组合
+#### 选择最优的剪裁率组合
-我们将**图7**中的折线拟合为**图8**中的曲线,每在竖坐标轴上选取一个精度损失值,就在横坐标轴上对应着一组剪切率,如**图8**中黑色实线所示。
-用户给定一个模型整体的剪切率,我们通过移动**图5**中的黑色实线来找到一组满足条件的且合法的剪切率。
+我们将**图7**中的折线拟合为**图8**中的曲线,每在竖坐标轴上选取一个精度损失值,就在横坐标轴上对应着一组剪裁率,如**图8**中黑色实线所示。
+用户给定一个模型整体的剪裁率,我们通过移动**图5**中的黑色实线来找到一组满足条件的且合法的剪裁率。
图8
-#### 迭代剪切
-考虑到多个卷积层间的相关性,一个卷积层的修改可能会影响其它卷积层的敏感度,我们采取了多次剪切的策略,步骤如下:
+#### 迭代剪裁
+考虑到多个卷积层间的相关性,一个卷积层的修改可能会影响其它卷积层的敏感度,我们采取了多次剪裁的策略,步骤如下:
- 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所示:
+
+
+
+图10
+
+
+
+## 5. 参考文献
1. [High-Performance Hardware for Machine Learning](https://media.nips.cc/Conferences/2015/tutorialslides/Dally-NIPS-Tutorial-2015.pdf)
diff --git a/PaddleSlim/docs/usage.md b/PaddleSlim/docs/usage.md
index 48069bc30a078317e3d6d4e7298f1f7251691722..6733f7512745a7f91afccc60e996fe8e23dddf6c 100644
--- a/PaddleSlim/docs/usage.md
+++ b/PaddleSlim/docs/usage.md
@@ -18,7 +18,7 @@
---
# Paddle模型压缩工具库使用说明
-本文第一章介绍PaddleSlim模块通用功能的使用,不涉及具体压缩策略的细节。第二、三、四章分别介绍量化训练、剪切、蒸馏三种压缩策略的使用方式。
+本文第一章介绍PaddleSlim模块通用功能的使用,不涉及具体压缩策略的细节。第二章分别用4小节介绍量化训练、剪裁、蒸馏和轻量级模型结构搜索四种压缩策略的使用方式。
建议在看具体策略使用方式之前,先浏览下对应的原理介绍:算法原理介绍
>在本文中不区分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之前,最多尝试的次数。