class_docstr: RNN decoder with multihead attention. Attention is calculated using encoder
  output and output of decoder's first RNN layerself. Attention is applied
  after first RNN layer and concatenated to input of subsequent layers.
class_docstr_tok: ["RNN","decoder","with","multihead","attention",".","Attention","is","calculated","using","encoder","output","and","output","of","decoder","'s","first","RNN","layerself",".","Attention","is","applied","after","first","RNN","layer","and","concatenated","to","input","of","subsequent","layers","."]
code: def forward_unprojected(
      self,
      input_tokens,
      encoder_out: Dict[str, torch.Tensor],
      incremental_state: Optional[Dict[str, torch.Tensor]] = None,
  ) -> Tuple[torch.Tensor, Dict[str, torch.Tensor]]:
      if incremental_state is not None and len(incremental_state) > 0:
          input_tokens = input_tokens[:, -1:]
      bsz, seqlen = input_tokens.size()
  
      # get outputs from encoder
      encoder_outs = encoder_out["unpacked_output"]
      src_lengths = encoder_out["src_lengths"]
  
      # embed tokens
      x = self.embed_tokens([[input_tokens]])
      x = F.dropout(x, p=self.dropout_in, training=self.training)
      # B x T x C -> T x B x C
      x = x.transpose(0, 1)
  
      # initialize previous states (or get from cache during incremental generation)
      cached_state = self._get_cached_state(incremental_state)
      if cached_state is not None:
          prev_hiddens, prev_cells, input_feed = cached_state
      else:
          # first time step, initialize previous states
          if incremental_state is None:
              incremental_state = {}
          self._init_prev_states(encoder_out, incremental_state)
          init_state = self._get_cached_state(incremental_state)
          assert init_state is not None
          prev_hiddens, prev_cells, input_feed = init_state
  
      outs = []
      attn_scores_per_step: List[torch.Tensor] = []
      next_hiddens: List[torch.Tensor] = []
      next_cells: List[torch.Tensor] = []
      for j in range(seqlen):
          # input feeding: concatenate context vector from previous time step
          step_input = torch.cat((x[j, :, :], input_feed), dim=1)
  
          for i, rnn in enumerate(self.layers):
              # recurrent cell
              hidden, cell = rnn(
                  step_input, (prev_hiddens[i], prev_cells[i])
              )
  
              if self.first_layer_attention and i == 0:
                  # tgt_len is 1 in decoder and squeezed for both matrices
                  # input_feed.shape = tgt_len X bsz X embed_dim
                  # step_attn_scores.shape = src_len X tgt_len X bsz
                  input_feed, step_attn_scores = self.attention(
                      hidden, encoder_outs, src_lengths
                  )
  
              # hidden state becomes the input to the next layer
              layer_output = F.dropout(
                  hidden, p=self.dropout_out, training=self.training
              )
  
              step_input = layer_output
  
              if self.first_layer_attention:
                  step_input = torch.cat(
                      (step_input, input_feed), dim=1
                  )
  
              # save state for next time step
              next_hiddens.append(hidden)
              next_cells.append(cell)
  
          if not self.first_layer_attention:
              input_feed, step_attn_scores = self.attention(
                  hidden, encoder_outs, src_lengths
              )
  
              attn_scores_per_step.append(step_attn_scores)
          combined_output_and_context = torch.cat(
              (hidden, input_feed), dim=1
          )
  
          # save final output
          outs.append(combined_output_and_context)
  
          # update hidden states for next timestep
          prev_hiddens = torch.stack(next_hiddens, 0)
          prev_cells = torch.stack(next_cells, 0)
          next_hiddens = []
          next_cells = []
  
      attn_scores = torch.stack(attn_scores_per_step, dim=1)
      # srclen x tgtlen x bsz -> bsz x tgtlen x srclen
      attn_scores = attn_scores.transpose(0, 2)
  
      # cache previous states
      self._set_cached_state(
          incremental_state, (prev_hiddens, prev_cells, input_feed)
      )
  
      # collect outputs across time steps
      x = torch.cat(outs, dim=0).view(
          seqlen, bsz, self.combined_output_and_context_dim
      )
  
      # T x B x C -> B x T x C
      x = x.transpose(1, 0)
  
      # bottleneck layer
      x = self.additional_fc(x)
      x = F.dropout(x, p=self.dropout_out, training=self.training)
      return (
          x,
          {
              "attn_scores": attn_scores,
              "src_tokens": encoder_out["src_tokens"],
              "src_lengths": encoder_out["src_lengths"],
          },
      )
  
imports: from typing import Dict, List, Optional, Tuple
  import torch
  import torch.nn.functional
  from fairseq import utils
  from pytext.config import ConfigBase
  from pytext.models.seq_models.base import PyTextSeq2SeqModule
  from pytext.utils.usage import log_class_usage
  from torch import nn
  from .attention import DotAttention
  from .base import PlaceholderIdentity, PyTextIncrementalDecoderComponent
label_desc: Use image node_id 3 for calling the RNNDecoderBase obj's underlying member method code with example usage: obj.forward_unprojected(input_tokens, encoder_out, incremental_state) and returns: x,  dict