class_docstr: CNNLSTM is a simple model for vision and language tasks. CNNLSTM is supposed
  to acts as a baseline to test out your stuff without any complex functionality.
  Passes image through a CNN, and text through an LSTM and fuses them using
  concatenation. Then, it finally passes the fused representation from a MLP to
  generate scores for each of the possible answers.
  
  Args:
      config (DictConfig): Configuration node containing all of the necessary
                           config required to initialize CNNLSTM.
  
  Inputs: sample_list (SampleList)
      - **sample_list** should contain image attribute for image, text for
        question split into word indices, targets for answer scores
code: def forward(self, sample_list):
      self.lstm.flatten_parameters()
  
      question = sample_list.text
      image = sample_list.image
  
      # Get (h_n, c_n), last hidden and cell state
      _, hidden = self.lstm(self.text_embedding(question))
      # X x B x H => B x X x H where X = num_layers * num_directions
      hidden = hidden[0].transpose(0, 1)
  
      # X should be 2 so we can merge in that dimension
      assert hidden.size(1) == 2, _CONSTANTS["hidden_state_warning"]
  
      hidden = torch.cat([hidden[:, 0, :], hidden[:, 1, :]], dim=-1)
      image = self.cnn(image)
  
      # Fuse into single dimension
      fused = torch.cat([hidden, image], dim=-1)
      scores = self.classifier(fused)
  
      return {"scores": scores}
  
file_path: mmf/mmf/models/cnn_lstm.py
imports: from copy import deepcopy
  import torch
  from mmf.common.registry import registry
  from mmf.models.base_model import BaseModel
  from mmf.modules.layers import ClassifierLayer, ConvNet, Flatten
  from torch import nn
label_desc: Use image node_id 4 for calling the CNNLSTM obj's underlying member method code with example usage: obj.forward(sample_list) and returns: dict