code: def forward(self, q, k, v, attn_mask=None):
      # q: [batch, slot, feat] or (batch * d_l) x max_len x d_k
      # k: [batch, slot, feat] or (batch * d_l) x max_len x d_k
      # v: [batch, slot, feat] or (batch * d_l) x max_len x d_v
      # q in LAL is (batch * d_l) x 1 x d_k
  
      attn = (
          torch.bmm(q, k.transpose(1, 2)) / self.temper
      )  # (batch * d_l) x max_len x max_len
      # in LAL, gives: (batch * d_l) x 1 x max_len
      # attention weights from each word to each word, for each label
      # in best model (repeated q): attention weights from label (as vector weights) to each word
  
      if attn_mask is not None:
          assert attn_mask.size() == attn.size(), (
              "Attention mask shape {} mismatch "
              "with Attention logit tensor shape "
              "{}.".format(attn_mask.size(), attn.size())
          )
  
          attn.data.masked_fill_(attn_mask, -float("inf"))
  
      attn = self.softmax(attn)
      # Note that this makes the distribution not sum to 1. At some point it
      # may be worth researching whether this is the right way to apply
      # dropout to the attention.
      # Note that the t2t code also applies dropout in this manner
      attn = self.dropout(attn)
      output = torch.bmm(attn, v)  # (batch * d_l) x max_len x d_v
      # in LAL, gives: (batch * d_l) x 1 x d_v
  
      return output, attn
  
imports: import numpy
  import functools
  import sys
  import torch
  from torch.autograd import Variable
  import torch.nn
  import torch.nn.init
label_desc: Use image node_id 2 for calling the ScaledDotProductAttention obj's underlying member method code with example usage: obj.forward(q, k, v, attn_mask) and returns: output,  attn