docstr: Mobile Inverted Residual Bottleneck Block.
  
  Args:
      spatial_dims: number of spatial dimensions.
      in_channels: number of input channels.
      out_channels: number of output channels.
      kernel_size: size of the kernel for conv ops.
      stride: stride to use for conv ops.
      image_size: input image resolution.
      expand_ratio: expansion ratio for inverted bottleneck.
      se_ratio: squeeze-excitation ratio for se layers.
      id_skip: whether to use skip connection.
      norm: feature normalization type and arguments. Defaults to batch norm.
      drop_connect_rate: dropconnect rate for drop connection (individual weights) layers.
  
  References:
      [1] https://arxiv.org/abs/1704.04861 (MobileNet v1)
      [2] https://arxiv.org/abs/1801.04381 (MobileNet v2)
      [3] https://arxiv.org/abs/1905.02244 (MobileNet v3)
docstr_tok: ["Mobile","Inverted","Residual","Bottleneck","Block",".","Args",":","spatial_dims",":","number","of","spatial","dimensions",".","in_channels",":","number","of","input","channels",".","out_channels",":","number","of","output","channels",".","kernel_size",":","size","of","the","kernel","for","conv","ops",".","stride",":","stride","to","use","for","conv","ops",".","image_size",":","input","image","resolution",".","expand_ratio",":","expansion","ratio","for","inverted","bottleneck",".","se_ratio",":","squeeze-excitation","ratio","for","se","layers",".","id_skip",":","whether","to","use","skip","connection",".","norm",":","feature","normalization","type","and","arguments",".","Defaults","to","batch","norm",".","drop_connect_rate",":","dropconnect","rate","for","drop","connection","(","individual","weights",")","layers",".","References",":","[","1","]","https",":","\/\/arxiv.org\/abs\/1704.04861","(","MobileNet","v1",")","[","2","]","https",":","\/\/arxiv.org\/abs\/1801.04381","(","MobileNet","v2",")","[","3","]","https",":","\/\/arxiv.org\/abs\/1905.02244","(","MobileNet","v3",")"]
code: def __init__(
      self,
      spatial_dims: int,
      in_channels: int,
      out_channels: int,
      kernel_size: int,
      stride: int,
      image_size: list[int],
      expand_ratio: int,
      se_ratio: float | None,
      id_skip: bool | None = True,
      norm: str | tuple = ("batch", {"eps": 1e-3, "momentum": 0.01}),
      drop_connect_rate: float | None = 0.2,
  ) -> None:
      """
      Mobile Inverted Residual Bottleneck Block.
  
      Args:
          spatial_dims: number of spatial dimensions.
          in_channels: number of input channels.
          out_channels: number of output channels.
          kernel_size: size of the kernel for conv ops.
          stride: stride to use for conv ops.
          image_size: input image resolution.
          expand_ratio: expansion ratio for inverted bottleneck.
          se_ratio: squeeze-excitation ratio for se layers.
          id_skip: whether to use skip connection.
          norm: feature normalization type and arguments. Defaults to batch norm.
          drop_connect_rate: dropconnect rate for drop connection (individual weights) layers.
  
      References:
          [1] https://arxiv.org/abs/1704.04861 (MobileNet v1)
          [2] https://arxiv.org/abs/1801.04381 (MobileNet v2)
          [3] https://arxiv.org/abs/1905.02244 (MobileNet v3)
      """
      super().__init__()
  
      # select the type of N-Dimensional layers to use
      # these are based on spatial dims and selected from MONAI factories
      conv_type = Conv["conv", spatial_dims]
      adaptivepool_type = Pool["adaptiveavg", spatial_dims]
  
      self.in_channels = in_channels
      self.out_channels = out_channels
      self.id_skip = id_skip
      self.stride = stride
      self.expand_ratio = expand_ratio
      self.drop_connect_rate = drop_connect_rate
  
      if (se_ratio is not None) and (0.0 < se_ratio <= 1.0):
          self.has_se = True
          self.se_ratio = se_ratio
      else:
          self.has_se = False
  
      # Expansion phase (Inverted Bottleneck)
      inp = in_channels  # number of input channels
      oup = in_channels * expand_ratio  # number of output channels
      if self.expand_ratio != 1:
          self._expand_conv = conv_type(
              in_channels=inp,
              out_channels=oup,
              kernel_size=1,
              bias=False,
          )
          self._expand_conv_padding = _make_same_padder(
              self._expand_conv, image_size
          )
  
          self._bn0 = get_norm_layer(
              name=norm, spatial_dims=spatial_dims, channels=oup
          )
      else:
          # need to have the following to fix JIT error:
          #   "Module 'MBConvBlock' has no attribute '_expand_conv'"
  
          # FIXME: find a better way to bypass JIT error
          self._expand_conv = nn.Identity()
          self._expand_conv_padding = nn.Identity()
          self._bn0 = nn.Identity()
  
      # Depthwise convolution phase
      self._depthwise_conv = conv_type(
          in_channels=oup,
          out_channels=oup,
          groups=oup,  # groups makes it depthwise
          kernel_size=kernel_size,
          stride=self.stride,
          bias=False,
      )
      self._depthwise_conv_padding = _make_same_padder(
          self._depthwise_conv, image_size
      )
      self._bn1 = get_norm_layer(
          name=norm, spatial_dims=spatial_dims, channels=oup
      )
      image_size = _calculate_output_image_size(image_size, self.stride)
  
      # Squeeze and Excitation layer, if desired
      if self.has_se:
          self._se_adaptpool = adaptivepool_type(1)
          num_squeezed_channels = max(
              1, int(in_channels * self.se_ratio)
          )
          self._se_reduce = conv_type(
              in_channels=oup,
              out_channels=num_squeezed_channels,
              kernel_size=1,
          )
          self._se_reduce_padding = _make_same_padder(
              self._se_reduce, [1] * spatial_dims
          )
          self._se_expand = conv_type(
              in_channels=num_squeezed_channels,
              out_channels=oup,
              kernel_size=1,
          )
          self._se_expand_padding = _make_same_padder(
              self._se_expand, [1] * spatial_dims
          )
  
      # Pointwise convolution phase
      final_oup = out_channels
      self._project_conv = conv_type(
          in_channels=oup,
          out_channels=final_oup,
          kernel_size=1,
          bias=False,
      )
      self._project_conv_padding = _make_same_padder(
          self._project_conv, image_size
      )
      self._bn2 = get_norm_layer(
          name=norm, spatial_dims=spatial_dims, channels=final_oup
      )
  
      # swish activation to use - using memory efficient swish by default
      # can be switched to normal swish using self.set_swish() function call
      self._swish = Act["memswish"](inplace=True)
  
imports: from __future__ import annotations
  import math
  import operator
  import re
  from functools import reduce
  from typing import NamedTuple
  import torch
  from torch import nn
  from torch.utils import model_zoo
  from monai.networks.blocks import BaseEncoder
  from monai.networks.layers.factories import Act, Conv, Pad, Pool
  from monai.networks.layers.utils import get_norm_layer
  from monai.utils.module import look_up_option
label_desc: Use image node_id 1 to create a new MBConvBlock object from inherited base classes: nn with example: obj = MBConvBlock(spatial_dims, in_channels, out_channels, kernel_size, stride, image_size, expand_ratio, se_ratio, id_skip, norm, drop_connect_rate)