class_docstr: Character-level CNN encoder to generate word representations, as input to
  RNN encoder.
code: def forward(self, src_tokens, src_lengths, char_inds, word_lengths):
      self.tracker.reset()
      # char_inds has shape (batch_size, max_words_per_sent, max_word_len)
      bsz, seqlen, maxchars = char_inds.size()
      # char_cnn_encoder takes input (max_word_length, total_words)
      char_inds_flat = char_inds.view(-1, maxchars)  # .t()
      # output (total_words, encoder_dim)
      if self.unk_only_char_encoding:
          assert (
              self.embed_tokens is not None
          ), "token_embed_dim should > 0 when unk_only_char_encoding is true!"
  
          unk_masks = (src_tokens == self.unk_idx).view(-1)
          unk_indices = torch.nonzero(unk_masks).squeeze()
          if unk_indices.dim() > 0 and unk_indices.size(0) > 0:
              char_inds_flat = torch.index_select(
                  char_inds_flat, 0, unk_indices
              )
              char_inds_flat = char_inds_flat.view(-1, maxchars)
          else:
              char_inds_flat = None
  
      if char_inds_flat is not None:
          # (bsz * seqlen, encoder_dim)
          char_cnn_output = self.char_cnn_encoder(char_inds_flat.t())
          x = char_cnn_output
      else:  # charCNN is not needed
          x = None
  
      if self.embed_tokens is not None:
          # (bsz, seqlen, token_embed_dim)
          embedded_tokens = self.embed_tokens(src_tokens)
          # (bsz * seqlen, token_embed_dim)
          embedded_tokens = embedded_tokens.view(
              -1, self.token_embed_dim
          )
          if self.unk_only_char_encoding:  # charCNN for UNK words only
              if x is not None:
                  x = embedded_tokens.index_copy(0, unk_indices, x)
              else:  # no UNK, so charCNN is not needed
                  x = embedded_tokens
          else:  # charCNN for all words
              x = torch.cat([x, embedded_tokens], dim=1)
  
      # (bsz, seqlen, x.shape[-1])
      x = x.view(bsz, seqlen, x.shape[-1])
      # (seqlen, bsz, x.shape[-1])
      x = x.transpose(0, 1)
  
      self.tracker.track(
          x, "token_embeddings", retain_grad=self.track_gradients
      )
      if self.dropout_in != 0:
          x = F.dropout(x, p=self.dropout_in, training=self.training)
      embedded_words = x
  
      unpacked_output, final_hiddens, final_cells = self.bilstm(
          embeddings=x, lengths=src_lengths
      )
  
      return (
          unpacked_output,
          final_hiddens,
          final_cells,
          src_lengths,
          src_tokens,
          embedded_words,
      )
  
imports: import logging
  from ast import literal_eval
  import torch
  import torch.nn.functional
  from fairseq.models import FairseqEncoder, register_model, register_model_architecture
  from pytorch_translate import char_encoder, model_constants, rnn, utils, vocab_constants
  from pytorch_translate.common_layers import Embedding, VariableTracker
  from pytorch_translate.data.dictionary import TAGS
label_desc: Use image node_id 4 for calling the CharCNNEncoder obj's underlying member method code with example usage: obj.forward(src_tokens, src_lengths, char_inds, word_lengths) and returns: unpacked_output,  final_hiddens,  final_cells,  src_lengths,  src_tokens,  embedded_words