code: def quantize_net(
      network,
      quantized_dtype="auto",
      quantize_mode="full",
      quantize_granularity="tensor-wise",
      exclude_layers=None,
      exclude_layers_match=None,
      exclude_operators=None,
      calib_data=None,
      data_shapes=None,
      calib_mode="none",
      num_calib_batches=None,
      device=cpu(),
      LayerOutputCollector=None,
      logger=None,
  ):
      """User-level API for Gluon users to generate a quantized SymbolBlock from a FP32 HybridBlock w/ or w/o calibration.
      The backend quantized operators are only enabled for Linux systems. Please do not run
      inference using the quantized models on Windows for now.
  
      Parameters
      ----------
      network : Gluon HybridBlock
          Defines the structure of a neural network for FP32 data types.
      quantized_dtype : str
          The quantized destination type for input data. Currently support 'int8'
          , 'uint8' and 'auto'. 'auto' means automatically select output type according to calibration result.
          Default value is 'int8'.
      quantize_mode : str
          The mode that quantization pass to apply. Support 'full' and 'smart'.
          'full' means quantize all operator if possible.
          'smart' means quantization pass will smartly choice which operator should be quantized.
      quantize_granularity: str
          The granularity of quantization, currently supports 'tensor-wise' and 'channel-wise'
          quantization. The default value is 'tensor-wise'.
      exclude_layers : list of strings
          A list of strings representing the names of the symbols that users want to excluding
      exclude_layers_match : list of strings
          A list of strings wildcard matching the names of the symbols that users want to excluding
          from being quantized.
      exclude_operators : list of strings
          A list of strings representing the names of the operators that users want to excluding
      calib_data : gluon.DataLoader
          A iterable data loading object.
      data_shapes : list of DataDesc or list of tuple
          A list of data shapes. Required if calib_data is not provided. In case of tuples,
          the names of inputs are generated.
      calib_mode : str
          If calib_mode='none', no calibration will be used and the thresholds for
          requantization after the corresponding layers will be calculated at runtime by
          calling min and max operators. The quantized models generated in this
          mode are normally 10-20% slower than those with calibrations during inference.
          If calib_mode='naive', the min and max values of the layer outputs from a calibration
          dataset will be directly taken as the thresholds for quantization.
          If calib_mode='entropy' (default mode), the thresholds for quantization will be
          derived such that the KL divergence between the distributions of FP32 layer outputs and
          quantized layer outputs is minimized based upon the calibration dataset.
          If calib_mode='custom', the provided LayerOutputCollector will be used to determine
          the thresholds for quantization. For more information refer to CalibrationCollector
          documentation.
      num_calib_batches : int or None
          The maximum number of batches that user would like to use for calibration. If not provided,
          the whole calibration dataset will be used.
      device : Device
          Defines the device that users want to run forward propagation on the calibration
          dataset for collecting layer output statistics. Currently, only supports single device.
      LayerOutputCollector : subclass of CalibrationCollector
          For `custom` calibration method usage.
          Passed object's include_layers attribute will be feed with names of layers which needs calibration
      logger : Object
          A logging object for printing information during the process of quantization.
  
      Returns
      -------
      network : Gluon SymbolBlock
          Defines the structure of a neural network for INT8 data types.
      """
      from ..gluon import SymbolBlock
  
      if device != mx.cpu():
          raise ValueError(
              "Quantization currently supports only CPU device"
          )
      backend = "ONEDNN_QUANTIZE"
  
      network.hybridize(static_alloc=False, static_shape=False)
      data_types = None
      if data_shapes is None:
          if calib_data is None:
              raise ValueError(
                  "At least one of data_shapes or calib_data has to be provided."
              )
  
          if isinstance(calib_data, mx.gluon.data.DataLoader):
              x = iter(calib_data)
              batch = next(x)
              if isinstance(batch, list):
                  data_shapes = _multilist_iterator(
                      batch, lambda x: x.shape
                  )
                  data_types = _multilist_iterator(
                      batch, lambda x: x.dtype
                  )
              else:
                  data_shapes = [batch.shape]
                  data_types = [batch.dtype]
          else:
              raise ValueError(
                  "calib_data expects mx.gluon.data.DataLoader"
              )
  
      if data_types is None:
          data_types = _multilist_iterator(
              data_shapes, lambda x: mx_real_t
          )
  
      data_descs = _generate_list_of_data_desc(data_shapes, data_types)
  
      num_inputs = len(data_descs)
      data_nd = []
      arr_fn = mx.np if is_np_array() else mx.nd
      data_nd = _multilist_iterator(
          data_descs,
          lambda d, F=arr_fn: F.zeros(shape=d.shape, dtype=d.dtype),
      )
  
      while True:
          try:
              network(*data_nd)
          except (ValueError, TypeError) as err:
              if logger:
                  logger.warning(err)
                  logger.warning(
                      "Deduced input data descriptors failed to run forward pass."
                      " Trying again with one less input."
                  )
              del data_nd[-1]
              num_inputs -= 1
              data_shapes = [b.shape for b in data_nd]
              data_types = [b.dtype for b in data_nd]
              data_descs = _generate_list_of_data_desc(
                  data_shapes, data_types
              )
              continue
          else:
              break
  
      symnet, params = network.export(None)
      symnet = symnet.optimize_for(backend=backend)
  
      if is_np_array():
          symnet = symnet.as_np_ndarray()
  
      args, auxs = dict(), dict()
      for k, v in params.items():
          ptype, pname = k[:3], k[4:]
          if ptype == "arg":
              args[pname] = v
          else:
              auxs[pname] = v
  
      if exclude_layers is None:
          exclude_layers = []
      if exclude_layers_match is None:
          exclude_layers_match = []
      if exclude_operators is None:
          exclude_operators = []
      for name_match in exclude_layers_match:
          for layers in list(symnet.get_internals()):
              if layers.name.find(name_match) != -1:
                  exclude_layers.append(layers.name)
      if logger:
          logger.info(
              f"These layers have been excluded {exclude_layers}"
          )
  
      qsym, qarg_params, aux_params, collector, _ = quantize_graph(
          sym=symnet,
          arg_params=args,
          aux_params=auxs,
          device=device,
          excluded_sym_names=exclude_layers,
          excluded_op_names=exclude_operators,
          calib_mode=calib_mode,
          quantized_dtype=quantized_dtype,
          quantize_mode=quantize_mode,
          quantize_granularity=quantize_granularity,
          LayerOutputCollector=LayerOutputCollector,
          logger=logger,
      )
  
      if calib_mode is not None and calib_mode != "none":
          if not isinstance(device, Device):
              raise ValueError(
                  f"currently only supports single device, while received {str(device)}"
              )
          if calib_data is None:
              raise ValueError(
                  f"calib_data must be provided when calib_mode={calib_mode}"
              )
          if calib_mode in ["naive", "entropy", "custom"]:
              inputs = _multilist_iterator(
                  data_descs, lambda dd: mx.sym.var(dd.name)
              )
              calib_net = SymbolBlock(symnet, inputs)
              for k, v in calib_net.collect_params().items():
                  v.grad_req = "null"
  
              calib_net.load_dict(
                  params, cast_dtype=True, dtype_source="saved"
              )
              calib_net.hybridize(
                  static_alloc=False, static_shape=False
              )
              num_batches = _collect_layer_statistics(
                  calib_net,
                  calib_data,
                  collector,
                  num_inputs,
                  num_calib_batches,
                  logger,
              )
  
              if logger:
                  logger.info(
                      f"Collected layer output values from FP32 model using {num_batches} batches"
                  )
  
              qsym, qarg_params, aux_params = calib_graph(
                  qsym=qsym,
                  arg_params=args,
                  aux_params=auxs,
                  collector=collector,
                  calib_mode=calib_mode,
                  logger=logger,
              )
          else:
              raise ValueError(
                  "calib_mode has to be one of: naive, entropy, custom"
              )
      elif calib_mode is not None and calib_mode == "none":
          inputs = _multilist_iterator(
              data_descs, lambda dd: mx.sym.var(dd.name)
          )
  
      net = SymbolBlock(qsym, inputs)
      for k, v in net.collect_params().items():
          v.grad_req = "null"
  
      all_params = {
          (f"arg:{k}"): v.as_in_context(cpu())
          for k, v in qarg_params.items()
      }
      all_params.update(
          {
              (f"aux:{k}"): v.as_in_context(cpu())
              for k, v in aux_params.items()
          }
      )
      net.load_dict(all_params, cast_dtype=True, dtype_source="saved")
      net.optimize_for(data_nd, backend=backend, skip_infer=True)
      return net
  
imports: import abc
  import ctypes
  import logging
  import os
  import warnings
  import numpy
  import mxnet
  from ..base import _LIB, check_call, py_str
  from ..base import c_array, c_str, mx_uint, mx_real_t, c_str_array
  from ..base import SymbolHandle
  from ..symbol import Symbol
  from ..None import ndarray
  from ..io import DataDesc
  from ..device import cpu, Device
  from ..util import is_np_array, wrap_ctx_to_device_func
label_desc: Use image node_id 11 for calling a global function with example usage: quantize_net(network, quantized_dtype, quantize_mode, quantize_granularity, exclude_layers, exclude_layers_match, exclude_operators, calib_data, data_shapes, calib_mode, num_calib_batches, device, LayerOutputCollector, logger) and returns: net