class_docstr: This class defines the `MobileViTv2 <https://arxiv.org/abs/2206.02680>`_ block
  
  Args:
      opts: command line arguments
      in_channels (int): :math:`C_{in}` from an expected input of size :math:`(N, C_{in}, H, W)`
      attn_unit_dim (int): Input dimension to the attention unit
      ffn_multiplier (int): Expand the input dimensions by this factor in FFN. Default is 2.
      n_attn_blocks (Optional[int]): Number of attention units. Default: 2
      attn_dropout (Optional[float]): Dropout in multi-head attention. Default: 0.0
      dropout (Optional[float]): Dropout rate. Default: 0.0
      ffn_dropout (Optional[float]): Dropout between FFN layers in transformer. Default: 0.0
      patch_h (Optional[int]): Patch height for unfolding operation. Default: 8
      patch_w (Optional[int]): Patch width for unfolding operation. Default: 8
      conv_ksize (Optional[int]): Kernel size to learn local representations in MobileViT block. Default: 3
      dilation (Optional[int]): Dilation rate in convolutions. Default: 1
      attn_norm_layer (Optional[str]): Normalization layer in the attention block. Default: layer_norm_2d
code: def _build_attn_layer(
      self,
      opts,
      d_model: int,
      ffn_mult: Union[Sequence, int, float],
      n_layers: int,
      attn_dropout: float,
      dropout: float,
      ffn_dropout: float,
      attn_norm_layer: str,
      *args,
      **kwargs,
  ) -> Tuple[nn.Module, int]:
      if isinstance(ffn_mult, Sequence) and len(ffn_mult) == 2:
          ffn_dims = (
              np.linspace(
                  ffn_mult[0], ffn_mult[1], n_layers, dtype=float
              )
              * d_model
          )
      elif isinstance(ffn_mult, Sequence) and len(ffn_mult) == 1:
          ffn_dims = [ffn_mult[0] * d_model] * n_layers
      elif isinstance(ffn_mult, (int, float)):
          ffn_dims = [ffn_mult * d_model] * n_layers
      else:
          raise NotImplementedError
  
      # ensure that dims are multiple of 16
      ffn_dims = [int((d // 16) * 16) for d in ffn_dims]
  
      global_rep = [
          LinearAttnFFN(
              opts=opts,
              embed_dim=d_model,
              ffn_latent_dim=ffn_dims[block_idx],
              attn_dropout=attn_dropout,
              dropout=dropout,
              ffn_dropout=ffn_dropout,
              norm_layer=attn_norm_layer,
          )
          for block_idx in range(n_layers)
      ]
      global_rep.append(
          get_normalization_layer(
              opts=opts, norm_type=attn_norm_layer, num_features=d_model
          )
      )
  
      return nn.Sequential(*global_rep), d_model
  
imports: import math
  from typing import Dict, Optional, Sequence, Tuple, Union
  import numpy
  import torch
  from torch import Tensor, nn
  from torch.nn import functional
  from cvnets.layers import ConvLayer2d, get_normalization_layer
  from cvnets.modules.base_module import BaseModule
  from cvnets.modules.transformer import LinearAttnFFN, TransformerEncoder
label_desc: Use image node_id 3 for calling the MobileViTBlockv2 obj's underlying member method code with example usage: obj._build_attn_layer(opts, d_model, ffn_mult, n_layers, attn_dropout, dropout, ffn_dropout, attn_norm_layer) and returns: nn,  d_model