class_docstr: Attention layer according to https://arxiv.org/abs/1409.0473.
  
  Params:
    num_units: Number of units used in the attention layer
docstr: Computes attention scores and outputs.
  
  Args:
    query: The query used to calculate attention scores.
      In seq2seq this is typically the current state of the decoder.
      A tensor of shape `[B, ...]`
    keys: The keys used to calculate attention scores. In seq2seq, these
      are typically the outputs of the encoder and equivalent to `values`.
      A tensor of shape `[B, T, ...]` where each element in the `T`
      dimension corresponds to the key for that value.
    values: The elements to compute attention over. In seq2seq, this is
      typically the sequence of encoder outputs.
      A tensor of shape `[B, T, input_dim]`.
    values_length: An int32 tensor of shape `[B]` defining the sequence
      length of the attention values.
  
  Returns:
    A tuple `(scores, context)`.
    `scores` is vector of length `T` where each element is the
    normalized "score" of the corresponding `inputs` element.
    `context` is the final attention layer output corresponding to
    the weighted inputs.
    A tensor fo shape `[B, input_dim]`.
docstr_tok: ["Computes","attention","scores","and","outputs",".","Args",":","query",":","The","query","used","to","calculate","attention","scores",".","In","seq2seq","this","is","typically","the","current","state","of","the","decoder",".","A","tensor","of","shape","`","[","B",",","...","]","`","keys",":","The","keys","used","to","calculate","attention","scores",".","In","seq2seq",",","these","are","typically","the","outputs","of","the","encoder","and","equivalent","to","`","values","`",".","A","tensor","of","shape","`","[","B",",","T",",","...","]","`","where","each","element","in","the","`","T","`","dimension","corresponds","to","the","key","for","that","value",".","values",":","The","elements","to","compute","attention","over",".","In","seq2seq",",","this","is","typically","the","sequence","of","encoder","outputs",".","A","tensor","of","shape","`","[","B",",","T",",","input_dim","]","`",".","values_length",":","An","int32","tensor","of","shape","`","[","B","]","`","defining","the","sequence","length","of","the","attention","values",".","Returns",":","A","tuple","`","(","scores",",","context",")","`",".","`","scores","`","is","vector","of","length","`","T","`","where","each","element","is","the","normalized","``","score","''","of","the","corresponding","`","inputs","`","element",".","`","context","`","is","the","final","attention","layer","output","corresponding","to","the","weighted","inputs",".","A","tensor","fo","shape","`","[","B",",","input_dim","]","`","."]
code: def _build(self, query, keys, values, values_length):
      """Computes attention scores and outputs.
  
      Args:
        query: The query used to calculate attention scores.
          In seq2seq this is typically the current state of the decoder.
          A tensor of shape `[B, ...]`
        keys: The keys used to calculate attention scores. In seq2seq, these
          are typically the outputs of the encoder and equivalent to `values`.
          A tensor of shape `[B, T, ...]` where each element in the `T`
          dimension corresponds to the key for that value.
        values: The elements to compute attention over. In seq2seq, this is
          typically the sequence of encoder outputs.
          A tensor of shape `[B, T, input_dim]`.
        values_length: An int32 tensor of shape `[B]` defining the sequence
          length of the attention values.
  
      Returns:
        A tuple `(scores, context)`.
        `scores` is vector of length `T` where each element is the
        normalized "score" of the corresponding `inputs` element.
        `context` is the final attention layer output corresponding to
        the weighted inputs.
        A tensor fo shape `[B, input_dim]`.
      """
      values_depth = values.get_shape().as_list()[-1]
  
      # Fully connected layers to transform both keys and query
      # into a tensor with `num_units` units
      att_keys = tf.contrib.layers.fully_connected(
          inputs=keys,
          num_outputs=self.params["num_units"],
          activation_fn=None,
          scope="att_keys",
      )
      att_query = tf.contrib.layers.fully_connected(
          inputs=query,
          num_outputs=self.params["num_units"],
          activation_fn=None,
          scope="att_query",
      )
  
      scores = self.score_fn(att_keys, att_query)
  
      # Replace all scores for padded inputs with tf.float32.min
      num_scores = tf.shape(scores)[1]
      scores_mask = tf.sequence_mask(
          lengths=tf.to_int32(values_length),
          maxlen=tf.to_int32(num_scores),
          dtype=tf.float32,
      )
      scores = scores * scores_mask + (
          (1.0 - scores_mask) * tf.float32.min
      )
  
      # Normalize the scores
      scores_normalized = tf.nn.softmax(
          scores, name="scores_normalized"
      )
  
      # Calculate the weighted average of the attention inputs
      # according to the scores
      context = tf.expand_dims(scores_normalized, 2) * values
      context = tf.reduce_sum(context, 1, name="context")
      context.set_shape([None, values_depth])
  
      return (scores_normalized, context)
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  from __future__ import unicode_literals
  import abc
  import six
  import tensorflow
  from tensorflow.python.framework import function
  from seq2seq.graph_module import GraphModule
  from seq2seq.configurable import Configurable
label_desc: Use image node_id 4 for calling the AttentionLayer obj's underlying member method code with example usage: obj._build(query, keys, values, values_length) and returns: scores_normalized,  context