docstr: return the KFAC updates
  
  :param gradlist: ([TensorFlow Tensor]) The gradients
  :param varlist: ([TensorFlow Tensor]) The parameters
  :return: ([TensorFlow Tensor]) the update list
docstr_tok: ["return","the","KFAC","updates",":","param","gradlist",":","(","[","TensorFlow","Tensor","]",")","The","gradients",":","param","varlist",":","(","[","TensorFlow","Tensor","]",")","The","parameters",":","return",":","(","[","TensorFlow","Tensor","]",")","the","update","list"]
code: def get_kfac_precond_updates(self, gradlist, varlist):
      """
      return the KFAC updates
  
      :param gradlist: ([TensorFlow Tensor]) The gradients
      :param varlist: ([TensorFlow Tensor]) The parameters
      :return: ([TensorFlow Tensor]) the update list
      """
      v_g = 0.0
  
      assert len(self.stats) > 0
      assert len(self.stats_eigen) > 0
      assert len(self.factors) > 0
      counter = 0
  
      grad_dict = {var: grad for grad, var in zip(gradlist, varlist)}
  
      for grad, var in zip(gradlist, varlist):
          grad_reshape = False
  
          fprop_factored_fishers = self.stats[var]["fprop_concat_stats"]
          bprop_factored_fishers = self.stats[var]["bprop_concat_stats"]
  
          if (
              len(fprop_factored_fishers) + len(bprop_factored_fishers)
          ) > 0:
              counter += 1
              grad_shape = grad.get_shape()
              if len(grad.get_shape()) > 2:
                  # reshape conv kernel parameters
                  kernel_width = int(grad.get_shape()[0])
                  kernel_height = int(grad.get_shape()[1])
                  n_channels = int(grad.get_shape()[2])
                  depth = int(grad.get_shape()[3])
  
                  if (
                      len(fprop_factored_fishers) > 1
                      and self._channel_fac
                  ):
                      # reshape conv kernel parameters into tensor
                      grad = tf.reshape(
                          grad,
                          [
                              kernel_width * kernel_height,
                              n_channels,
                              depth,
                          ],
                      )
                  else:
                      # reshape conv kernel parameters into 2D grad
                      grad = tf.reshape(grad, [-1, depth])
                  grad_reshape = True
              elif len(grad.get_shape()) == 1:
                  # reshape bias or 1D parameters
  
                  grad = tf.expand_dims(grad, 0)
                  grad_reshape = True
  
              if (
                  self.stats[var]["assnBias"] is not None
              ) and not self._blockdiag_bias:
                  # use homogeneous coordinates only works for 2D grad.
                  # TODO: figure out how to factorize bias grad
                  # stack bias grad
                  var_assn_bias = self.stats[var]["assnBias"]
                  grad = tf.concat(
                      [
                          grad,
                          tf.expand_dims(grad_dict[var_assn_bias], 0),
                      ],
                      0,
                  )
  
              # project gradient to eigen space and reshape the eigenvalues
              # for broadcasting
              eig_vals = []
  
              for idx, stats in enumerate(
                  self.stats[var]["fprop_concat_stats"]
              ):
                  eigen_vectors = self.stats_eigen[stats]["Q"]
                  eigen_values = detect_min_val(
                      self.stats_eigen[stats]["e"],
                      var,
                      name="act",
                      debug=KFAC_DEBUG,
                  )
  
                  eigen_vectors, eigen_values = factor_reshape(
                      eigen_vectors,
                      eigen_values,
                      grad,
                      fac_idx=idx,
                      f_type="act",
                  )
                  eig_vals.append(eigen_values)
                  grad = gmatmul(
                      eigen_vectors,
                      grad,
                      transpose_a=True,
                      reduce_dim=idx,
                  )
  
              for idx, stats in enumerate(
                  self.stats[var]["bprop_concat_stats"]
              ):
                  eigen_vectors = self.stats_eigen[stats]["Q"]
                  eigen_values = detect_min_val(
                      self.stats_eigen[stats]["e"],
                      var,
                      name="grad",
                      debug=KFAC_DEBUG,
                  )
  
                  eigen_vectors, eigen_values = factor_reshape(
                      eigen_vectors,
                      eigen_values,
                      grad,
                      fac_idx=idx,
                      f_type="grad",
                  )
                  eig_vals.append(eigen_values)
                  grad = gmatmul(
                      grad,
                      eigen_vectors,
                      transpose_b=False,
                      reduce_dim=idx,
                  )
  
              # whiten using eigenvalues
              weight_decay_coeff = 0.0
              if var in self._weight_decay_dict:
                  weight_decay_coeff = self._weight_decay_dict[var]
                  if KFAC_DEBUG:
                      print(
                          (
                              "weight decay coeff for %s is %f"
                              % (var.name, weight_decay_coeff)
                          )
                      )
  
              if self._factored_damping:
                  if KFAC_DEBUG:
                      print(("use factored damping for %s" % var.name))
                  coeffs = 1.0
                  num_factors = len(eig_vals)
                  # compute the ratio of two trace norm of the left and right
                  # KFac matrices, and their generalization
                  if len(eig_vals) == 1:
                      damping = self._epsilon + weight_decay_coeff
                  else:
                      damping = tf.pow(
                          self._epsilon + weight_decay_coeff,
                          1.0 / num_factors,
                      )
                  eig_vals_tnorm_avg = [
                      tf.reduce_mean(tf.abs(e)) for e in eig_vals
                  ]
                  for eigen_val, e_tnorm in zip(
                      eig_vals, eig_vals_tnorm_avg
                  ):
                      eig_tnorm_neg_list = [
                          item
                          for item in eig_vals_tnorm_avg
                          if item != e_tnorm
                      ]
                      if len(eig_vals) == 1:
                          adjustment = 1.0
                      elif len(eig_vals) == 2:
                          adjustment = tf.sqrt(
                              e_tnorm / eig_tnorm_neg_list[0]
                          )
                      else:
                          eig_tnorm_neg_list_prod = reduce(
                              lambda x, y: x * y, eig_tnorm_neg_list
                          )
                          adjustment = tf.pow(
                              tf.pow(e_tnorm, num_factors - 1.0)
                              / eig_tnorm_neg_list_prod,
                              1.0 / num_factors,
                          )
                      coeffs *= eigen_val + adjustment * damping
              else:
                  coeffs = 1.0
                  damping = self._epsilon + weight_decay_coeff
                  for eigen_val in eig_vals:
                      coeffs *= eigen_val
                  coeffs += damping
  
              grad /= coeffs
  
              # project gradient back to euclidean space
              for idx, stats in enumerate(
                  self.stats[var]["fprop_concat_stats"]
              ):
                  eigen_vectors = self.stats_eigen[stats]["Q"]
                  grad = gmatmul(
                      eigen_vectors,
                      grad,
                      transpose_a=False,
                      reduce_dim=idx,
                  )
  
              for idx, stats in enumerate(
                  self.stats[var]["bprop_concat_stats"]
              ):
                  eigen_vectors = self.stats_eigen[stats]["Q"]
                  grad = gmatmul(
                      grad,
                      eigen_vectors,
                      transpose_b=True,
                      reduce_dim=idx,
                  )
  
              if (
                  self.stats[var]["assnBias"] is not None
              ) and not self._blockdiag_bias:
                  # use homogeneous coordinates only works for 2D grad.
                  # TODO: figure out how to factorize bias grad
                  # un-stack bias grad
                  var_assn_bias = self.stats[var]["assnBias"]
                  c_plus_one = int(grad.get_shape()[0])
                  grad_assn_bias = tf.reshape(
                      tf.slice(
                          grad, begin=[c_plus_one - 1, 0], size=[1, -1]
                      ),
                      var_assn_bias.get_shape(),
                  )
                  grad_assn_weights = tf.slice(
                      grad, begin=[0, 0], size=[c_plus_one - 1, -1]
                  )
                  grad_dict[var_assn_bias] = grad_assn_bias
                  grad = grad_assn_weights
  
              if grad_reshape:
                  grad = tf.reshape(grad, grad_shape)
  
              grad_dict[var] = grad
  
      if self.verbose > 1:
          print(("projecting %d gradient matrices" % counter))
  
      for grad_1, var in zip(gradlist, varlist):
          grad = grad_dict[var]
          # clipping
          if KFAC_DEBUG:
              print(("apply clipping to %s" % var.name))
              tf.Print(
                  grad,
                  [tf.sqrt(tf.reduce_sum(tf.pow(grad, 2)))],
                  "Euclidean norm of new grad",
              )
          local_vg = tf.reduce_sum(
              grad * grad_1 * (self._lr * self._lr)
          )
          v_g += local_vg
  
      # rescale everything
      if KFAC_DEBUG:
          print("apply vFv clipping")
  
      scaling = tf.minimum(1.0, tf.sqrt(self._clip_kl / v_g))
      if KFAC_DEBUG:
          scaling = tf.Print(
              scaling,
              [
                  tf.convert_to_tensor("clip: "),
                  scaling,
                  tf.convert_to_tensor(" vFv: "),
                  v_g,
              ],
          )
      with tf.control_dependencies([tf.assign(self.v_f_v, v_g)]):
          updatelist = [grad_dict[var] for var in varlist]
          for i, item in enumerate(updatelist):
              updatelist[i] = scaling * item
  
      return updatelist
  
imports: import re
  from functools import reduce
  import tensorflow
  import numpy
  from stable_baselines.acktr.kfac_utils import detect_min_val, factor_reshape, gmatmul
label_desc: Use image node_id 11 for calling the KfacOptimizer obj's underlying member method code with example usage: obj.get_kfac_precond_updates(gradlist, varlist) and returns: updatelist