class_docstr: ## Instance Normalization Layer
  
  Instance normalization layer $\text{IN}$ normalizes the input $X$ as follows:
  
  When input $X \in \mathbb{R}^{B \times C \times H \times W}$ is a batch of image representations,
  where $B$ is the batch size, $C$ is the number of channels, $H$ is the height and $W$ is the width.
  $\gamma \in \mathbb{R}^{C}$ and $\beta \in \mathbb{R}^{C}$. The affine transformation with $gamma$ and
  $beta$ are optional.
  
  $$\text{IN}(X) = \gamma
  \frac{X - \underset{H, W}{\mathbb{E}}[X]}{\sqrt{\underset{H, W}{Var}[X] + \epsilon}}
  + \beta$$
docstr: `x` is a tensor of shape `[batch_size, channels, *]`.
  `*` denotes any number of (possibly 0) dimensions.
   For example, in an image (2D) convolution this will be
  `[batch_size, channels, height, width]`
docstr_tok: ["`","x","`","is","a","tensor","of","shape","`","[","batch_size",",","channels",",","*","]","`",".","`","*","`","denotes","any","number","of","(","possibly","0",")","dimensions",".","For","example",",","in","an","image","(","2D",")","convolution","this","will","be","`","[","batch_size",",","channels",",","height",",","width","]","`"]
code: def forward(self, x: torch.Tensor):
      """
      `x` is a tensor of shape `[batch_size, channels, *]`.
      `*` denotes any number of (possibly 0) dimensions.
       For example, in an image (2D) convolution this will be
      `[batch_size, channels, height, width]`
      """
      # Keep the original shape
      x_shape = x.shape
      # Get the batch size
      batch_size = x_shape[0]
      # Sanity check to make sure the number of features is the same
      assert self.channels == x.shape[1]
  
      # Reshape into `[batch_size, channels, n]`
      x = x.view(batch_size, self.channels, -1)
  
      # Calculate the mean across last dimension
      # i.e. the means for each feature  $\mathbb{E}[x_{t,i}]$
      mean = x.mean(dim=[-1], keepdim=True)
      # Calculate the squared mean across first and last dimension;
      # i.e. the means for each feature $\mathbb{E}[(x_{t,i}^2]$
      mean_x2 = (x**2).mean(dim=[-1], keepdim=True)
      # Variance for each feature $Var[x_{t,i}] = \mathbb{E}[x_{t,i}^2] - \mathbb{E}[x_{t,i}]^2$
      var = mean_x2 - mean**2
  
      # Normalize $$\hat{x}_{t,i} = \frac{x_{t,i} - \mathbb{E}[x_{t,i}]}{\sqrt{Var[x_{t,i}] + \epsilon}}$$
      x_norm = (x - mean) / torch.sqrt(var + self.eps)
      x_norm = x_norm.view(batch_size, self.channels, -1)
  
      # Scale and shift $$y_{t,i} =\gamma_i \hat{x}_{t,i} + \beta_i$$
      if self.affine:
          x_norm = self.scale.view(1, -1, 1) * x_norm + self.shift.view(
              1, -1, 1
          )
  
      # Reshape to original and return
      return x_norm.view(x_shape)
  
file_path: annotated_deep_learning_paper_implementations/labml_nn/normalization/instance_norm/__init__.py
imports: import torch
  from torch import nn
  from labml_helpers.module import Module
label_desc: Use image node_id 2 for calling the InstanceNorm obj's underlying member method code with example usage: obj.forward(x) and returns: x_norm