class_docstr: Implements decoder module of the SAR model
  
  Args:
  ----
      rnn_units: number of hidden units in recurrent cells
      max_length: maximum length of a sequence
      vocab_size: number of classes in the model alphabet
      embedding_units: number of hidden embedding units
      attention_units: number of hidden attention units
class_docstr_tok: ["Implements","decoder","module","of","the","SAR","model","Args",":","--","--","rnn_units",":","number","of","hidden","units","in","recurrent","cells","max_length",":","maximum","length","of","a","sequence","vocab_size",":","number","of","classes","in","the","model","alphabet","embedding_units",":","number","of","hidden","embedding","units","attention_units",":","number","of","hidden","attention","units"]
code: def forward(
      self,
      features: torch.Tensor,  # (N, C, H, W)
      holistic: torch.Tensor,  # (N, C)
      gt: Optional[torch.Tensor] = None,  # (N, L)
  ) -> torch.Tensor:
      if gt is not None:
          gt_embedding = self.embed_tgt(gt)
  
      logits_list: List[torch.Tensor] = []
  
      for t in range(self.max_length + 1):  # 32
          if t == 0:
              # step to init the first states of the LSTMCell
              hidden_state_init = cell_state_init = torch.zeros(
                  features.size(0),
                  features.size(1),
                  device=features.device,
              )
              hidden_state, cell_state = (
                  hidden_state_init,
                  cell_state_init,
              )
              prev_symbol = holistic
          elif t == 1:
              # step to init a 'blank' sequence of length vocab_size + 1 filled with zeros
              # (N, vocab_size + 1) --> (N, embedding_units)
              prev_symbol = torch.zeros(
                  features.size(0),
                  self.vocab_size + 1,
                  device=features.device,
              )
              prev_symbol = self.embed(prev_symbol)
          else:
              if gt is not None:
                  # (N, embedding_units) -2 because of <bos> and <eos> (same)
                  prev_symbol = self.embed(gt_embedding[:, t - 2])
              else:
                  # -1 to start at timestep where prev_symbol was initialized
                  index = logits_list[t - 1].argmax(-1)
                  # update prev_symbol with ones at the index of the previous logit vector
                  # (N, embedding_units)
                  prev_symbol = prev_symbol.scatter_(
                      1, index.unsqueeze(1), 1
                  )
  
          # (N, C), (N, C)  take the last hidden state and cell state from current timestep
          hidden_state_init, cell_state_init = self.lstm_cell(
              prev_symbol, (hidden_state_init, cell_state_init)
          )
          hidden_state, cell_state = self.lstm_cell(
              hidden_state_init, (hidden_state, cell_state)
          )
          # (N, C, H, W), (N, C) --> (N, C)
          glimpse = self.attention_module(features, hidden_state)
          # (N, C), (N, C) --> (N, 2 * C)
          logits = torch.cat([hidden_state, glimpse], dim=1)
          logits = self.dropout(logits)
          # (N, vocab_size + 1)
          logits_list.append(self.output_dense(logits))
  
      # (max_length + 1, N, vocab_size + 1) --> (N, max_length + 1, vocab_size + 1)
      return torch.stack(logits_list[1:]).permute(1, 0, 2)
  
imports: from copy import deepcopy
  from typing import Any, Callable, Dict, List, Optional, Tuple
  import torch
  from torch import nn
  from torch.nn import functional
  from torchvision.models._utils import IntermediateLayerGetter
  from doctr.datasets import VOCABS
  from ...classification import resnet31
  from ...utils.pytorch import _bf16_to_float32, load_pretrained_params
  from ..core import RecognitionModel, RecognitionPostProcessor
label_desc: Use image node_id 2 for calling the SARDecoder obj's underlying member method code with example usage: obj.forward(features, holistic, gt) and returns: torch