class_docstr: This class implements the inverted residual block with squeeze-excitation unit, as described in
  `MobileNetv3 <https://arxiv.org/abs/1905.02244>`_ paper
  
  Args:
      opts: command-line arguments
      in_channels (int): :math:`C_{in}` from an expected input of size :math:`(N, C_{in}, H_{in}, W_{in})`
      out_channels (int): :math:`C_{out}` from an expected output of size :math:`(N, C_{out}, H_{out}, W_{out)`
      expand_ratio (Union[int, float]): Expand the input channels by this factor in depth-wise conv
      dilation (Optional[int]): Use conv with dilation. Default: 1
      stride (Optional[int]): Use convolutions with a stride. Default: 1
      use_se (Optional[bool]): Use squeeze-excitation block. Default: False
      act_fn_name (Optional[str]): Activation function name. Default: relu
      se_scale_fn_name (Optional [str]): Scale activation function inside SE unit. Defaults to hard_sigmoid
      kernel_size (Optional[int]): Kernel size in depth-wise convolution. Defaults to 3.
      squeeze_factor (Optional[bool]): Squeezing factor in SE unit. Defaults to 4.
  
  Shape:
      - Input: :math:`(N, C_{in}, H_{in}, W_{in})`
      - Output: :math:`(N, C_{out}, H_{out}, W_{out})`
code: def __init__(
      self,
      opts,
      in_channels: int,
      out_channels: int,
      expand_ratio: Union[int, float],
      dilation: Optional[int] = 1,
      stride: Optional[int] = 1,
      use_se: Optional[bool] = False,
      act_fn_name: Optional[str] = "relu",
      se_scale_fn_name: Optional[str] = "hard_sigmoid",
      kernel_size: Optional[int] = 3,
      squeeze_factor: Optional[int] = 4,
      *args,
      **kwargs,
  ) -> None:
      hidden_dim = make_divisible(
          int(round(in_channels * expand_ratio)), 8
      )
      act_fn = build_activation_layer(
          opts, act_type=act_fn_name, inplace=True
      )
  
      super().__init__()
  
      block = nn.Sequential()
      if expand_ratio != 1:
          block.add_module(
              name="exp_1x1",
              module=ConvLayer2d(
                  opts,
                  in_channels=in_channels,
                  out_channels=hidden_dim,
                  kernel_size=1,
                  use_act=False,
                  use_norm=True,
              ),
          )
          block.add_module(name="act_fn_1", module=act_fn)
  
      block.add_module(
          name="conv_3x3",
          module=ConvLayer2d(
              opts,
              in_channels=hidden_dim,
              out_channels=hidden_dim,
              stride=stride,
              kernel_size=kernel_size,
              groups=hidden_dim,
              use_act=False,
              use_norm=True,
              dilation=dilation,
          ),
      )
      block.add_module(name="act_fn_2", module=act_fn)
  
      if use_se:
          se = SqueezeExcitation(
              opts=opts,
              in_channels=hidden_dim,
              squeeze_factor=squeeze_factor,
              scale_fn_name=se_scale_fn_name,
          )
          block.add_module(name="se", module=se)
  
      block.add_module(
          name="red_1x1",
          module=ConvLayer2d(
              opts,
              in_channels=hidden_dim,
              out_channels=out_channels,
              kernel_size=1,
              use_act=False,
              use_norm=True,
          ),
      )
  
      self.block = block
      self.in_channels = in_channels
      self.out_channels = out_channels
      self.exp = expand_ratio
      self.dilation = dilation
      self.use_se = use_se
      self.stride = stride
      self.act_fn_name = act_fn_name
      self.kernel_size = kernel_size
      self.use_res_connect = (
          self.stride == 1 and in_channels == out_channels
      )
  
file_path: ml-cvnets/cvnets/modules/mobilenetv2.py
imports: from typing import Optional, Union
  from torch import Tensor, nn
  from cvnets.layers import ConvLayer2d
  from cvnets.layers.activation import build_activation_layer
  from cvnets.modules import BaseModule, SqueezeExcitation
  from utils.math_utils import make_divisible
label_desc: Use image node_id 1 to create a new InvertedResidualSE object from inherited base classes: BaseModule with example: obj = InvertedResidualSE(opts, in_channels, out_channels, expand_ratio, dilation, stride, use_se, act_fn_name, se_scale_fn_name, kernel_size, squeeze_factor)