未验证 提交 bc442429 编写于 作者: G gushiqiao 提交者: GitHub

Add reconstuction quant algorithm (#1457)

上级 880ad20b
arch: YOLOv6
model_dir: ./yolov6s.onnx
dataset_dir: /dataset/coco/
model_filename: model.pdmodel
params_filename: model.pdiparams
train_image_dir: train2017
val_image_dir: val2017
train_anno_path: annotations/instances_train2017.json
val_anno_path: annotations/instances_val2017.json
skip_tensor_list: None
regions: [['x2paddle_image_arrays','relu_8.tmp_0'],
['relu_8.tmp_0','relu_15.tmp_0'],
['relu_15.tmp_0','relu_21.tmp_0'],
['concat_1.tmp_0','relu_26.tmp_0'],
['concat_2.tmp_0', 'relu_30.tmp_0'],
['relu_30.tmp_0', 'concat_4.tmp_0'],
['relu_30.tmp_0', 'relu_31.tmp_0'],
['concat_3.tmp_0', 'relu_35.tmp_0'],
['relu_35.tmp_0', 'relu_36.tmp_0'],
['concat_5.tmp_0', 'concat_10.tmp_0'],
['relu_35.tmp_0', 'concat_8.tmp_0']]
region_weights_names: [['conv2d_0.w_0','conv2d_1.w_0','conv2d_2.w_0','conv2d_3.w_0','conv2d_4.w_0','conv2d_5.w_0','conv2d_6.w_0','conv2d_7.w_0','conv2d_8.w_0'],
['conv2d_9.w_0','conv2d_10.w_0','conv2d_11.w_0','conv2d_12.w_0','conv2d_13.w_0','conv2d_14.w_0','conv2d_15.w_0'],
['conv2d_16.w_0','conv2d_17.w_0','conv2d_18.w_0','conv2d_19.w_0','conv2d_20.w_0','conv2d_21.w_0'],
['conv2d_22.w_0','conv2d_23.w_0','conv2d_24.w_0','conv2d_25.w_0','conv2d_26.w_0'],
['conv2d_27.w_0','conv2d_28.w_0','conv2d_29.w_0','conv2d_30.w_0'],
['conv2d_32.w_0','conv2d_34.w_0','conv2d_35.w_0','conv2d_37.w_0','conv2d_38.w_0','conv2d_39.w_0'],
['conv2d_31.w_0'],
['conv2d_33.w_0','conv2d_36.w_0','conv2d_40.w_0','conv2d_41.w_0'],
['conv2d_42.w_0'],
['conv2d_44.w_0','conv2d_47.w_0','conv2d_51.w_0','conv2d_52.w_0','conv2d_53.w_0','conv2d_54.w_0','conv2d_55.w_0','conv2d_56.w_0','conv2d_57.w_0','conv2d_58.w_0'],
['conv2d_43.w_0','conv2d_45.w_0','conv2d_46.w_0','conv2d_49.w_0','conv2d_48.w_0','conv2d_50.w_0'],]
\ No newline at end of file
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import sys
import numpy as np
import argparse
import paddle
from paddleslim.common import load_config, load_onnx_model
from paddleslim.quant import quant_post_static
from paddleslim.quant import quant_recon_static
from dataset import COCOTrainDataset
def argsparser():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
'--config_path',
type=str,
default=None,
help="path of post training quantization config.",
required=True)
parser.add_argument(
'--save_dir',
type=str,
default='ptq_out',
help="directory to save compressed model.")
parser.add_argument(
'--devices',
type=str,
default='gpu',
help="which device used to compress.")
parser.add_argument(
'--algo', type=str, default='avg', help="post quant algo.")
parser.add_argument(
'--round_type', type=str, default='adaround', help="round type.")
parser.add_argument('--gpu', type=int, default=0, help='gpu index')
parser.add_argument(
'--recon_level',
type=str,
default='layer-wise',
help='reconstruction level')
parser.add_argument(
'--simulate_activation_quant',
type=bool,
default=False,
help='simulate activation quant')
return parser
def main():
global config
config = load_config(FLAGS.config_path)
input_name = 'x2paddle_image_arrays' if config[
'arch'] == 'YOLOv6' else 'x2paddle_images'
dataset = COCOTrainDataset(
dataset_dir=config['dataset_dir'],
image_dir=config['val_image_dir'],
anno_path=config['val_anno_path'],
input_name=input_name)
train_loader = paddle.io.DataLoader(
dataset, batch_size=1, shuffle=True, drop_last=True, num_workers=0)
place = paddle.CUDAPlace(
FLAGS.gpu) if FLAGS.devices == 'gpu' else paddle.CPUPlace()
exe = paddle.static.Executor(place)
# since the type pf model converted from pytorch is onnx,
# use load_onnx_model firstly and rename the model_dir
load_onnx_model(config["model_dir"])
inference_model_path = config["model_dir"].rstrip().rstrip(
'.onnx') + '_infer'
quant_recon_static(
executor=exe,
model_dir=inference_model_path,
quantize_model_path=FLAGS.save_dir,
data_loader=train_loader,
model_filename='model.pdmodel',
params_filename='model.pdiparams',
batch_size=32,
batch_nums=10,
algo=FLAGS.algo,
hist_percent=0.999,
is_full_quantize=False,
bias_correction=False,
onnx_format=False,
weight_quantize_type='channel_wise_abs_max',
recon_level=FLAGS.recon_level,
simulate_activation_quant=FLAGS.simulate_activation_quant,
regions=config['regions'],
region_weights_names=config['region_weights_names'],
skip_tensor_list=config['skip_tensor_list']
if 'skip_tensor_list' in config else None,
epochs=20,
lr=0.1)
if __name__ == '__main__':
paddle.enable_static()
parser = argsparser()
FLAGS = parser.parse_args()
assert FLAGS.devices in ['cpu', 'gpu', 'xpu', 'npu']
paddle.set_device(FLAGS.devices)
main()
...@@ -26,6 +26,7 @@ try: ...@@ -26,6 +26,7 @@ try:
from .quanter import quant_aware, convert, quant_post_static, quant_post_dynamic from .quanter import quant_aware, convert, quant_post_static, quant_post_dynamic
from .quanter import quant_post, quant_post_only_weight from .quanter import quant_post, quant_post_only_weight
from .quant_aware_with_infermodel import quant_aware_with_infermodel, export_quant_infermodel from .quant_aware_with_infermodel import quant_aware_with_infermodel, export_quant_infermodel
from .reconstruction_quantization import quant_recon_static
if platform.system().lower() == 'linux': if platform.system().lower() == 'linux':
from .post_quant_hpo import quant_post_hpo from .post_quant_hpo import quant_post_hpo
else: else:
......
...@@ -813,4 +813,4 @@ def pact(x, name=None): ...@@ -813,4 +813,4 @@ def pact(x, name=None):
def get_pact_optimizer(): def get_pact_optimizer():
return paddle.fluid.optimizer.MomentumOptimizer(0.0001, 0.9) return paddle.fluid.optimizer.MomentumOptimizer(0.0001, 0.9)
\ No newline at end of file
...@@ -22,15 +22,15 @@ from models import MobileNet ...@@ -22,15 +22,15 @@ from models import MobileNet
from layers import conv_bn_layer from layers import conv_bn_layer
import paddle.dataset.mnist as reader import paddle.dataset.mnist as reader
import numpy as np import numpy as np
from paddle.fluid.contrib.slim.quantization import PostTrainingQuantization from paddleslim.quant import quant_recon_static
from paddleslim.quant.rounding_optimizer import RoundingOptimizer
class TestRoundingOptimizer(StaticCase): class TestRoundingOptimizer(StaticCase):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(TestRoundingOptimizer, self).__init__(*args, **kwargs) super(TestRoundingOptimizer, self).__init__(*args, **kwargs)
paddle.enable_static() paddle.enable_static()
self._gen_model() self._gen_model()
def _gen_model(self): def _gen_model(self):
image = paddle.static.data( image = paddle.static.data(
name='image', shape=[None, 1, 28, 28], dtype='float32') name='image', shape=[None, 1, 28, 28], dtype='float32')
...@@ -52,13 +52,15 @@ class TestRoundingOptimizer(StaticCase): ...@@ -52,13 +52,15 @@ class TestRoundingOptimizer(StaticCase):
) else paddle.CPUPlace() ) else paddle.CPUPlace()
exe = paddle.static.Executor(place) exe = paddle.static.Executor(place)
exe.run(paddle.static.default_startup_program()) exe.run(paddle.static.default_startup_program())
def transform(x): def transform(x):
return np.reshape(x, [1, 28, 28]) return np.reshape(x, [1, 28, 28])
train_dataset = paddle.vision.datasets.MNIST( train_dataset = paddle.vision.datasets.MNIST(
mode='train', backend='cv2', transform=transform) mode='train', backend='cv2', transform=transform)
test_dataset = paddle.vision.datasets.MNIST( test_dataset = paddle.vision.datasets.MNIST(
mode='test', backend='cv2', transform=transform) mode='test', backend='cv2', transform=transform)
train_loader = paddle.io.DataLoader( self.train_loader = paddle.io.DataLoader(
train_dataset, train_dataset,
places=place, places=place,
feed_list=[image, label], feed_list=[image, label],
...@@ -71,15 +73,18 @@ class TestRoundingOptimizer(StaticCase): ...@@ -71,15 +73,18 @@ class TestRoundingOptimizer(StaticCase):
feed_list=[image, label], feed_list=[image, label],
batch_size=64, batch_size=64,
return_list=False) return_list=False)
def sample_generator_creator(): def sample_generator_creator():
def __reader__(): def __reader__():
for data in test_dataset: for data in test_dataset:
image, label = data image, label = data
yield image, label yield image, label
return __reader__ return __reader__
def train(program): def train(program):
iter = 0 iter = 0
for data in train_loader(): for data in self.train_loader():
cost, top1, top5 = exe.run( cost, top1, top5 = exe.run(
program, program,
feed=data, feed=data,
...@@ -89,6 +94,7 @@ class TestRoundingOptimizer(StaticCase): ...@@ -89,6 +94,7 @@ class TestRoundingOptimizer(StaticCase):
print( print(
'train iter={}, avg loss {}, acc_top1 {}, acc_top5 {}'. 'train iter={}, avg loss {}, acc_top1 {}, acc_top5 {}'.
format(iter, cost, top1, top5)) format(iter, cost, top1, top5))
train(main_prog) train(main_prog)
paddle.fluid.io.save_inference_model( paddle.fluid.io.save_inference_model(
dirname='./test_rounding_optimizer', dirname='./test_rounding_optimizer',
...@@ -98,55 +104,59 @@ class TestRoundingOptimizer(StaticCase): ...@@ -98,55 +104,59 @@ class TestRoundingOptimizer(StaticCase):
executor=exe, executor=exe,
model_filename='model', model_filename='model',
params_filename='params') params_filename='params')
self.post_training_quantization = PostTrainingQuantization(
exe, self.data_loader = sample_generator_creator()
'./test_rounding_optimizer',
sample_generator=sample_generator_creator(), self._regions = [['image', 'batch_norm_26.tmp_4']]
model_filename='model', self._region_weights_names = [[
params_filename='params', 'conv1_weights', 'conv2_1_dw_weights', 'conv2_1_sep_weights',
batch_nums=10, 'conv2_2_dw_weights', 'conv2_2_sep_weights', 'conv3_1_dw_weights',
algo='abs_max', 'conv3_1_sep_weights', 'conv3_2_dw_weights', 'conv3_2_sep_weights',
bias_correction=True) 'conv4_1_dw_weights', 'conv4_1_sep_weights', 'conv4_2_dw_weights',
'conv4_2_sep_weights', 'conv5_1_dw_weights', 'conv5_1_sep_weights',
self.post_training_quantization._load_model_data() 'conv5_2_dw_weights', 'conv5_2_sep_weights', 'conv5_3_dw_weights',
self.post_training_quantization._collect_target_varnames() 'conv5_3_sep_weights', 'conv5_4_dw_weights', 'conv5_4_sep_weights',
self.post_training_quantization._set_activation_persistable() 'conv5_5_dw_weights', 'conv5_5_sep_weights', 'conv5_6_dw_weights',
for data in self.post_training_quantization._data_loader(): 'conv5_6_sep_weights', 'conv6_dw_weights', 'conv6_sep_weights'
self.post_training_quantization._executor.run(program=self.post_training_quantization._program, ]]
feed=data,
fetch_list=self.post_training_quantization._fetch_list,
return_numpy=False,
scope=self.post_training_quantization._scope)
self.post_training_quantization._sampling()
self.post_training_quantization._reset_activation_persistable()
self._blocks= [['image','batch_norm_26.tmp_4']]
self._block_weights_names= [['conv1_weights', 'conv2_1_dw_weights', 'conv2_1_sep_weights', 'conv2_2_dw_weights', 'conv2_2_sep_weights', 'conv3_1_dw_weights', 'conv3_1_sep_weights','conv3_2_dw_weights','conv3_2_sep_weights'
,'conv4_1_dw_weights','conv4_1_sep_weights','conv4_2_dw_weights','conv4_2_sep_weights','conv5_1_dw_weights','conv5_1_sep_weights','conv5_2_dw_weights','conv5_2_sep_weights','conv5_3_dw_weights','conv5_3_sep_weights','conv5_4_dw_weights','conv5_4_sep_weights','conv5_5_dw_weights','conv5_5_sep_weights','conv5_6_dw_weights','conv5_6_sep_weights','conv6_dw_weights','conv6_sep_weights']]
def test_qdrop(self): def test_qdrop(self):
rounding_optimizer = RoundingOptimizer( place = paddle.CUDAPlace(0) if paddle.is_compiled_with_cuda(
data_loader=self.post_training_quantization._data_loader, ) else paddle.CPUPlace()
fp32_program=self.post_training_quantization._program, exe = paddle.static.Executor(place)
feed_list=self.post_training_quantization._feed_list, quant_recon_static(
fetch_list=self.post_training_quantization._fetch_list, exe,
exe=self.post_training_quantization._executor, './test_rounding_optimizer',
scope=self.post_training_quantization._scope, quantize_model_path='rsq_out',
place=self.post_training_quantization._place, sample_generator=self.data_loader,
quantized_op_pairs=self.post_training_quantization._quantized_op_pairs, model_filename='model',
weight_quantize_type=self.post_training_quantization._weight_quantize_type, params_filename='params',
scale_dict=self.post_training_quantization._quantized_threshold, batch_nums=10,
blocks=self._blocks, algo='abs_max',
block_weights_names=self._block_weights_names, regions=self._regions,
round_type='qdrop', region_weights_names=self._region_weights_names,
num_iterations=self.post_training_quantization._batch_nums, recon_level='region-wise',
lr=self.post_training_quantization._learning_rate, simulate_activation_quant=True)
bias_correction=self.post_training_quantization._bias_correction,
epochs=10, def test_qdrop(self):
) place = paddle.CUDAPlace(0) if paddle.is_compiled_with_cuda(
rounding_optimizer._run() ) else paddle.CPUPlace()
rounding_optimizer._get_layers() exe = paddle.static.Executor(place)
quant_recon_static(
exe,
'./test_rounding_optimizer',
quantize_model_path='rsq_out',
sample_generator=self.data_loader,
model_filename='model',
params_filename='params',
batch_nums=10,
algo='KL',
regions=self._regions,
region_weights_names=self._region_weights_names,
recon_level='layer-wise',
simulate_activation_quant=True,
bias_correction=True)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册