class_docstr: Self attention both on image and question.
class_docstr_tok: ["Self","attention","both","on","image","and","question","."]
code: def body(self, features):
      hp = self.hparams
      # pylint: disable=eval-used
      if hp.image_input_type == "image":
          image_feat = vqa_layers.image_embedding(
              features["inputs"],
              model_fn=eval(hp.image_model_fn),
              trainable=hp.train_resnet,
              is_training=hp.mode == tf_estimator.ModeKeys.TRAIN,
          )
      else:
          image_feat = features["inputs"]
  
      image_feat = common_layers.flatten4d3d(image_feat)
      image_hidden_size = hp.image_hidden_size or hp.hidden_size
      if hp.image_feat_preprocess_proj:
          image_feat = common_layers.dense(
              image_feat, image_hidden_size
          )
          utils.collect_named_outputs(
              "norms",
              "image_feat_after_proj",
              tf.norm(image_feat, axis=-1),
          )
      else:
          assert image_hidden_size == 2048
  
      image_feat = tf.nn.dropout(
          image_feat, keep_prob=1.0 - hp.layer_prepostprocess_dropout
      )
  
      if hp.image_feat_encode:
          image_feat = image_encoder(image_feat, hp)
          utils.collect_named_outputs(
              "norms",
              "image_feat_encoded",
              tf.norm(image_feat, axis=-1),
          )
      else:
          image_feat = common_layers.layer_norm(image_feat)
          utils.collect_named_outputs(
              "norms",
              "image_feat_after_layer",
              tf.norm(image_feat, axis=-1),
          )
  
      question = common_layers.flatten4d3d(features["question"])
      utils.collect_named_outputs(
          "norms", "question_embedding", tf.norm(question, axis=-1)
      )
      question, question_self_attention_bias = prepare_question_encoder(
          question, hp
      )
      question = tf.nn.dropout(
          question, keep_prob=1.0 - hp.layer_prepostprocess_dropout
      )
      query = question_encoder(
          question, question_self_attention_bias, hp
      )
      utils.collect_named_outputs(
          "norms", "query_encode", tf.norm(query, axis=-1)
      )
      query = query + tf.expand_dims(
          tf.squeeze(question_self_attention_bias, [1, 2]), axis=2
      )
      query = tf.reduce_max(query, axis=1)
      utils.collect_named_outputs(
          "norms", "query_maxpool", tf.norm(query, axis=-1)
      )
  
      # query = common_layers.l2_norm(query)
      # utils.collect_named_outputs("norms", "query_after_l2",
      #                             tf.norm(query, axis=-1))
  
      image_ave = attn(image_feat, query, hp)
      utils.collect_named_outputs(
          "norms", "image_ave", tf.norm(image_ave, axis=-1)
      )
  
      if hp.multimodal_combine == "concat":
          image_question = tf.concat([image_ave, query], axis=1)
      elif hp.multimodal_combine == "sum":
          image_question = image_ave + query
      elif hp.multimodal_combine == "product":
          image_question = image_ave * query
  
      utils.collect_named_outputs(
          "norms", "image_question", tf.norm(image_question, axis=-1)
      )
  
      image_question = tf.nn.dropout(image_question, 1.0 - hp.dropout)
  
      output = mlp(image_question, hp)
      utils.collect_named_outputs(
          "norms", "output", tf.norm(output, axis=-1)
      )
  
      norm_tensors = utils.convert_collection_to_dict("norms")
      vqa_layers.summarize_tensors(norm_tensors, tag="norms/")
  
      # Expand dimension 1 and 2
      return tf.expand_dims(tf.expand_dims(output, axis=1), axis=2)
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  from six.moves import range
  from tensor2tensor.layers import common_attention
  from tensor2tensor.layers import common_hparams
  from tensor2tensor.layers import common_layers
  from tensor2tensor.layers import vqa_layers
  from tensor2tensor.models.research import vqa_attention
  from tensor2tensor.utils import registry
  import tensorflow.compat.v1
  from tensorflow.compat.v1 import estimator
  from tensorflow.contrib.layers.python.layers import utils
label_desc: Use image node_id 1 for calling the VqaSelfAttention obj's underlying member method code with example usage: obj.body(features) and returns: tf