class_docstr: Implementation of a multiscale attention block. Compare to a conventional attention
  block, a multiscale attention block optionally supports pooling (either
  before or after qkv projection). If pooling is not used, a multiscale attention
  block is equivalent to a conventional attention block.
  
  ::
                                 Input
                                   |
                  |----------------|-----------------|
                  ↓                ↓                 ↓
                Linear           Linear            Linear
                  &                &                 &
               Pool (Q)         Pool (K)          Pool (V)
                  → -------------- ←                 |
                           ↓                         |
                     MatMul & Scale                  |
                           ↓                         |
                        Softmax                      |
                           → ----------------------- ←
                                       ↓
                                 MatMul & Scale
                                       ↓
                                    DropOut
code: def _qkv_proj(
      self,
      q: torch.Tensor,
      q_size: List[int],
      k: torch.Tensor,
      k_size: List[int],
      v: torch.Tensor,
      v_size: List[int],
      batch_size: List[int],
      chan_size: List[int],
  ) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
      q = (
          self.q(q)
          .reshape(
              batch_size,
              q_size,
              self.num_heads,
              chan_size // self.num_heads,
          )
          .permute(0, 2, 1, 3)
      )
      k = (
          self.k(k)
          .reshape(
              batch_size,
              k_size,
              self.num_heads,
              chan_size // self.num_heads,
          )
          .permute(0, 2, 1, 3)
      )
      v = (
          self.v(v)
          .reshape(
              batch_size,
              v_size,
              self.num_heads,
              chan_size // self.num_heads,
          )
          .permute(0, 2, 1, 3)
      )
      return q, k, v
  
imports: from typing import List, Optional, Tuple
  import numpy
  import torch
  import torch.fx
  import torch.nn
  from torch.nn.common_types import _size_3_t
  from .drop_path import DropPath
label_desc: Use image node_id 2 for calling the MultiScaleAttention obj's underlying member method code with example usage: obj._qkv_proj(q, q_size, k, k_size, v, v_size, batch_size, chan_size) and returns: q,  k,  v