class_docstr: FeCAMClassifier
  
  Similar to NCM but uses malahanobis distance instead of l2 distance
  
  This approach has been proposed for continual learning in
  "FeCAM: Exploiting the Heterogeneity of Class Distributions
  in Exemplar-Free Continual Learning" Goswami et. al.
  (Neurips 2023)
  
  This requires the storage of full per-class covariance matrices
code: def _shrink_cov(self, cov):
      diag_mean = torch.mean(torch.diagonal(cov))
      off_diag = cov.clone()
      off_diag.fill_diagonal_(0.0)
      mask = off_diag != 0.0
      off_diag_mean = (off_diag * mask).sum() / mask.sum()
      iden = torch.eye(cov.shape[0]).to(cov.device)
      cov_ = (
          cov
          + (self.shrink1 * diag_mean * iden)
          + (self.shrink2 * off_diag_mean * (1 - iden))
      )
      return cov_
  
imports: import copy
  from typing import Dict
  import numpy
  import torch
  import torch.nn.functional
  import tqdm
  from torch import Tensor, nn
  from avalanche.models import DynamicModule
label_desc: Use image node_id 6 for calling the FeCAMClassifier obj's underlying member method code with example usage: obj._shrink_cov(cov) and returns: cov_