class_docstr: Implements simple/classical attention.
class_docstr_tok: ["Implements","simple\/classical","attention","."]
docstr: Compute attention.
  
  Attend over ys with query xs to obtain weights, then apply weights to
  values (ys if yalues is None)
  
  Args:
      xs: B x query_len x dim (queries)
      ys: B x key_len x dim (keys)
      mask_ys: B x key_len (mask)
      values: B x value_len x dim (values); if None, default to ys
docstr_tok: ["Compute","attention",".","Attend","over","ys","with","query","xs","to","obtain","weights",",","then","apply","weights","to","values","(","ys","if","yalues","is","None",")","Args",":","xs",":","B","x","query_len","x","dim","(","queries",")","ys",":","B","x","key_len","x","dim","(","keys",")","mask_ys",":","B","x","key_len","(","mask",")","values",":","B","x","value_len","x","dim","(","values",")",";","if","None",",","default","to","ys"]
code: def forward(
      self,
      xs: torch.Tensor,
      ys: torch.Tensor,
      mask_ys: Optional[torch.Tensor] = None,
      values: Optional[torch.Tensor] = None,
  ) -> Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]:
      """
      Compute attention.
  
      Attend over ys with query xs to obtain weights, then apply weights to
      values (ys if yalues is None)
  
      Args:
          xs: B x query_len x dim (queries)
          ys: B x key_len x dim (keys)
          mask_ys: B x key_len (mask)
          values: B x value_len x dim (values); if None, default to ys
      """
      bsz = xs.size(0)
      y_len = ys.size(1)
      x_len = xs.size(1)
      if self.attn == "cosine":
          l1 = self.cosine(xs, ys).unsqueeze(self.dim - 1)
      else:
          l1 = torch.bmm(xs, ys.transpose(1, 2))
          if self.attn == "sqrt":
              d_k = ys.size(-1)
              l1 = l1 / math.sqrt(d_k)
      if mask_ys is not None:
          attn_mask = (mask_ys == 0).view(bsz, 1, y_len)
          attn_mask = attn_mask.repeat(1, x_len, 1)
          l1.masked_fill_(attn_mask, neginf(l1.dtype))
      l2 = F.softmax(l1, dim=self.dim, dtype=torch.float).type_as(l1)
      if values is None:
          values = ys
      lhs_emb = torch.bmm(l2, values)
  
      # # add back the query
      if self.residual:
          lhs_emb = lhs_emb.add(xs)
  
      if self.get_weights:
          return lhs_emb.squeeze(self.dim - 1), l2
      else:
          return lhs_emb.squeeze(self.dim - 1)
  
file_path: ParlAI/parlai/agents/transformer/modules/attention.py
imports: import math
  from typing import Dict, Tuple, Optional, Union
  import torch
  import torch.nn
  import torch.nn.functional
  from parlai.core.opt import Opt
  from parlai.core.params import default
  from parlai.utils.torch import neginf
label_desc: Use image node_id 2 for calling the BasicAttention obj's underlying member method code with example usage: obj.forward(xs, ys, mask_ys, values) and returns: lhs_emb,  l2, lhs_emb