class_docstr: INC Custom strategy definition
class_docstr_tok: ["INC","Custom","strategy","definition"]
code: def next_tune_cfg(self):
      FALLBACK_DTYPE = "fp32"
  
      # creating base configuration - all nodes are quantized and calibrated with minmax algorithm
      best_cfg = {}
      best_cfg["calib_iteration"] = int(
          self.calib_iter[0]
      )  # number of batches for calibration
      best_cfg["calib_sampling_size"] = int(
          self.calib_sampling_size[0]
      )  # number of samples for calibration (multiplicity of batch)
      nodes_cfg = OrderedDict()
      nodes_cfg_idx = {}
      for node_key, cfgs in self.opwise_tune_cfgs.items():
          for i, cfg in enumerate(cfgs):
              if cfg["activation"]["algorithm"] == "minmax":
                  nodes_cfg_idx[node_key] = i
                  break
          nodes_cfg[node_key] = cfg
      best_cfg["op"] = nodes_cfg
  
      yield best_cfg
  
      # If fully quantized model does not meet the requirements, we proceed to exclude some nodes
  
      # Collecting tensors from the original model - expected tensors
      node_list = [
          op_name for (op_name, op_type) in best_cfg["op"].keys()
      ]
      f32_tensors = self.adaptor.inspect_tensor(
          self.model, self.calib_dataloader, node_list, [1]
      )
      f32_tensors = f32_tensors["activation"][0]
  
      # Collecting tensors from the fully quantized model
      q_tensors = self.get_qtensors(best_cfg, node_list)
      approx_errors = get_approx_errors(f32_tensors, q_tensors)
  
      # best_cfg['op'] is an OrderedDict, which order of elements should correspond to their
      # order in the computational graph
      for node_key, cfg in best_cfg["op"].items():
          # Node's key in INC is its name + its operator
          node_name, node_op = node_key
          # Checking what configuration options are available for this particular node
          capabilities = self.opwise_tune_space[node_key]["activation"][
              "dtype"
          ]
          # If a particular node can be excluded from quanrtization ('fp32' in capabilities)
          # and current error is bigger than threshold value, we check what accuracy improvement
          # would be achieved by this exclusion
          if (
              FALLBACK_DTYPE in capabilities
              and approx_errors[node_name] > 0.06
          ):
              original_dtype = cfg["activation"]["dtype"]
              cfg["activation"][
                  "dtype"
              ] = FALLBACK_DTYPE  # Exclude the node from quantization
  
              # Collecting tensors for a new configuration with the current node excluded
              q_tensors = self.get_qtensors(best_cfg, node_list)
              # Calculating errors for the new configuration
              new_approx_errors = get_approx_errors(
                  f32_tensors, q_tensors
              )
              # Calculating error differences for every node in a model
              err_diffs = {}
              for tensor_node_name in new_approx_errors.keys():
                  diff = (
                      approx_errors[tensor_node_name]
                      - new_approx_errors[tensor_node_name]
                  )
                  err_diffs[tensor_node_name] = diff
              err_diffs_arr = np.array(list(err_diffs.values()))
  
              # If the sum of errors on the following layers is greater than the threshold value we
              # keep the node excluded
              threshold_sum_error_layers = err_diffs_arr.size * 0.01
              if err_diffs_arr.sum() >= threshold_sum_error_layers:
                  before = approx_errors
                  after = approx_errors.copy()
                  after.update(new_approx_errors)
                  if plot_operator_influence:
                      import matplotlib.pyplot as plt
  
                      plt.figure()
                      plt.plot(
                          before.values(),
                          marker="o",
                          markersize=2.5,
                          label="Before",
                      )
                      plt.plot(
                          after.values(),
                          marker="o",
                          markersize=2.5,
                          label="After",
                      )
                      plt.ylabel("Relative error")
                      plt.xlabel("Layer")
                      plt.legend()
                      plt.savefig(f"{node_name}_error.png")
  
                  approx_errors.update(new_approx_errors)
                  nodes_cfg_idx.pop(
                      node_key
                  )  # Mark node as not quantizable
              else:
                  cfg["activation"]["dtype"] = original_dtype
  
      yield best_cfg
  
      # Choosing calibration algorithm (kl or minmax) for every node which was not excluded from quantization
      for cfg in self.bayesian_configurations(best_cfg, nodes_cfg_idx):
          yield cfg
  
file_path: gluon-nlp/scripts/question_answering/custom_strategy.py
imports: import copy
  import numpy
  from collections import OrderedDict
  from neural_compressor.strategy.strategy import TuneStrategy, strategy_registry
label_desc: Use image node_id 3 for calling the MyCustomTuneStrategy obj's underlying member method code with example usage: obj.next_tune_cfg() without return types