class_docstr: Defines interpretable multi-head attention layer.
  
  Attributes:
    n_head: Number of heads
    d_k: Key/query dimensionality per head
    d_v: Value dimensionality
    dropout: Dropout rate to apply
    qs_layers: List of queries across heads
    ks_layers: List of keys across heads
    vs_layers: List of values across heads
    attention: Scaled dot product attention layer
    w_o: Output weight matrix to project internal state to the original TFT
      state size
class_docstr_tok: ["Defines","interpretable","multi-head","attention","layer",".","Attributes",":","n_head",":","Number","of","heads","d_k",":","Key\/query","dimensionality","per","head","d_v",":","Value","dimensionality","dropout",":","Dropout","rate","to","apply","qs_layers",":","List","of","queries","across","heads","ks_layers",":","List","of","keys","across","heads","vs_layers",":","List","of","values","across","heads","attention",":","Scaled","dot","product","attention","layer","w_o",":","Output","weight","matrix","to","project","internal","state","to","the","original","TFT","state","size"]
docstr: Applies interpretable multihead attention.
  
  Using T to denote the number of time steps fed into the transformer.
  
  Args:
    q: Query tensor of shape=(?, T, d_model)
    k: Key of shape=(?, T, d_model)
    v: Values of shape=(?, T, d_model)
    mask: Masking if required with shape=(?, T, T)
  
  Returns:
    Tuple of (layer outputs, attention weights)
docstr_tok: ["Applies","interpretable","multihead","attention",".","Using","T","to","denote","the","number","of","time","steps","fed","into","the","transformer",".","Args",":","q",":","Query","tensor","of","shape=","(","?",",","T",",","d_model",")","k",":","Key","of","shape=","(","?",",","T",",","d_model",")","v",":","Values","of","shape=","(","?",",","T",",","d_model",")","mask",":","Masking","if","required","with","shape=","(","?",",","T",",","T",")","Returns",":","Tuple","of","(","layer","outputs",",","attention","weights",")"]
code: def __call__(self, q, k, v, mask=None):
      """Applies interpretable multihead attention.
  
      Using T to denote the number of time steps fed into the transformer.
  
      Args:
        q: Query tensor of shape=(?, T, d_model)
        k: Key of shape=(?, T, d_model)
        v: Values of shape=(?, T, d_model)
        mask: Masking if required with shape=(?, T, T)
  
      Returns:
        Tuple of (layer outputs, attention weights)
      """
      n_head = self.n_head
  
      heads = []
      attns = []
      for i in range(n_head):
          qs = self.qs_layers[i](q)
          ks = self.ks_layers[i](k)
          vs = self.vs_layers[i](v)
          head, attn = self.attention(qs, ks, vs, mask)
  
          head_dropout = Dropout(self.dropout)(head)
          heads.append(head_dropout)
          attns.append(attn)
      head = K.stack(heads) if n_head > 1 else heads[0]
      attn = K.stack(attns)
  
      outputs = K.mean(head, axis=0) if n_head > 1 else head
      outputs = self.w_o(outputs)
      outputs = Dropout(self.dropout)(outputs)  # output dropout
  
      return outputs, attn
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import gc
  import json
  import os
  import shutil
  import data_formatters.base
  import libs.utils
  import numpy
  import pandas
  import tensorflow
label_desc: Use image node_id 2 for calling the InterpretableMultiHeadAttention obj's underlying member method code with example usage: obj.__call__(q, k, v, mask) and returns: outputs,  attn