docstr: Analysis transform from ELIC (https://arxiv.org/abs/2203.10886), which
  can be configured to match the one from "Devil's in the Details"
  (https://arxiv.org/abs/2203.08450).
  
  Args:
      num_residual_blocks: defaults to 3.
      channels: defaults to [128, 160, 192, 192].
      compression_channels: optional, defaults to None. If provided, it must equal
          the last element of `channels`.
      max_frames: optional, defaults to None. If provided, the input is chunked
          into max_frames elements, otherwise the entire batch is processed at
          once. This is useful when large sequences are to be processed and can
          be used to manage memory a bit better.
docstr_tok: ["Analysis","transform","from","ELIC","(","https",":","\/\/arxiv.org\/abs\/2203.10886",")",",","which","can","be","configured","to","match","the","one","from","``","Devil","'s","in","the","Details","''","(","https",":","\/\/arxiv.org\/abs\/2203.08450",")",".","Args",":","num_residual_blocks",":","defaults","to","3.","channels",":","defaults","to","[","128",",","160",",","192",",","192","]",".","compression_channels",":","optional",",","defaults","to","None",".","If","provided",",","it","must","equal","the","last","element","of","`","channels","`",".","max_frames",":","optional",",","defaults","to","None",".","If","provided",",","the","input","is","chunked","into","max_frames","elements",",","otherwise","the","entire","batch","is","processed","at","once",".","This","is","useful","when","large","sequences","are","to","be","processed","and","can","be","used","to","manage","memory","a","bit","better","."]
code: def __init__(
      self,
      num_residual_blocks=3,
      channels: List[int] = [128, 160, 192, 192],
      compression_channels: Optional[int] = None,
      max_frames: Optional[int] = None,
  ) -> None:
      """Analysis transform from ELIC (https://arxiv.org/abs/2203.10886), which
      can be configured to match the one from "Devil's in the Details"
      (https://arxiv.org/abs/2203.08450).
  
      Args:
          num_residual_blocks: defaults to 3.
          channels: defaults to [128, 160, 192, 192].
          compression_channels: optional, defaults to None. If provided, it must equal
              the last element of `channels`.
          max_frames: optional, defaults to None. If provided, the input is chunked
              into max_frames elements, otherwise the entire batch is processed at
              once. This is useful when large sequences are to be processed and can
              be used to manage memory a bit better.
      """
      super().__init__()
      if len(channels) != 4:
          raise ValueError(
              f"ELIC uses 4 conv layers (not {len(channels)})."
          )
      if (
          compression_channels is not None
          and compression_channels != channels[-1]
      ):
          raise ValueError(
              "output_channels specified but does not match channels: "
              f"{compression_channels} vs. {channels}"
          )
      self._compression_channels = (
          compression_channels
          if compression_channels is not None
          else channels[-1]
      )
      self._max_frames = max_frames
  
      def res_units(N):
          return [ResidualUnit(N) for _ in range(num_residual_blocks)]
  
      channels = [3] + channels
  
      self.transforms = nn.Sequential(
          make_conv(channels[0], channels[1], kernel_size=5, stride=2),
          *res_units(channels[1]),
          make_conv(channels[1], channels[2], kernel_size=5, stride=2),
          *res_units(channels[2]),
          AttentionBlock(channels[2]),
          make_conv(channels[2], channels[3], kernel_size=5, stride=2),
          *res_units(channels[3]),
          make_conv(channels[3], channels[4], kernel_size=5, stride=2),
          AttentionBlock(channels[4]),
      )
  
imports: from typing import List, Optional
  import torch
  import torch.nn
  from compressai.layers import GDN, AttentionBlock
  from neural.layers_utils import make_conv, make_deconv
  from torch import Tensor
label_desc: Use image node_id 1 to create a new ELICAnalysis object from inherited base classes: nn with example: obj = ELICAnalysis(num_residual_blocks, channels, compression_channels, max_frames)