class_docstr: Wrapper for nn.LSTM
  
  Differences include:
  * weight initialization
  * the bidirectional option makes the first layer bidirectional only
  (and in that case the hidden dim is divided by 2)
class_docstr_tok: ["Wrapper","for","nn.LSTM","Differences","include",":","*","weight","initialization","*","the","bidirectional","option","makes","the","first","layer","bidirectional","only","(","and","in","that","case","the","hidden","dim","is","divided","by","2",")"]
code: def forward(self, embeddings, lengths, enforce_sorted=True):
      # enforce_sorted is set to True by default to force input lengths
      # are sorted in a descending order when pack padded sequence.
      bsz = embeddings.size()[1]
  
      # Generate packed seq to deal with varying source seq length
      # packed_input is of type PackedSequence, which consists of:
      # element [0]: a tensor, the packed data, and
      # element [1]: a list of integers, the batch size for each step
      packed_input = pack_padded_sequence(
          embeddings, lengths.cpu(), enforce_sorted=enforce_sorted
      )
  
      final_hiddens, final_cells = [], []
      for i, rnn_layer in enumerate(self.layers):
          if self.bidirectional and i == 0:
              h0 = embeddings.new(2, bsz, self.hidden_dim // 2).zero_()
              c0 = embeddings.new(2, bsz, self.hidden_dim // 2).zero_()
          else:
              h0 = embeddings.new(1, bsz, self.hidden_dim).zero_()
              c0 = embeddings.new(1, bsz, self.hidden_dim).zero_()
  
          # apply LSTM along entire sequence
          current_output, (h_last, c_last) = rnn_layer(
              packed_input, (h0, c0)
          )
  
          # final state shapes: (bsz, hidden_dim)
          if self.bidirectional and i == 0:
              # concatenate last states for forward and backward LSTM
              h_last = torch.cat(
                  (h_last[0, :, :], h_last[1, :, :]), dim=1
              )
              c_last = torch.cat(
                  (c_last[0, :, :], c_last[1, :, :]), dim=1
              )
          else:
              h_last = h_last.squeeze(dim=0)
              c_last = c_last.squeeze(dim=0)
  
          final_hiddens.append(h_last)
          final_cells.append(c_last)
  
          if (
              self.residual_level is not None
              and i >= self.residual_level
          ):
              packed_input[0] = (
                  packed_input.clone()[0] + current_output[0]
              )
          else:
              packed_input = current_output
  
      # Reshape to [num_layer, batch_size, hidden_dim]
      final_hiddens = torch.cat(final_hiddens, dim=0).view(
          self.num_layers, *final_hiddens[0].size()
      )
      final_cells = torch.cat(final_cells, dim=0).view(
          self.num_layers, *final_cells[0].size()
      )
  
      #  [max_seqlen, batch_size, hidden_dim]
      unpacked_output, _ = pad_packed_sequence(packed_input)
  
      return (unpacked_output, final_hiddens, final_cells)
  
imports: import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  import torch.onnx.operators
  from fairseq import options, utils
  from fairseq.models import FairseqEncoder, FairseqEncoderDecoderModel, register_model, register_model_architecture
  from fairseq.modules import AdaptiveSoftmax
  from pytorch_translate import attention, rnn_cell, utils, vocab_reduction
  from pytorch_translate.common_layers import ContextEmbedding, DecoderWithOutputProjection, Embedding, Linear, RNNLayer, VariableTracker
  from pytorch_translate.data import data
  from pytorch_translate.multi_model import MultiDecoder, MultiEncoder
  from pytorch_translate.multilingual import MultilingualDecoder, MultilingualEncoder
  from pytorch_translate.ngram import NGramDecoder
  from pytorch_translate.semi_supervised import SemiSupervisedModel
  from pytorch_translate.utils import maybe_cat, maybe_cuda, torch_find
  from torch.nn.utils.rnn import pack_padded_sequence, PackedSequence, pad_packed_sequence
label_desc: Use image node_id 3 for calling the BiLSTM obj's underlying member method code with example usage: obj.forward(embeddings, lengths, enforce_sorted) and returns: unpacked_output,  final_hiddens,  final_cells