(self, graph: BaseGraph, dataloader: Iterable,
executor: BaseGraphExecutor, calib_steps: int, collate_fn: Callable, **kwargs)
| 226 | self.name = 'PPQ ReCalibration For Computing Op Pass' |
| 227 | |
| 228 | def optimize(self, graph: BaseGraph, dataloader: Iterable, |
| 229 | executor: BaseGraphExecutor, calib_steps: int, collate_fn: Callable, **kwargs) -> None: |
| 230 | self._collate_fn = collate_fn |
| 231 | self._calib_steps = calib_steps |
| 232 | assert calib_steps >= 8, 'Insufficient Calibration Detected, to better quantize your network, '\ |
| 233 | 'more calibration steps is demonded, we strongly recommend you to prepare more calibration data '\ |
| 234 | 'and more calibration steps is preferred here. (at least 8)' |
| 235 | |
| 236 | assert calib_steps <= 512, 'Calibration steps is too large, ppq is capable for quantizing your network within 32-128 '\ |
| 237 | 'calibration steps. More calibraiton steps will greatly delay ppq\'s calibration procedure. '\ |
| 238 | 'Reset your calib_steps parameter please.' |
| 239 | |
| 240 | hooks = {} |
| 241 | for operation in tqdm(graph.topological_sort(), |
| 242 | desc='Collecting Observer For Computing Ops'): |
| 243 | |
| 244 | if not isinstance(operation, QuantableOperation) or not operation.is_computing_op: continue |
| 245 | output_cfg = operation.config.output_quantization_config[0] |
| 246 | master_cfg, master_operation, master_var = output_cfg, operation, operation.outputs[0] |
| 247 | |
| 248 | observe_table = {} |
| 249 | # to check if all input data is greater than 0 |
| 250 | # we only need a basic observer here |
| 251 | if operation.inputs[0].name in graph.inputs: |
| 252 | input_cfg = operation.config.input_quantization_config[0] |
| 253 | sym_input_cfg = TensorQuantizationConfig( |
| 254 | policy=QuantizationPolicy( |
| 255 | QuantizationProperty.SYMMETRICAL + |
| 256 | QuantizationProperty.LINEAR + |
| 257 | QuantizationProperty.PER_TENSOR |
| 258 | ), |
| 259 | rounding=input_cfg.rounding, |
| 260 | num_of_bits=input_cfg.num_of_bits, |
| 261 | quant_min=input_cfg.quant_min, |
| 262 | quant_max=input_cfg.quant_max, |
| 263 | scale=None, |
| 264 | offset=None, |
| 265 | observer_algorithm='Minmax', |
| 266 | detail={'consumer': input_cfg} |
| 267 | ) |
| 268 | observe_table.update({input_cfg : TensorObserverFactroy.build_observer(operation.inputs[0], sym_input_cfg)}) |
| 269 | |
| 270 | # only consider overlapped by relu/clip activation here |
| 271 | downstream_ops = graph.get_downstream_operations(operation) |
| 272 | if len(downstream_ops) == 1 and downstream_ops[0].type in {'Relu', 'Clip'}\ |
| 273 | and isinstance(downstream_ops[0], QuantableOperation): |
| 274 | if len(observe_table) > 0: |
| 275 | hooks[operation.name] = CalibrationHook(operation, observe_table) |
| 276 | observe_table = {} |
| 277 | master_cfg = downstream_ops[0].config.output_quantization_config[0] |
| 278 | master_operation = downstream_ops[0] |
| 279 | master_var = downstream_ops[0].outputs[0] |
| 280 | |
| 281 | master_cfg_per_channel = TensorQuantizationConfig( |
| 282 | policy=QuantizationPolicy( |
| 283 | QuantizationProperty.SYMMETRICAL + |
| 284 | QuantizationProperty.LINEAR + |
| 285 | QuantizationProperty.PER_CHANNEL |
nothing calls this directly
no test coverage detected