class_docstr: **LSTM** 的 Encoder
  
  :param embed: ``decoder`` 输入的 embedding，支持以下几种输入类型：
  
          - ``tuple(num_embedings, embedding_dim)``，即 embedding 的大小和每个词的维度，此时将随机初始化一个 :class:`torch.nn.Embedding` 实例；
          - :class:`torch.nn.Embedding` 或 **fastNLP** 的 ``Embedding`` 对象，此时就以传入的对象作为 embedding；
          - :class:`numpy.ndarray` ，将使用传入的 ndarray 作为 Embedding 初始化；
          - :class:`torch.Tensor`，此时将使用传入的值作为 Embedding 初始化；
  :param num_layers: LSTM 的层数
  :param hidden_size: 隐藏层大小, 该值也被认为是 ``encoder`` 的输出维度大小
  :param dropout: Dropout 的大小
  :param bidirectional: 是否使用双向
class_docstr_tok: ["*","*","LSTM","*","*","\u7684","Encoder",":","param","embed",":","``","decoder","``","\u8f93\u5165\u7684","embedding\uff0c\u652f\u6301\u4ee5\u4e0b\u51e0\u79cd\u8f93\u5165\u7c7b\u578b\uff1a","-","``","tuple","(","num_embedings",",","embedding_dim",")","``","\uff0c\u5373","embedding","\u7684\u5927\u5c0f\u548c\u6bcf\u4e2a\u8bcd\u7684\u7ef4\u5ea6\uff0c\u6b64\u65f6\u5c06\u968f\u673a\u521d\u59cb\u5316\u4e00\u4e2a",":","class",":","`","torch.nn.Embedding","`","\u5b9e\u4f8b\uff1b","-",":","class",":","`","torch.nn.Embedding","`","\u6216","*","*","fastNLP","*","*","\u7684","``","Embedding","``","\u5bf9\u8c61\uff0c\u6b64\u65f6\u5c31\u4ee5\u4f20\u5165\u7684\u5bf9\u8c61\u4f5c\u4e3a","embedding\uff1b","-",":","class",":","`","numpy.ndarray","`","\uff0c\u5c06\u4f7f\u7528\u4f20\u5165\u7684","ndarray","\u4f5c\u4e3a","Embedding","\u521d\u59cb\u5316\uff1b","-",":","class",":","`","torch.Tensor","`","\uff0c\u6b64\u65f6\u5c06\u4f7f\u7528\u4f20\u5165\u7684\u503c\u4f5c\u4e3a","Embedding","\u521d\u59cb\u5316\uff1b",":","param","num_layers",":","LSTM","\u7684\u5c42\u6570",":","param","hidden_size",":","\u9690\u85cf\u5c42\u5927\u5c0f",",","\u8be5\u503c\u4e5f\u88ab\u8ba4\u4e3a\u662f","``","encoder","``","\u7684\u8f93\u51fa\u7ef4\u5ea6\u5927\u5c0f",":","param","dropout",":","Dropout","\u7684\u5927\u5c0f",":","param","bidirectional",":","\u662f\u5426\u4f7f\u7528\u53cc\u5411"]
docstr: :param tokens: 输入序列，形状为 ``[batch_size, max_len]``
  :param seq_len: 序列长度，形状为 ``[batch_size, ]``，若为 ``None``，表示所有输入看做一样长
  :return: 返回 ``((output, (ht, ct)), encoder_mask)`` 格式的结果。
  
          - ``output`` 形状为 ``[batch_size, seq_len, hidden_size*num_direction]``，表示输出序列；
          - ``ht`` 和 ``ct`` 形状为 ``[num_layers*num_direction, batch_size, hidden_size]``，表示最后时刻隐状态；
          - ``encoder_mask`` 形状为 ``[batch_size, max_len]``， 表示产生的掩码 ``encoder_mask``，为 **0** 的地方为 padding
docstr_tok: [":","param","tokens",":","\u8f93\u5165\u5e8f\u5217\uff0c\u5f62\u72b6\u4e3a","``","[","batch_size",",","max_len","]","``",":","param","seq_len",":","\u5e8f\u5217\u957f\u5ea6\uff0c\u5f62\u72b6\u4e3a","``","[","batch_size",",","]","``","\uff0c\u82e5\u4e3a","``","None","``","\uff0c\u8868\u793a\u6240\u6709\u8f93\u5165\u770b\u505a\u4e00\u6837\u957f",":","return",":","\u8fd4\u56de","``","(","(","output",",","(","ht",",","ct",")",")",",","encoder_mask",")","``","\u683c\u5f0f\u7684\u7ed3\u679c\u3002","-","``","output","``","\u5f62\u72b6\u4e3a","``","[","batch_size",",","seq_len",",","hidden_size","*","num_direction","]","``","\uff0c\u8868\u793a\u8f93\u51fa\u5e8f\u5217\uff1b","-","``","ht","``","\u548c","``","ct","``","\u5f62\u72b6\u4e3a","``","[","num_layers","*","num_direction",",","batch_size",",","hidden_size","]","``","\uff0c\u8868\u793a\u6700\u540e\u65f6\u523b\u9690\u72b6\u6001\uff1b","-","``","encoder_mask","``","\u5f62\u72b6\u4e3a","``","[","batch_size",",","max_len","]","``","\uff0c","\u8868\u793a\u4ea7\u751f\u7684\u63a9\u7801","``","encoder_mask","``","\uff0c\u4e3a","*","*","0","*","*","\u7684\u5730\u65b9\u4e3a","padding"]
code: def forward(
      self, tokens: torch.LongTensor, seq_len: torch.LongTensor
  ):
      """
  
      :param tokens: 输入序列，形状为 ``[batch_size, max_len]``
      :param seq_len: 序列长度，形状为 ``[batch_size, ]``，若为 ``None``，表示所有输入看做一样长
      :return: 返回 ``((output, (ht, ct)), encoder_mask)`` 格式的结果。
  
              - ``output`` 形状为 ``[batch_size, seq_len, hidden_size*num_direction]``，表示输出序列；
              - ``ht`` 和 ``ct`` 形状为 ``[num_layers*num_direction, batch_size, hidden_size]``，表示最后时刻隐状态；
              - ``encoder_mask`` 形状为 ``[batch_size, max_len]``， 表示产生的掩码 ``encoder_mask``，为 **0** 的地方为 padding
  
      """
      x = self.embed(tokens)
      device = x.device
      x, (final_hidden, final_cell) = self.lstm(x, seq_len)
      encoder_mask = seq_len_to_mask(seq_len).to(device)
  
      # x: batch,seq_len,dim; h/c: num_layers*2,batch,dim
  
      if self.bidirectional:
          final_hidden = self.concat_bidir(
              final_hidden
          )  # 将双向的hidden state拼接起来，用于接下来的decoder的input
          final_cell = self.concat_bidir(final_cell)
  
      return (x, (final_hidden[-1], final_cell[-1])), encoder_mask
  
imports: import torch.nn
  import torch
  from torch.nn import LayerNorm
  import torch.nn.functional
  from typing import Union, Tuple
  from ....core.utils import seq_len_to_mask
  import math
  from .lstm import LSTM
  from ..attention import MultiHeadAttention
  from ....embeddings.torch import StaticEmbedding
  from ....embeddings.torch.utils import get_embeddings
label_desc: Use image node_id 2 for calling the LSTMSeq2SeqEncoder obj's underlying member method code with example usage: obj.forward(tokens, seq_len) and returns: x,  final_hidden,  final_cell,  encoder_mask