class_docstr: Perceptual loss using features from pretrained deep neural networks trained. The function supports networks
  pretrained on: ImageNet that use the LPIPS approach from Zhang, et al. "The unreasonable effectiveness of deep
  features as a perceptual metric." https://arxiv.org/abs/1801.03924 ; RadImagenet from Mei, et al. "RadImageNet: An
  Open Radiologic Deep Learning Research Dataset for Effective Transfer Learning"
  https://pubs.rsna.org/doi/full/10.1148/ryai.210315 ; MedicalNet from Chen et al. "Med3D: Transfer Learning for
  3D Medical Image Analysis" https://arxiv.org/abs/1904.00625 ;
  and ResNet50 from Torchvision: https://pytorch.org/vision/main/models/generated/torchvision.models.resnet50.html .
  
  The fake 3D implementation is based on a 2.5D approach where we calculate the 2D perceptual loss on slices from all
  three axes and average. The full 3D approach uses a 3D network to calculate the perceptual loss.
  
  Args:
      spatial_dims: number of spatial dimensions.
      network_type: {``"alex"``, ``"vgg"``, ``"squeeze"``, ``"radimagenet_resnet50"``,
      ``"medicalnet_resnet10_23datasets"``, ``"medicalnet_resnet50_23datasets"``, ``"resnet50"``}
          Specifies the network architecture to use. Defaults to ``"alex"``.
      is_fake_3d: if True use 2.5D approach for a 3D perceptual loss.
      fake_3d_ratio: ratio of how many slices per axis are used in the 2.5D approach.
      cache_dir: path to cache directory to save the pretrained network weights.
      pretrained: whether to load pretrained weights. This argument only works when using networks from
          LIPIS or Torchvision. Defaults to ``"True"``.
      pretrained_path: if `pretrained` is `True`, users can specify a weights file to be loaded
          via using this argument. This argument only works when ``"network_type"`` is "resnet50".
          Defaults to `None`.
      pretrained_state_dict_key: if `pretrained_path` is not `None`, this argument is used to
          extract the expected state dict. This argument only works when ``"network_type"`` is "resnet50".
          Defaults to `None`.
docstr: Calculate perceptual loss in one of the axis used in the 2.5D approach. After the slices of one spatial axis
  is transformed into different instances in the batch, we compute the loss using the 2D approach.
  
  Args:
      input: input 5D tensor. BNHWD
      target: target 5D tensor. BNHWD
      spatial_axis: spatial axis to obtain the 2D slices.
docstr_tok: ["Calculate","perceptual","loss","in","one","of","the","axis","used","in","the","2.5D","approach",".","After","the","slices","of","one","spatial","axis","is","transformed","into","different","instances","in","the","batch",",","we","compute","the","loss","using","the","2D","approach",".","Args",":","input",":","input","5D","tensor",".","BNHWD","target",":","target","5D","tensor",".","BNHWD","spatial_axis",":","spatial","axis","to","obtain","the","2D","slices","."]
code: def _calculate_axis_loss(
      self, input: torch.Tensor, target: torch.Tensor, spatial_axis: int
  ) -> torch.Tensor:
      """
      Calculate perceptual loss in one of the axis used in the 2.5D approach. After the slices of one spatial axis
      is transformed into different instances in the batch, we compute the loss using the 2D approach.
  
      Args:
          input: input 5D tensor. BNHWD
          target: target 5D tensor. BNHWD
          spatial_axis: spatial axis to obtain the 2D slices.
      """
  
      def batchify_axis(
          x: torch.Tensor, fake_3d_perm: tuple
      ) -> torch.Tensor:
          """
          Transform slices from one spatial axis into different instances in the batch.
          """
          slices = x.float().permute((0,) + fake_3d_perm).contiguous()
          slices = slices.view(
              -1,
              x.shape[fake_3d_perm[1]],
              x.shape[fake_3d_perm[2]],
              x.shape[fake_3d_perm[3]],
          )
  
          return slices
  
      preserved_axes = [2, 3, 4]
      preserved_axes.remove(spatial_axis)
  
      channel_axis = 1
      input_slices = batchify_axis(
          x=input,
          fake_3d_perm=(spatial_axis, channel_axis)
          + tuple(preserved_axes),
      )
      indices = torch.randperm(input_slices.shape[0])[
          : int(input_slices.shape[0] * self.fake_3d_ratio)
      ].to(input_slices.device)
      input_slices = torch.index_select(
          input_slices, dim=0, index=indices
      )
      target_slices = batchify_axis(
          x=target,
          fake_3d_perm=(spatial_axis, channel_axis)
          + tuple(preserved_axes),
      )
      target_slices = torch.index_select(
          target_slices, dim=0, index=indices
      )
  
      axis_loss = torch.mean(
          self.perceptual_function(input_slices, target_slices)
      )
  
      return axis_loss
  
imports: from __future__ import annotations
  import warnings
  import torch
  import torch.nn
  from monai.utils import optional_import
  from monai.utils.enums import StrEnum
label_desc: Use image node_id 2 for calling the PerceptualLoss obj's underlying member method code with example usage: obj._calculate_axis_loss(input, target, spatial_axis) and returns: axis_loss, slices