class_docstr: MultiScaleAttention
class_docstr_tok: ["MultiScaleAttention"]
code: def relprop(self, cam, **kwargs):
      thw = kwargs.pop("thw")
      if self.drop_rate > 0.0:
          cam = self.proj_drop.relprop(cam, **kwargs)
      cam = self.proj.relprop(cam, **kwargs)
      cam = rearrange(cam, "b n (h d) -> b h n d", h=self.num_heads)
  
      # attn = A*V
      (cam1, cam_v) = self.matmul2.relprop(cam, **kwargs)
      cam1 /= 2
      cam_v /= 2
  
      self.save_v_cam(cam_v)
      self.save_attn_cam(cam1)
  
      cam1 = self.softmax.relprop(cam1, **kwargs)
  
      # A = Q*K^T
      (cam_q, cam_k) = self.matmul1.relprop(cam1, **kwargs)
      cam_q /= 2
      cam_k /= 2
  
      t = thw[0]
      kv_h = kv_w = int(math.sqrt(cam_k.shape[-2] - 1))
      cam_q, input_thw = self.atn_pool_q.relprop(
          cam_q, thw=thw, **kwargs
      )
      cam_k, _ = self.atn_pool_k.relprop(
          cam_k, thw=[t, kv_h, kv_w], **kwargs
      )
      cam_v, _ = self.atn_pool_v.relprop(
          cam_v, thw=[t, kv_h, kv_w], **kwargs
      )
  
      cam_qkv = rearrange(
          [cam_q, cam_k, cam_v],
          "qkv b h n d -> b n (qkv h d)",
          qkv=3,
          h=self.num_heads,
      )
  
      return self.qkv.relprop(cam_qkv, **kwargs), input_thw
  
imports: import math
  from functools import partial
  from typing import Tuple, List
  import numpy
  import torch
  from torch import nn
  from torch.nn.init import trunc_normal_
  from einops import rearrange
  from towhee.models.layers.layers_with_relprop import GELU, Linear, Dropout, Conv2d, Conv3d, Softmax, Sigmoid, LayerNorm, Einsum, Add, Clone, MaxPool3d, IndexSelect
label_desc: Use image node_id 13 for calling the MultiScaleAttention obj's underlying member method code with example usage: obj.relprop(cam) and returns: self,  input_thw