class_docstr: ### Cross Attention Layer
  
  This falls-back to self-attention when conditional embeddings are not specified.
class_docstr_tok: ["#","#","#","Cross","Attention","Layer","This","falls-back","to","self-attention","when","conditional","embeddings","are","not","specified","."]
docstr: #### Normal Attention
  
  :param q: are the query vectors before splitting heads, of shape `[batch_size, seq, d_attn]`
  :param k: are the query vectors before splitting heads, of shape `[batch_size, seq, d_attn]`
  :param v: are the query vectors before splitting heads, of shape `[batch_size, seq, d_attn]`
docstr_tok: ["#","#","#","#","Normal","Attention",":","param","q",":","are","the","query","vectors","before","splitting","heads",",","of","shape","`","[","batch_size",",","seq",",","d_attn","]","`",":","param","k",":","are","the","query","vectors","before","splitting","heads",",","of","shape","`","[","batch_size",",","seq",",","d_attn","]","`",":","param","v",":","are","the","query","vectors","before","splitting","heads",",","of","shape","`","[","batch_size",",","seq",",","d_attn","]","`"]
code: def normal_attention(
      self, q: torch.Tensor, k: torch.Tensor, v: torch.Tensor
  ):
      """
      #### Normal Attention
  
      :param q: are the query vectors before splitting heads, of shape `[batch_size, seq, d_attn]`
      :param k: are the query vectors before splitting heads, of shape `[batch_size, seq, d_attn]`
      :param v: are the query vectors before splitting heads, of shape `[batch_size, seq, d_attn]`
      """
  
      # Split them to heads of shape `[batch_size, seq_len, n_heads, d_head]`
      q = q.view(*q.shape[:2], self.n_heads, -1)
      k = k.view(*k.shape[:2], self.n_heads, -1)
      v = v.view(*v.shape[:2], self.n_heads, -1)
  
      # Calculate attention $\frac{Q K^\top}{\sqrt{d_{key}}}$
      attn = torch.einsum("bihd,bjhd->bhij", q, k) * self.scale
  
      # Compute softmax
      # $$\underset{seq}{softmax}\Bigg(\frac{Q K^\top}{\sqrt{d_{key}}}\Bigg)$$
      if self.is_inplace:
          half = attn.shape[0] // 2
          attn[half:] = attn[half:].softmax(dim=-1)
          attn[:half] = attn[:half].softmax(dim=-1)
      else:
          attn = attn.softmax(dim=-1)
  
      # Compute attention output
      # $$\underset{seq}{softmax}\Bigg(\frac{Q K^\top}{\sqrt{d_{key}}}\Bigg)V$$
      out = torch.einsum("bhij,bjhd->bihd", attn, v)
      # Reshape to `[batch_size, height * width, n_heads * d_head]`
      out = out.reshape(*out.shape[:2], -1)
      # Map to `[batch_size, height * width, d_model]` with a linear layer
      return self.to_out(out)
  
imports: from typing import Optional
  import torch
  import torch.nn.functional
  from torch import nn
label_desc: Use image node_id 4 for calling the CrossAttention obj's underlying member method code with example usage: obj.normal_attention(q, k, v) and returns: self