Skip to content

Commit 0db9a28

Browse files
authored
update ACT quick start demo (PaddlePaddle#1116)
1 parent bdffa0f commit 0db9a28

File tree

5 files changed

+153
-51
lines changed

5 files changed

+153
-51
lines changed

demo/auto_compression/README.md

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# 自动压缩工具ACT(Auto Compression Tookit)
1+
# 自动化压缩工具ACT(Auto Compression Tookit)
22

33
## 简介
4-
PaddleSlim推出全新自动压缩工具(ACT),旨在通过Source-Free的方式,自动对预测模型进行压缩,压缩后模型可直接部署应用。ACT自动压缩工具主要特性如下
4+
PaddleSlim推出全新自动化压缩工具(ACT),旨在通过Source-Free的方式,自动对预测模型进行压缩,压缩后模型可直接部署应用。ACT自动化压缩工具主要特性如下
55
- **『更便捷』**:开发者无需了解或修改模型源码,直接使用导出的预测模型进行压缩;
66
- **『更智能』**:开发者简单配置即可启动压缩,ACT工具会自动优化得到最好预测模型;
77
- **『更丰富』**:ACT中提供了量化训练、蒸馏、结构化剪枝、非结构化剪枝、多种离线量化方法及超参搜索等等,可任意搭配使用。
@@ -14,32 +14,68 @@ PaddleSlim推出全新自动压缩工具(ACT),旨在通过Source-Free的
1414

1515
## 快速上手
1616

17+
- 1.准备模型及数据集
18+
19+
```shell
20+
# 下载MobileNet预测模型
21+
wget https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/inference/MobileNetV1_infer.tar
22+
tar -xf MobileNetV1_infer.tar
23+
# 下载ImageNet小型数据集
24+
wget https://sys-p0.bj.bcebos.com/slim_ci/ILSVRC2012_data_demo.tar.gz
25+
tar xf ILSVRC2012_data_demo.tar.gz
26+
```
27+
28+
- 2.运行
29+
1730
```python
1831
# 导入依赖包
19-
from paddleslim.auto_compression.config_helpers import load_config
32+
import paddle
33+
from PIL import Image
34+
from paddle.vision.datasets import DatasetFolder
35+
from paddle.vision.transforms import transforms
2036
from paddleslim.auto_compression import AutoCompression
21-
from paddleslim.common.imagenet_reader import reader
22-
# 加载配置文件
23-
compress_config, train_config = load_slim_config("./image_classification/mobilenetv1_qat_dis.yaml")
37+
paddle.enable_static()
38+
# 定义DataSet
39+
class ImageNetDataset(DatasetFolder):
40+
def __init__(self, path, image_size=224):
41+
super(ImageNetDataset, self).__init__(path)
42+
normalize = transforms.Normalize(
43+
mean=[123.675, 116.28, 103.53], std=[58.395, 57.120, 57.375])
44+
self.transform = transforms.Compose([
45+
transforms.Resize(256),
46+
transforms.CenterCrop(image_size), transforms.Transpose(),
47+
normalize
48+
])
49+
50+
def __getitem__(self, idx):
51+
img_path, _ = self.samples[idx]
52+
return self.transform(Image.open(img_path).convert('RGB'))
53+
54+
def __len__(self):
55+
return len(self.samples)
56+
2457
# 定义DataLoader
25-
train_loader = reader(mode='test') # DataLoader
58+
train_dataset = ImageNetDataset("./ILSVRC2012_data_demo/ILSVRC2012/train/")
59+
image = paddle.static.data(
60+
name='inputs', shape=[None] + [3, 224, 224], dtype='float32')
61+
train_loader = paddle.io.DataLoader(train_dataset, feed_list=[image], batch_size=32)
2662
# 开始自动压缩
2763
ac = AutoCompression(
28-
model_dir="./mobilenetv1_infer",
29-
model_filename="model.pdmodel",
30-
params_filename="model.pdiparams",
64+
model_dir="./MobileNetV1_infer/",
65+
model_filename="inference.pdmodel",
66+
params_filename="inference.pdiparams",
3167
save_dir="output",
32-
strategy_config=compress_config,
33-
train_config=train_config,
68+
strategy_config=None,
69+
train_config=None,
3470
train_dataloader=train_loader,
35-
eval_callback=None) # eval_function to verify accuracy
71+
eval_dataloader=train_loader) # eval_function to verify accuracy
3672
ac.compress()
3773
```
3874

3975
**提示:**
4076
- DataLoader传入的数据集是待压缩模型所用的数据集,DataLoader继承自`paddle.io.DataLoader`
41-
- 如无需验证自动压缩过程中模型的精度`eval_callback`可不传入function,程序会自动根据损失来选择最优模型。
42-
- 自动压缩Config中定义量化、蒸馏、剪枝等压缩算法会合并执行,压缩策略有:量化+蒸馏,剪枝+蒸馏等等。
77+
- 如无需验证自动化压缩过程中模型的精度`eval_callback`可不传入function,程序会自动根据损失来选择最优模型。
78+
- 自动化压缩Config中定义量化、蒸馏、剪枝等压缩算法会合并执行,压缩策略有:量化+蒸馏,剪枝+蒸馏等等。
4379

4480
## 应用示例
4581

@@ -52,11 +88,11 @@ ac.compress()
5288
#### [NLP](./nlp)
5389

5490
#### 即将发布
55-
- [ ] 更多自动压缩应用示例
56-
- [ ] X2Paddle模型自动压缩示例
91+
- [ ] 更多自动化压缩应用示例
92+
- [ ] X2Paddle模型自动化压缩示例
5793

5894
## 其他
5995

6096
- ACT可以自动处理常见的预测模型,如果有更特殊的改造需求,可以参考[ACT超参配置教程](./hyperparameter_tutorial.md)来进行单独配置压缩策略。
6197

62-
- 如果你发现任何关于ACT自动压缩工具的问题或者是建议, 欢迎通过[GitHub Issues](https://github.com/PaddlePaddle/PaddleSlim/issues)给我们提issues。同时欢迎贡献更多优秀模型,共建开源生态。
98+
- 如果你发现任何关于ACT自动化压缩工具的问题或者是建议, 欢迎通过[GitHub Issues](https://github.com/PaddlePaddle/PaddleSlim/issues)给我们提issues。同时欢迎贡献更多优秀模型,共建开源生态。

demo/auto_compression/image_classification/README.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
## 2. Benchmark
1919
- MobileNetV1模型
2020

21-
| 模型 | 策略 | Top-1 Acc | 耗时(ms) threads=4 |
21+
| 模型 | 策略 | Top-1 Acc | 耗时(ms) threads=4 |
2222
|:------:|:------:|:------:|:------:|
23-
| MobileNetV1 | Base模型 | 70.90 | 39.041 |
23+
| MobileNetV1 | Base模型 | 70.90 | 39.041 |
2424
| MobileNetV1 | 量化+蒸馏 | 70.49 | 29.238|
2525

2626
- 测试环境:`SDM710 2*A75(2.2GHz) 6*A55(1.7GHz)`
@@ -59,7 +59,7 @@ pip install paddleslim
5959

6060
```shell
6161
wget https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/inference/MobileNetV1_infer.tar
62-
tar -zxvf MobileNetV1_infer.tar
62+
tar -xf MobileNetV1_infer.tar
6363
```
6464
也可根据[PaddleClas文档](https://github.com/PaddlePaddle/PaddleClas/blob/release/2.3/docs/zh_CN/inference_deployment/export_model.md)导出Inference模型。
6565

@@ -73,20 +73,20 @@ python run.py \
7373
--model_dir='MobileNetV1_infer' \
7474
--model_filename='inference.pdmodel' \
7575
--params_filename='inference.pdiparams' \
76-
--save_dir='./save_quant_mobilev1/' \
76+
--save_dir='./output' \
7777
--batch_size=128 \
78-
--config_path='./configs/mobilev1.yaml'\
78+
--config_path='./configs/mobilenetv1_qat_dis.yaml'\
7979
--data_dir='ILSVRC2012'
80-
80+
8181
# 多卡启动
8282
python -m paddle.distributed.launch run.py \
8383
--model_dir='MobileNetV1_infer' \
8484
--model_filename='inference.pdmodel' \
8585
--params_filename='inference.pdiparams' \
86-
--save_dir='./save_quant_mobilev1/' \
86+
--save_dir='./output' \
8787
--batch_size=128 \
88-
--config_path='./configs/mobilev1.yaml'\
89-
--data_dir='ILSVRC2012'
88+
--config_path='./configs/mobilenetv1_qat_dis.yaml'\
89+
--data_dir='ILSVRC2012'
9090
```
9191

9292

@@ -96,4 +96,4 @@ python -m paddle.distributed.launch run.py \
9696
- [Paddle Inference C++部署](https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.5/docs/deployment/inference/cpp_inference.md)
9797
- [Paddle Lite部署](https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.5/docs/deployment/lite/lite.md)
9898

99-
## 5.FAQ
99+
## 5.FAQ

paddleslim/auto_compression/auto_strategy.py

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@
2525
"prepare_strategy", "create_strategy_config", "get_final_quant_config"
2626
]
2727

28-
### config tester to test the loss of quant_post
28+
# config tester to test the loss of quant_post
2929
hpo_config_tester = {
30-
"ptq_algo": ["avg", "mse", "KL"],
30+
"ptq_algo": ["avg"],
3131
"weight_quantize_type": ['channel_wise_abs_max', 'abs_max'],
3232
"bias_correct": [False],
33-
"batch_num": [2, 3],
33+
"batch_num": [5],
3434
"max_quant_count": 1,
3535
}
3636

37-
### default hpo config
37+
# default hpo config
3838
default_hpo_config = {
3939
"ptq_algo": ["KL", "hist", "avg", "mse"],
4040
"weight_quantize_type": ['channel_wise_abs_max', 'abs_max'],
@@ -44,11 +44,26 @@
4444
"max_quant_count": 20,
4545
}
4646

47-
### default quant config, can be used by ptq&hpo and qat&distillation
47+
# default quant config, can be used by ptq&hpo and qat&distillation
4848
default_quant_config = {
4949
'quantize_op_types': ['conv2d', 'depthwise_conv2d', 'mul', 'matmul'],
5050
'weight_bits': 8,
51-
'activation_bits': 8
51+
'activation_bits': 8,
52+
"is_full_quantize": False,
53+
"activation_quantize_type": 'range_abs_max',
54+
"weight_quantize_type": 'abs_max',
55+
"not_quant_pattern": ["skip_quant"],
56+
}
57+
58+
# default train config
59+
DefaultTrainConfig = {
60+
"epochs": 1,
61+
"eval_iter": 500,
62+
"learning_rate": 0.0001,
63+
"optimizer": "Momentum",
64+
"optim_args": {
65+
"weight_decay": 4.0e-05
66+
},
5267
}
5368

5469
EXPERIENCE_STRATEGY_WITHOUT_LOSS = [
@@ -118,6 +133,12 @@ def create_strategy_config(strategy_str, model_type):
118133
return configs
119134

120135

136+
def create_train_config(strategy_str, model_type):
137+
# TDOD: support more strategy and model_type
138+
train_config = TrainConfig(**DefaultTrainConfig)
139+
return train_config
140+
141+
121142
def prepare_strategy(model_dir,
122143
model_filename,
123144
params_filename,
@@ -203,20 +224,21 @@ def prepare_strategy(model_dir,
203224
return strategy_config
204225

205226

206-
def get_final_quant_config(ptq_loss):
227+
def get_final_quant_config(ptq_loss, mode='DistilQuant'):
207228
""" transform quantization tester config to real quantization config """
208-
if ptq_loss <= MAGIC_EMD_DISTANCE:
229+
if mode == 'HPO':
209230
quant_config = Quantization(**default_quant_config)
210231
hpo_config = HyperParameterOptimization(**default_hpo_config)
211232
configs = [{
212233
'Quantization': quant_config,
213234
'HyperParameterOptimization': hpo_config
214235
}]
215236

216-
else:
237+
if mode == 'DistilQuant':
217238
quant_config = Quantization(**default_quant_config)
218239
dis_config = Distillation()
219240
configs = [{'Quantization': quant_config, 'Distillation': dis_config}]
241+
_logger.info("Start Quantization and Distillation Training.")
220242

221243
return configs
222244

paddleslim/auto_compression/compressor.py

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@
2424
import paddle.distributed.fleet as fleet
2525
if platform.system().lower() == 'linux':
2626
from ..quant import quant_post_hpo
27-
from ..quant.quanter import convert
27+
from ..quant.quanter import convert, quant_post
2828
from ..common.recover_program import recover_inference_program
2929
from ..common import get_logger
3030
from ..common.patterns import get_patterns
3131
from ..analysis import TableLatencyPredictor
3232
from .create_compressed_program import build_distill_program, build_quant_program, build_prune_program, remove_unused_var_nodes
3333
from .strategy_config import ProgramInfo, merge_config
34-
from .auto_strategy import prepare_strategy, get_final_quant_config, create_strategy_config
34+
from .auto_strategy import prepare_strategy, get_final_quant_config, create_strategy_config, create_train_config
3535

3636
_logger = get_logger(__name__, level=logging.INFO)
3737

@@ -143,6 +143,11 @@ def __init__(self,
143143
self._strategy, self._config = self._prepare_strategy(
144144
self.strategy_config)
145145

146+
# If train_config is None, set default train_config
147+
if self.train_config is None:
148+
self.train_config = create_train_config(self.strategy_config,
149+
self.model_type)
150+
146151
def _prepare_envs(self):
147152
devices = paddle.device.get_device().split(':')[0]
148153
places = paddle.device._convert_to_place(devices)
@@ -248,8 +253,9 @@ def _prepare_program(self, program, feed_target_names, fetch_targets,
248253
feed_target_names, fetch_targets)
249254

250255
config_dict = dict(config._asdict())
251-
if config_dict["prune_strategy"] == "gmp" and config_dict[
252-
'gmp_config'] is None:
256+
if "prune_strategy" in config_dict and config_dict[
257+
"prune_strategy"] == "gmp" and config_dict[
258+
'gmp_config'] is None:
253259
_logger.info(
254260
"Calculating the iterations per epoch……(It will take some time)")
255261
# NOTE:XXX: This way of calculating the iters needs to be improved.
@@ -351,20 +357,57 @@ def compress(self):
351357
).lower() == 'linux':
352358
ptq_loss = quant_post_hpo.g_min_emd_loss
353359

354-
final_quant_config = get_final_quant_config(ptq_loss)
360+
final_quant_config = get_final_quant_config(
361+
ptq_loss, mode='DistilQuant')
355362
quant_strategy, quant_config = self._prepare_strategy(
356363
final_quant_config)
357364
self.single_strategy_compress(quant_strategy[0], quant_config[0],
358365
strategy_idx)
359-
old_model_path = os.path.join(
366+
tmp_model_path = os.path.join(
360367
self.save_dir, 'strategy_{}'.format(str(strategy_idx + 1)))
361368
final_model_path = os.path.join(self.final_dir)
362-
shutil.move(old_model_path, final_model_path)
369+
if not os.path.exists(final_model_path):
370+
os.makedirs(final_model_path)
371+
tmp_model_file = os.path.join(tmp_model_path, 'model.pdmodel')
372+
tmp_params_file = os.path.join(tmp_model_path, 'model.pdiparams')
373+
final_model_file = os.path.join(final_model_path, 'model.pdmodel')
374+
final_params_file = os.path.join(final_model_path, 'model.pdiparams')
375+
shutil.move(tmp_model_file, final_model_file)
376+
shutil.move(tmp_params_file, final_params_file)
377+
_logger.info(
378+
"==> Finished the ACT process and the final model is saved in:{}".
379+
format(final_model_path))
363380
os._exit(0)
364381

365382
def single_strategy_compress(self, strategy, config, strategy_idx):
366-
### start compress, including train/eval model
367-
if strategy == 'ptq_hpo':
383+
# start compress, including train/eval model
384+
# TODO: add the emd loss of evaluation model.
385+
if strategy == 'quant_post':
386+
quant_post(
387+
self._exe,
388+
model_dir=self.model_dir,
389+
quantize_model_path=os.path.join(
390+
self.save_dir, 'strategy_{}'.format(str(strategy_idx + 1))),
391+
data_loader=self.train_dataloader,
392+
model_filename=self.model_filename,
393+
params_filename=self.params_filename,
394+
save_model_filename=self.model_filename,
395+
save_params_filename=self.params_filename,
396+
batch_size=1,
397+
batch_nums=config.batch_num,
398+
algo=config.ptq_algo,
399+
round_type='round',
400+
bias_correct=config.bias_correct,
401+
hist_percent=config.hist_percent,
402+
quantizable_op_type=config.quantize_op_types,
403+
is_full_quantize=config.is_full_quantize,
404+
weight_bits=config.weight_bits,
405+
activation_bits=config.activation_bits,
406+
activation_quantize_type='range_abs_max',
407+
weight_quantize_type=config.weight_quantize_type,
408+
onnx_format=False)
409+
410+
elif strategy == 'ptq_hpo':
368411
if platform.system().lower() != 'linux':
369412
raise NotImplementedError(
370413
"post-quant-hpo is not support in system other than linux")
@@ -503,11 +546,12 @@ def _save_model(self, test_program_info, strategy, strategy_idx):
503546
test_program_info.program,
504547
paddle.static.CompiledProgram) else test_program_info.program
505548

506-
paddle.static.load(test_program,
507-
os.path.join(self.save_dir, 'best_model'))
508-
os.remove(os.path.join(self.save_dir, 'best_model.pdmodel'))
509-
os.remove(os.path.join(self.save_dir, 'best_model.pdopt'))
510-
os.remove(os.path.join(self.save_dir, 'best_model.pdparams'))
549+
if os.path.exists(os.path.join(self.save_dir, 'best_model.pdparams')):
550+
paddle.static.load(test_program,
551+
os.path.join(self.save_dir, 'best_model'))
552+
os.remove(os.path.join(self.save_dir, 'best_model.pdmodel'))
553+
os.remove(os.path.join(self.save_dir, 'best_model.pdopt'))
554+
os.remove(os.path.join(self.save_dir, 'best_model.pdparams'))
511555

512556
if 'qat' in strategy:
513557
float_program, int8_program = convert(test_program_info.program._program, self._places, self._quant_config, \

0 commit comments

Comments
 (0)