diff --git a/paddleslim/quant/dy_quanter.py b/paddleslim/quant/dy_quanter.py new file mode 100644 index 0000000000000000000000000000000000000000..7b9463628e657e280d72a2ac888f645ff20696b5 --- /dev/null +++ b/paddleslim/quant/dy_quanter.py @@ -0,0 +1,136 @@ +# Copyright (c) 2019 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 copy +import logging + +import paddle +import paddle.fluid as fluid + +from paddle.fluid.contrib.slim.quantization import ImperativeQuantAware + +from ..common import get_logger +_logger = get_logger(__name__, level=logging.INFO) + +WEIGHT_QUANTIZATION_TYPES = [ + 'abs_max', 'channel_wise_abs_max', 'range_abs_max', + 'moving_average_abs_max' +] +WEIGHT_QUANTIZATION_TYPES_TENSORRT = ['channel_wise_abs_max'] + +ACTIVATION_QUANTIZATION_TYPES = [ + 'abs_max', 'range_abs_max', 'moving_average_abs_max' +] + +ACTIVATION_QUANTIZATION_TYPES_TENSORRT = [ + 'range_abs_max', 'moving_average_abs_max' +] + +_quant_config_default = { + # weight quantize type, default is 'channel_wise_abs_max' + 'weight_quantize_type': 'channel_wise_abs_max', + # activation quantize type, default is 'moving_average_abs_max' + 'activation_quantize_type': 'moving_average_abs_max', + # weight quantize bit num, default is 8 + 'weight_bits': 8, + # activation quantize bit num, default is 8 + 'activation_bits': 8, + # Layer of type in quantize_layer_types, will be quantized + 'quantize_layer_types': ['Conv2D', 'Linear', 'ReLU', 'Pool2D', 'LeakyReLU'], + # data type after quantization, such as 'uint8', 'int8', etc. default is 'int8' + 'dtype': 'int8', + # window size for 'range_abs_max' quantization. defaulf is 10000 + 'window_size': 10000, + # The decay coefficient of moving average, default is 0.9 + 'moving_rate': 0.9, +} + + + +def _parse_configs(user_config): + """ + check if user's configs are valid. + Args: + user_config(dict): user's config. + Return: + configs(dict): final configs will be used. + """ + + configs = copy.deepcopy(_quant_config_default) + configs.update(user_config) + + assert isinstance(configs['for_tensorrt'], bool) and isinstance( + configs['is_full_quantize'], + bool), "'for_tensorrt' and 'is_full_quantize' must both be bool'" + + # check if configs is valid + if configs['for_tensorrt']: + weight_types = WEIGHT_QUANTIZATION_TYPES_TENSORRT + activation_types = ACTIVATION_QUANTIZATION_TYPES_TENSORRT + platform = 'TensorRT' + else: + weight_types = WEIGHT_QUANTIZATION_TYPES + activation_types = WEIGHT_QUANTIZATION_TYPES + platform = 'PaddleLite' + assert configs['weight_quantize_type'] in weight_types, \ + "Unknown weight_quantize_type: {}. {} only supports {} ".format(configs['weight_quantize_type'], + platform, weight_types) + + assert configs['activation_quantize_type'] in activation_types, \ + "Unknown activation_quantize_type: {}. {} only supports {}".format(configs['activation_quantize_type'], + platform, activation_types) + + assert isinstance(configs['weight_bits'], int), \ + "weight_bits must be int value." + + assert (configs['weight_bits'] >= 1 and configs['weight_bits'] <= 16), \ + "weight_bits should be between 1 and 16." + + assert isinstance(configs['activation_bits'], int), \ + "activation_bits must be int value." + + assert (configs['activation_bits'] >= 1 and configs['activation_bits'] <= 16), \ + "activation_bits should be between 1 and 16." + + assert isinstance(configs['dtype'], str), \ + "dtype must be a str." + + assert isinstance(configs['window_size'], int), \ + "window_size must be int value, window size for 'range_abs_max' quantization, default is 10000." + + assert isinstance(configs['moving_rate'], float), \ + "moving_rate must be float value, The decay coefficient of moving average, default is 0.9." + + return configs + +def dy_quant_aware(model, + config=None, + scope=None, + for_test=False, + weight_quantize_func=None, + act_quantize_func=None, + weight_preprocess_func=None, + act_preprocess_func=None, + optimizer_func=None): + + imperative_qat = ImperativeQuantAware( + weight_quantize_type='abs_max', + activation_quantize_type='moving_average_abs_max', + quantizable_layer_type=[ + 'Conv2D', 'Linear', 'ReLU', 'Pool2D', 'LeakyReLU' + ]) + + imperative_qat.quantize(model) + + return model \ No newline at end of file