docstr: This function analyze the sensitivity to pruning for
  each conv layer in the target model.
  If start and end are not set, we analyze all the conv
  layers by default. Users can specify several layers to
  analyze or parallelize the analysis process easily through
  the start and end parameter.
  
  Parameters
  ----------
  val_args : list
      args for the val_function
  val_kwargs : dict
      kwargs for the val_funtion
  specified_layers : list
      list of layer names to analyze sensitivity.
      If this variable is set, then only analyze
      the conv layers that specified in the list.
      User can also use this option to parallelize
      the sensitivity analysis easily.
  Returns
  -------
  sensitivities : dict
      dict object that stores the trajectory of the
      accuracy/loss when the prune ratio changes
docstr_tok: ["This","function","analyze","the","sensitivity","to","pruning","for","each","conv","layer","in","the","target","model",".","If","start","and","end","are","not","set",",","we","analyze","all","the","conv","layers","by","default",".","Users","can","specify","several","layers","to","analyze","or","parallelize","the","analysis","process","easily","through","the","start","and","end","parameter",".","Parameters","--","--","--","--","--","val_args",":","list","args","for","the","val_function","val_kwargs",":","dict","kwargs","for","the","val_funtion","specified_layers",":","list","list","of","layer","names","to","analyze","sensitivity",".","If","this","variable","is","set",",","then","only","analyze","the","conv","layers","that","specified","in","the","list",".","User","can","also","use","this","option","to","parallelize","the","sensitivity","analysis","easily",".","Returns","--","--","--","-","sensitivities",":","dict","dict","object","that","stores","the","trajectory","of","the","accuracy\/loss","when","the","prune","ratio","changes"]
code: def analysis(
      self, val_args=None, val_kwargs=None, specified_layers=None
  ):
      """
      This function analyze the sensitivity to pruning for
      each conv layer in the target model.
      If start and end are not set, we analyze all the conv
      layers by default. Users can specify several layers to
      analyze or parallelize the analysis process easily through
      the start and end parameter.
  
      Parameters
      ----------
      val_args : list
          args for the val_function
      val_kwargs : dict
          kwargs for the val_funtion
      specified_layers : list
          list of layer names to analyze sensitivity.
          If this variable is set, then only analyze
          the conv layers that specified in the list.
          User can also use this option to parallelize
          the sensitivity analysis easily.
      Returns
      -------
      sensitivities : dict
          dict object that stores the trajectory of the
          accuracy/loss when the prune ratio changes
      """
      if val_args is None:
          val_args = []
      if val_kwargs is None:
          val_kwargs = {}
      # Get the original validation metric(accuracy/loss) before pruning
      # Get the accuracy baseline before starting the analysis.
      self.ori_metric = self.val_func(*val_args, **val_kwargs)
      namelist = list(self.target_layer.keys())
      if specified_layers is not None:
          # only analyze several specified conv layers
          namelist = list(
              filter(lambda x: x in specified_layers, namelist)
          )
      for name in namelist:
          self.sensitivities[name] = {}
          for sparsity in self.sparsities:
              # here the sparsity is the relative sparsity of the
              # the remained weights
              # Calculate the actual prune ratio based on the already pruned ratio
              real_sparsity = (
                  1.0 - self.already_pruned[name]
              ) * sparsity + self.already_pruned[name]
              # TODO In current L1/L2 Filter Pruner, the 'op_types' is still necessary
              # I think the L1/L2 Pruner should specify the op_types automaticlly
              # according to the op_names
              cfg = [
                  {
                      "sparsity": real_sparsity,
                      "op_names": [name],
                      "op_types": ["Conv2d"],
                  }
              ]
              pruner = self.Pruner(self.model, cfg)
              pruner.compress()
              val_metric = self.val_func(*val_args, **val_kwargs)
              logger.info(
                  "Layer: %s Sparsity: %.2f Validation Metric: %.4f",
                  name,
                  real_sparsity,
                  val_metric,
              )
  
              self.sensitivities[name][sparsity] = val_metric
              pruner._unwrap_model()
              del pruner
              # check if the current metric meet the stop condition
              if self._need_to_stop(self.ori_metric, val_metric):
                  break
  
          # reset the weights pruned by the pruner, because the
          # input sparsities is sorted, so we donnot need to reset
          # weight of the layer when the sparsity changes, instead,
          # we only need reset the weight when the pruning layer changes.
          self.model.load_state_dict(self.ori_state_dict)
  
      return self.sensitivities
  
file_path: auptimizer/src/aup/compression/torch/utils/sensitivity_analysis.py
imports: import copy
  import csv
  import logging
  from collections import OrderedDict
  import numpy
  import torch.nn
label_desc: Use image node_id 5 for calling the SensitivityAnalysis obj's underlying member method code with example usage: obj.analysis(val_args, val_kwargs, specified_layers) and returns: self