未验证 提交 d0e11f4b 编写于 作者: G Guanghua Yu 提交者: GitHub

add tinyposs auto-compression (#1083)

上级 b4ac163c
_BASE_: [
'./coco_dataset.yml',
]
worker_num: 8
TestReader:
inputs_def:
image_shape: [3, 640, 640]
sample_transforms:
- Decode: {}
- Resize: {target_size: [640, 640], keep_ratio: False, interp: 2}
- NormalizeImage: {mean: [0.485, 0.456, 0.406], std: [0.229, 0.224, 0.225], is_scale: True}
- Permute: {}
batch_size: 4
# 使用预测模型进行量化训练示例
# 目标检测模型自动压缩
预测模型保存接口:
动态图使用``paddle.jit.save``保存;
......@@ -41,9 +41,9 @@ tar -xf yolov3_mobilenet_v1_270e_coco.tar
```
cd PaddleSlim/demo/auto-compression/
```
使用[demo_coco.py](../../demo_coco.py)脚本得到模型的mAP:
使用[run_main.py](run_main.py)脚本得到模型的mAP:
```
python3.7 ../../demo_coco.py --model_dir=../../yolov3_mobilenet_v1_270e_coco/ --model_filename=model.pdmodel --params_filename=model.pdiparams --eval=True
python3.7 run_main.py --config_path='./configs/yolov3_mbv1_qat_dis.yaml --eval=True
```
### 3. 进行多策略融合压缩
......@@ -51,13 +51,7 @@ python3.7 ../../demo_coco.py --model_dir=../../yolov3_mobilenet_v1_270e_coco/ --
每一个小章节代表一种多策略融合压缩,不代表需要串行执行。
### 3.1 进行量化蒸馏压缩
蒸馏量化训练示例脚本为[demo_coco.py](../../demo_coco.py),使用接口``paddleslim.auto_compression.AutoCompression``对模型进行量化训练。运行命令为:
```
python ../../demo_coco.py \
--model_dir='infermodel_mobilenetv2' \
--model_filename='model.pdmodel' \
--params_filename='./model.pdiparams' \
--save_dir='./output/' \
--devices='gpu' \
--config_path='./yolov3_mbv1_qat_dis.yaml'
蒸馏量化训练示例脚本为[run_main.py](run_main.py),使用接口``paddleslim.auto_compression.AutoCompression``对模型进行量化训练。运行命令为:
```
python run_main.py --config_path='./configs/yolov3_mbv1_qat_dis.yaml --save_dir='./output/' --devices='gpu'
```
Global:
reader_config: configs/tinypose_reader.yml
input_list: ['image']
Evaluation: False
model_dir: ./tinypose_128x96/
model_filename: model.pdmodel
params_filename: model.pdiparams
Distillation:
distill_lambda: 1.0
distill_loss: l2_loss
distill_node_pair:
- teacher_conv2d_441.tmp_0
- conv2d_441.tmp_0
merge_feed: true
teacher_model_dir: ./tinypose_128x96/
teacher_model_filename: model.pdmodel
teacher_params_filename: model.pdiparams
Quantization:
activation_bits: 8
is_full_quantize: false
activation_quantize_type: 'range_abs_max'
weight_quantize_type: 'abs_max'
not_quant_pattern:
- skip_quant
quantize_op_types:
- conv2d
- depthwise_conv2d
weight_bits: 8
TrainConfig:
epochs: 1
eval_iter: 1000
learning_rate: 0.0001
optimizer: SGD
optim_args:
weight_decay: 4.0e-05
#origin_metric: 0.291
num_joints: &num_joints 17
pixel_std: &pixel_std 200
metric: KeyPointTopDownCOCOEval
num_classes: 1
train_height: &train_height 128
train_width: &train_width 96
trainsize: &trainsize [*train_width, *train_height]
hmsize: &hmsize [24, 32]
flip_perm: &flip_perm [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12], [13, 14], [15, 16]]
TrainDataset:
!KeypointTopDownCocoDataset
image_dir: val2017
anno_path: annotations/person_keypoints_val2017.json
dataset_dir: dataset/coco
num_joints: *num_joints
trainsize: *trainsize
pixel_std: *pixel_std
use_gt_bbox: True
image_thre: 0.5
EvalDataset:
!KeypointTopDownCocoDataset
image_dir: val2017
anno_path: annotations/person_keypoints_val2017.json
dataset_dir: dataset/coco
num_joints: *num_joints
trainsize: *trainsize
pixel_std: *pixel_std
use_gt_bbox: True
image_thre: 0.5
worker_num: 2
global_mean: &global_mean [0.485, 0.456, 0.406]
global_std: &global_std [0.229, 0.224, 0.225]
EvalReader:
sample_transforms:
- TopDownAffine:
trainsize: *trainsize
use_udp: true
batch_transforms:
- NormalizeImage:
mean: *global_mean
std: *global_std
is_scale: true
- Permute: {}
batch_size: 4
metric: COCO
num_classes: 80
# Datset configuration
TrainDataset:
!COCODataSet
image_dir: train2017
......@@ -13,6 +14,13 @@ EvalDataset:
anno_path: annotations/instances_val2017.json
dataset_dir: dataset/coco/
TestDataset:
!ImageFolder
anno_path: annotations/instances_val2017.json
worker_num: 8
# preprocess reader in test
EvalReader:
sample_transforms:
- Decode: {}
- Resize: {target_size: [640, 640], keep_ratio: False, interp: 2}
- NormalizeImage: {mean: [0.485, 0.456, 0.406], std: [0.229, 0.224, 0.225], is_scale: True}
- Permute: {}
batch_size: 4
Global:
reader_config: configs/yolo_reader.yml
input_list: ['image', 'im_shape', 'scale_factor']
Evaluation: True
model_dir: ./yolov3_mobilenet_v1_270e_coco/
model_filename: model.pdmodel
params_filename: model.pdiparams
Distillation:
distill_lambda: 1.0
distill_loss: l2_loss
......@@ -12,8 +20,11 @@ Distillation:
teacher_model_dir: ./yolov3_mobilenet_v1_270e_coco/
teacher_model_filename: model.pdmodel
teacher_params_filename: model.pdiparams
Quantization:
activation_bits: 8
activation_quantize_type: 'range_abs_max'
weight_quantize_type: 'channel_wise_abs_max'
is_full_quantize: false
not_quant_pattern:
- skip_quant
......@@ -21,6 +32,7 @@ Quantization:
- conv2d
- depthwise_conv2d
weight_bits: 8
TrainConfig:
epochs: 1
eval_iter: 1000
......
......@@ -20,9 +20,6 @@ parser = argparse.ArgumentParser(description=__doc__)
add_arg = functools.partial(add_arguments, argparser=parser)
# yapf: disable
add_arg('model_dir', str, None, "inference model directory.")
add_arg('model_filename', str, None, "inference model filename.")
add_arg('params_filename', str, None, "inference params filename.")
add_arg('save_dir', str, 'output', "directory to save compressed model.")
add_arg('devices', str, 'gpu', "which device used to compress.")
add_arg('batch_size', int, 1, "train batch size.")
......@@ -31,45 +28,40 @@ add_arg('eval', bool, False, "whether to run eval
# yapf: enable
def reader_wrapper(reader):
def reader_wrapper(reader, input_list):
def gen():
for data in reader:
yield {
"image": data['image'],
'im_shape': data['im_shape'],
'scale_factor': data['scale_factor']
}
in_dict = {}
for input_name in input_list:
in_dict[input_name] = data[input_name]
yield in_dict
return gen
def eval():
dataset = reader_cfg['EvalDataset']
val_loader = create('TestReader')(dataset,
reader_cfg['worker_num'],
return_list=True)
def eval(args, compress_config):
place = paddle.CUDAPlace(0) if args.devices == 'gpu' else paddle.CPUPlace()
exe = paddle.static.Executor(place)
val_program, feed_target_names, fetch_targets = paddle.fluid.io.load_inference_model(
args.model_dir,
compress_config["model_dir"],
exe,
model_filename=args.model_filename,
params_filename=args.params_filename)
model_filename=compress_config["model_filename"],
params_filename=compress_config["params_filename"], )
clsid2catid = {v: k for k, v in dataset.catid2clsid.items()}
anno_file = dataset.get_anno()
metric = COCOMetric(
anno_file=anno_file, clsid2catid=clsid2catid, bias=0, IouType='bbox')
for batch_id, data in enumerate(val_loader):
data_new = {k: np.array(v) for k, v in data.items()}
data_all = {k: np.array(v) for k, v in data.items()}
data_input = {}
for k, v in data.items():
if k in compress_config['input_list']:
data_input[k] = np.array(v)
outs = exe.run(val_program,
feed={
'image': data['image'],
'im_shape': data['im_shape'],
'scale_factor': data['scale_factor']
},
feed=data_input,
fetch_list=fetch_targets,
return_numpy=False)
res = {}
......@@ -80,7 +72,7 @@ def eval():
else:
res['bbox_num'] = v
metric.update(data_new, res)
metric.update(data_all, res)
if batch_id % 100 == 0:
print('Eval iter:', batch_id)
metric.accumulate()
......@@ -95,13 +87,13 @@ def eval_function(exe, compiled_test_program, test_feed_names, test_fetch_list):
metric = COCOMetric(
anno_file=anno_file, clsid2catid=clsid2catid, bias=1, IouType='bbox')
for batch_id, data in enumerate(val_loader):
data_new = {k: np.array(v) for k, v in data.items()}
data_all = {k: np.array(v) for k, v in data.items()}
data_input = {}
for k, v in data.items():
if k in test_feed_names:
data_input[k] = np.array(v)
outs = exe.run(compiled_test_program,
feed={
'image': data['image'],
'im_shape': data['im_shape'],
'scale_factor': data['scale_factor']
},
feed=data_input,
fetch_list=test_fetch_list,
return_numpy=False)
res = {}
......@@ -112,7 +104,7 @@ def eval_function(exe, compiled_test_program, test_feed_names, test_fetch_list):
else:
res['bbox_num'] = v
metric.update(data_new, res)
metric.update(data_all, res)
if batch_id % 100 == 0:
print('Eval iter:', batch_id)
metric.accumulate()
......@@ -122,36 +114,47 @@ def eval_function(exe, compiled_test_program, test_feed_names, test_fetch_list):
return map_res['bbox'][0]
if __name__ == '__main__':
args = parser.parse_args()
print_arguments(args)
paddle.enable_static()
reader_cfg = load_config('./configs/PaddleDet/yolo_reader.yml')
if args.eval:
eval()
sys.exit(0)
def main(args):
compress_config, train_config = load_slim_config(args.config_path)
reader_cfg = load_config(compress_config['reader_config'])
train_loader = create('TestReader')(reader_cfg['TrainDataset'],
train_loader = create('EvalReader')(reader_cfg['TrainDataset'],
reader_cfg['worker_num'],
return_list=True)
train_loader = reader_wrapper(train_loader, compress_config['input_list'])
global dataset
dataset = reader_cfg['EvalDataset']
val_loader = create('TestReader')(reader_cfg['EvalDataset'],
global val_loader
val_loader = create('EvalReader')(reader_cfg['EvalDataset'],
reader_cfg['worker_num'],
return_list=True)
train_dataloader = reader_wrapper(train_loader)
if args.eval:
eval(args, compress_config)
sys.exit(0)
if 'Evaluation' in compress_config.keys() and compress_config['Evaluation']:
eval_func = eval_function
else:
eval_func = None
ac = AutoCompression(
model_dir=args.model_dir,
model_filename=args.model_filename,
params_filename=args.params_filename,
model_dir=compress_config["model_dir"],
model_filename=compress_config["model_filename"],
params_filename=compress_config["params_filename"],
save_dir=args.save_dir,
strategy_config=compress_config,
train_config=train_config,
train_dataloader=train_dataloader,
eval_callback=eval_function,
train_dataloader=train_loader,
eval_callback=eval_func,
devices=args.devices)
ac.compress()
if __name__ == '__main__':
args = parser.parse_args()
print_arguments(args)
paddle.enable_static()
main(args)
......@@ -41,7 +41,7 @@ class AutoCompression:
strategy_config,
train_config,
train_dataloader,
eval_callback,
eval_callback=None,
devices='gpu'):
### model_dir(str): 模型路径
### model_filename(str): 模型文件名称
......@@ -61,6 +61,9 @@ class AutoCompression:
paddle.enable_static()
if self.train_config is not None and self.train_config.use_fleet:
fleet.init(is_collective=True)
if not eval_callback:
self.eval_function = None
self.eval_dataloader = None
if self._prepare_eval(eval_callback) == 'eval_dataloader':
self.eval_function = None
self.eval_dataloader = eval_callback
......@@ -163,8 +166,6 @@ class AutoCompression:
self._exe, self._places, config_dict, train_program_info,
self._strategy)
if self.train_config.use_fleet:
dist_strategy = _prepare_fleet_strategy(self.train_config)
else:
......@@ -190,8 +191,6 @@ class AutoCompression:
self._exe.run(train_program_info.startup_program)
if (not self.train_config.use_fleet
) and self.train_config.amp_config is not None:
if hasattr(self.train_config.amp_config, 'use_pure_fp16'
......@@ -345,8 +344,9 @@ class AutoCompression:
return
else:
raise NotImplementedError(
"Please support eval function")
_logger.warning(
"Not set eval function, so unable to test accuracy performance."
)
if 'qat' in self._strategy:
### TODO: load best model to save
......
......@@ -27,8 +27,13 @@ def load_config(config_path):
compress_config = {}
for key, value in cfg.items():
default_key = eval(key)(**value)
compress_config[key] = default_key
if key == "Global":
for g_key, g_value in cfg["Global"].items():
compress_config[g_key] = g_value
else:
default_key = eval(key)(**value)
compress_config[key] = default_key
if compress_config.get('TrainConfig') != None:
train_config = compress_config.pop('TrainConfig')
else:
......
......@@ -27,9 +27,11 @@ Quantization = namedtuple(
"quantize_op_types",
"weight_bits",
"activation_bits",
"not_quant_pattern", ### ptq没有暴露相应接口
"use_pact", ### 仅QAT支持
"is_full_quantize"
"not_quant_pattern", # Only support in QAT
"use_pact", # Only support in QAT
"is_full_quantize",
"activation_quantize_type",
"weight_quantize_type"
])
Quantization.__new__.__defaults__ = (None, ) * (len(Quantization._fields) - 1
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册