class_docstr: Non-recurrent encoder based on the transformer architecture in:
  
  Attention Is All You Need, Figure 1 (left)
  Vaswani et al. (https://arxiv.org/pdf/1706.03762.pdf).
  
  :param config: Configuration for transformer encoder.
code: def forward(
      self, data: pt.Tensor, valid_length: pt.Tensor
  ) -> Tuple[pt.Tensor, pt.Tensor, pt.Tensor]:
      # positional embedding
      data = self.pos_embedding(data)
  
      if self.dropout is not None:
          data = self.dropout(data)
  
      _, max_len, __ = data.size()
      # length_mask for source attention masking. Shape: (batch_size, max_len)
      single_head_att_mask = layers.prepare_source_length_mask(
          valid_length,
          self.config.attention_heads,
          max_length=max_len,
          expand=False,
      )
      # Shape: (batch_size, max_len) -> (batch_size * heads, 1, max_len)
      att_mask = (
          single_head_att_mask.unsqueeze(1)
          .expand(-1, self.config.attention_heads, -1)
          .reshape((-1, max_len))
          .unsqueeze(1)
      )
      att_mask = att_mask.expand(-1, max_len, -1)
  
      data = data.transpose(1, 0)  # batch to time major
      for layer in self.layers:
          data = layer(data, att_mask=att_mask)
  
      data = self.final_process(data)
      data = data.transpose(1, 0)  # time to batch major
      return data, valid_length, single_head_att_mask
  
imports: from abc import abstractmethod
  from dataclasses import dataclass, field
  from typing import List, Tuple, Optional, Union
  import torch
  import sockeye.constants
  from .None import config
  from .None import layers
  from .None import transformer
label_desc: Use image node_id 2 for calling the TransformerEncoder obj's underlying member method code with example usage: obj.forward(data, valid_length) and returns: data,  valid_length,  single_head_att_mask