Solve scale and offset with given min, max value. For Symmetrical Quantization, offset is set to 0. For ASymmetrical Quantization, offset is limited by [config.quant_min, config.quant_max]. Scale is limited by [scale_threshold, +inf]. Args: min_val (float): min value
(
min_val: float, max_val: float,
config: TensorQuantizationConfig,
scale_threshold: float=OBSERVER_MIN_SCALE
)
| 21 | |
| 22 | @ ppq_quant_param_computing_function |
| 23 | def minmax_to_scale_offset( |
| 24 | min_val: float, max_val: float, |
| 25 | config: TensorQuantizationConfig, |
| 26 | scale_threshold: float=OBSERVER_MIN_SCALE |
| 27 | ) -> Tuple[float, float]: |
| 28 | """ |
| 29 | Solve scale and offset with given min, max value. |
| 30 | For Symmetrical Quantization, offset is set to 0. |
| 31 | For ASymmetrical Quantization, offset is limited by [config.quant_min, config.quant_max]. |
| 32 | |
| 33 | Scale is limited by [scale_threshold, +inf]. |
| 34 | |
| 35 | Args: |
| 36 | min_val (float): min value |
| 37 | max_val (float): max value |
| 38 | config (TensorQuantizationConfig): Corresponding TQC. |
| 39 | scale_threshold (float, optional): minimum scale. |
| 40 | |
| 41 | Returns: |
| 42 | Tuple[float, float]: Solved scale and offset. |
| 43 | """ |
| 44 | if OBSERVER_MIN_SCALE_MANUL_OVERRIDE in config.detail: |
| 45 | scale_threshold = config.detail[OBSERVER_MIN_SCALE_MANUL_OVERRIDE] |
| 46 | |
| 47 | scale, offset = 1, 0 |
| 48 | if min_val > 0: min_val = 0 |
| 49 | if max_val < 0: max_val = 0 |
| 50 | |
| 51 | if config.policy.has_property(QuantizationProperty.ASYMMETRICAL): |
| 52 | range = float(max_val - min_val) |
| 53 | scale = range / (config.quant_max - config.quant_min) |
| 54 | if scale < scale_threshold and OBSERVER_WARNING: |
| 55 | ppq_warning('Numeric instability detected: ' |
| 56 | 'ppq find there is a scale value < 1e-7, ' |
| 57 | 'which probably cause numeric underflow in further computation.') |
| 58 | scale = max(scale, scale_threshold) |
| 59 | offset = ppq_numerical_round(-min_val / scale) |
| 60 | |
| 61 | elif config.policy.has_property(QuantizationProperty.SYMMETRICAL): |
| 62 | range = 2 * float(max(abs(max_val), abs(min_val))) |
| 63 | scale = range / (config.quant_max - config.quant_min) |
| 64 | if scale < scale_threshold and OBSERVER_WARNING: |
| 65 | ppq_warning('Numeric instability detected: ' |
| 66 | 'ppq find there is a scale value < 1e-7, ' |
| 67 | 'which probably cause numeric underflow in further computation.') |
| 68 | scale = max(scale, scale_threshold) |
| 69 | offset = 0 |
| 70 | |
| 71 | else: |
| 72 | raise TypeError('Tensor Min Max Observer Excepts either ASYMMETRICAL or SYMMETRICAL quantization config.') |
| 73 | if config.policy.has_property(QuantizationProperty.POWER_OF_2): |
| 74 | scale = ppq_round_to_power_of_2(scale, policy=RoundingPolicy.ROUND_UP) |
| 75 | return scale, offset |
| 76 | |
| 77 | |
| 78 | class TorchMinMaxObserver(BaseTensorObserver): |
no test coverage detected