code: def test_MultiScaleAttention(self):
      seq_len = 21
      c_dim = 10
      c_dim_out = 20
  
      # Test MultiScaleAttention without dim expansion; i.e., no dim_out
      multiscale_attention = MultiScaleAttention(c_dim, num_heads=2)
      fake_input = torch.rand(8, seq_len, c_dim)
      input_shape = (2, 2, 5)
      output, output_shape = multiscale_attention(
          fake_input, input_shape
      )
      self.assertTrue(output.shape, fake_input.shape)
  
      # Test MultiScaleAttention with dim expansion
      multiscale_attention = MultiScaleAttention(
          c_dim, dim_out=c_dim_out, num_heads=2
      )
      fake_input = torch.rand(8, seq_len, c_dim)
      input_shape = (2, 2, 5)
      output, output_shape = multiscale_attention(
          fake_input, input_shape
      )
      gt_shape_tensor = torch.rand(8, seq_len, c_dim_out)
      self.assertTrue(output.shape, gt_shape_tensor.shape)
  
      # Test pooling kernel without dim expansion.
      multiscale_attention = MultiScaleAttention(
          c_dim,
          num_heads=2,
          stride_q=(2, 2, 1),
      )
      output, output_shape = multiscale_attention(
          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 dim expansion.
      multiscale_attention = MultiScaleAttention(
          c_dim,
          dim_out=c_dim_out,
          num_heads=2,
          stride_q=(2, 2, 1),
      )
      output, output_shape = multiscale_attention(
          fake_input, input_shape
      )
      gt_shape_tensor = torch.rand(8, 6, c_dim_out)
      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)
      multiscale_attention = MultiScaleAttention(
          c_dim, num_heads=2, stride_q=(2, 2, 1), has_cls_embed=False
      )
      output, output_shape = multiscale_attention(
          fake_input, input_shape
      )
      gt_shape_tensor = torch.rand(8, int(seq_len / 2 / 2), c_dim)
      gt_output_shape = [1, 1, 5]
      self.assertEqual(output.shape, gt_shape_tensor.shape)
      self.assertEqual(output_shape, gt_output_shape)
  
file_path: pytorchvideo/tests/test_layers_attention.py
imports: import itertools
  import unittest
  import torch
  import torch.nn
  from pytorchvideo.layers import Mlp, MultiScaleAttention, MultiScaleBlock
label_desc: Use image node_id 2 for calling the TestMLP obj's underlying member method code with example usage: obj.test_MultiScaleAttention() without return types