code: def test_multi_scale_attention(self):
      seq_len = 21
      c_dim = 10
      msa = MultiScaleAttention(c_dim, num_heads=2)
      fake_input = torch.rand(8, seq_len, c_dim)
      input_shape = (2, 2, 5)
      output, output_shape = msa(fake_input, input_shape)
      self.assertTrue(output.shape == fake_input.shape)
  
      # Test pooling kernel.
      msa = MultiScaleAttention(
          c_dim,
          num_heads=2,
          stride_q=(2, 2, 1),
      )
      output, output_shape = msa(fake_input, input_shape)
      gt_shape_tensor = torch.rand(8, 6, c_dim)
      gt_output_shape = [1, 1, 5]
      self.assertTrue(output.shape == gt_shape_tensor.shape)
      self.assertTrue(output_shape == gt_output_shape)
  
      # Test pooling kernel with no cls.
      seq_len = 20
      c_dim = 10
      fake_input = torch.rand(8, seq_len, c_dim)
      msa = MultiScaleAttention(
          c_dim, num_heads=2, stride_q=(2, 2, 1), has_cls_embed=False
      )
      output, output_shape = msa(fake_input, input_shape)
      gt_shape_tensor = torch.rand(8, int(seq_len / 2 / 2), c_dim)
      gt_output_shape = [1, 1, 5]
      self.assertTrue(output.shape == gt_shape_tensor.shape)
      self.assertTrue(output_shape == gt_output_shape)
  
imports: import unittest
  import torch
  from towhee.models.layers.multi_scale_attention import MultiScaleAttention
label_desc: Use image node_id 1 for calling the MultiScaleAttentionTest obj's underlying member method code with example usage: obj.test_multi_scale_attention() without return types