class_docstr: ## Encoder module
docstr: :param channels: is the number of channels in the first convolution layer
  :param channel_multipliers: are the multiplicative factors for the number of channels in the
      subsequent blocks
  :param n_resnet_blocks: is the number of resnet layers at each resolution
  :param in_channels: is the number of channels in the image
  :param z_channels: is the number of channels in the embedding space
code: def __init__(
      self,
      *,
      channels: int,
      channel_multipliers: List[int],
      n_resnet_blocks: int,
      in_channels: int,
      z_channels: int,
  ):
      """
      :param channels: is the number of channels in the first convolution layer
      :param channel_multipliers: are the multiplicative factors for the number of channels in the
          subsequent blocks
      :param n_resnet_blocks: is the number of resnet layers at each resolution
      :param in_channels: is the number of channels in the image
      :param z_channels: is the number of channels in the embedding space
      """
      super().__init__()
  
      # Number of blocks of different resolutions.
      # The resolution is halved at the end each top level block
      n_resolutions = len(channel_multipliers)
  
      # Initial $3 \times 3$ convolution layer that maps the image to `channels`
      self.conv_in = nn.Conv2d(
          in_channels, channels, 3, stride=1, padding=1
      )
  
      # Number of channels in each top level block
      channels_list = [m * channels for m in [1] + channel_multipliers]
  
      # List of top-level blocks
      self.down = nn.ModuleList()
      # Create top-level blocks
      for i in range(n_resolutions):
          # Each top level block consists of multiple ResNet Blocks and down-sampling
          resnet_blocks = nn.ModuleList()
          # Add ResNet Blocks
          for _ in range(n_resnet_blocks):
              resnet_blocks.append(
                  ResnetBlock(channels, channels_list[i + 1])
              )
              channels = channels_list[i + 1]
          # Top-level block
          down = nn.Module()
          down.block = resnet_blocks
          # Down-sampling at the end of each top level block except the last
          if i != n_resolutions - 1:
              down.downsample = DownSample(channels)
          else:
              down.downsample = nn.Identity()
          #
          self.down.append(down)
  
      # Final ResNet blocks with attention
      self.mid = nn.Module()
      self.mid.block_1 = ResnetBlock(channels, channels)
      self.mid.attn_1 = AttnBlock(channels)
      self.mid.block_2 = ResnetBlock(channels, channels)
  
      # Map to embedding space with a $3 \times 3$ convolution
      self.norm_out = normalization(channels)
      self.conv_out = nn.Conv2d(
          channels, 2 * z_channels, 3, stride=1, padding=1
      )
  
imports: from typing import List
  import torch
  import torch.nn.functional
  from torch import nn
label_desc: Use image node_id 1 to create a new Encoder object from inherited base classes: nn with example: obj = Encoder()