code: def __init__(
      self,
      in_channels=None,
      out_channels=None,
      nmasks=None,
      level=None,
      filter_size=None,
      debug=False,
      use_act=False,
      stride=1,
      act=None,
      unique_masks=False,
      mix_maps=None,
      train_masks=False,
      noise_type="uniform",
      input_size=None,
  ):
      super(PerturbLayer, self).__init__()
      self.nmasks = nmasks  # per input channel
      self.unique_masks = unique_masks  # same set or different sets of nmasks per input channel
      self.train_masks = train_masks  # whether to treat noise masks as regular trainable parameters of the model
      self.level = level  # noise magnitude
      self.filter_size = filter_size  # if filter_size=0, layers=(perturb, conv_1x1) else layers=(conv_NxN), N=filter_size
      self.use_act = use_act  # whether to use activation immediately after perturbing input (set it to False for the first layer)
      self.act = act_fn(
          act
      )  # relu, prelu, rrelu, elu, selu, tanh, sigmoid (see utils)
      self.debug = (
          debug  # print input, mask, output values for each batch
      )
      self.noise_type = noise_type  # normal or uniform
      self.in_channels = in_channels
      self.input_size = input_size  # input image resolution (28 for MNIST, 32 for CIFAR), needed to construct masks
      self.mix_maps = mix_maps  # whether to apply second 1x1 convolution after perturbation, to mix output feature maps
  
      if filter_size == 1:
          padding = 0
          bias = True
      elif filter_size in (3, 5):
          padding = 1
          bias = False
      elif filter_size == 7:
          stride = 2
          padding = 3
          bias = False
  
      if self.filter_size > 0:
          self.noise = None
          self.layers = nn.Sequential(
              nn.Conv2d(
                  in_channels,
                  out_channels,
                  kernel_size=filter_size,
                  padding=padding,
                  stride=stride,
                  bias=bias,
              ),
              nn.BatchNorm2d(out_channels),
              self.act,
          )
      else:
          noise_channels = in_channels if self.unique_masks else 1
          shape = (
              1,
              noise_channels,
              self.nmasks,
              input_size,
              input_size,
          )  # can't dynamically reshape masks in forward if we want to train them
          self.noise = nn.Parameter(
              torch.Tensor(*shape), requires_grad=self.train_masks
          )
          if noise_type == "uniform":
              self.noise.data.uniform_(-1, 1)
          elif self.noise_type == "normal":
              self.noise.data.normal_()
          else:
              print(
                  "\n\nNoise type {} is not supported / understood\n\n".format(
                      self.noise_type
                  )
              )
  
          if nmasks != 1:
              if out_channels % in_channels != 0:
                  print(
                      "\n\n\nnfilters must be divisible by 3 if using multiple noise masks per input channel\n\n\n"
                  )
              groups = in_channels
          else:
              groups = 1
  
          self.layers = nn.Sequential(
              # self.act,      #TODO orig code uses ReLU here
              # nn.BatchNorm2d(out_channels), #TODO: orig code uses BN here
              nn.Conv2d(
                  in_channels * self.nmasks,
                  out_channels,
                  kernel_size=1,
                  stride=1,
                  groups=groups,
              ),
              nn.BatchNorm2d(out_channels),
              self.act,
          )
          if self.mix_maps:
              self.mix_layers = nn.Sequential(
                  nn.Conv2d(
                      out_channels,
                      out_channels,
                      kernel_size=1,
                      stride=1,
                      groups=1,
                  ),
                  nn.BatchNorm2d(out_channels),
                  self.act,
              )
  
imports: import torch
  import torch.nn
  import torch.nn.functional
label_desc: Use image node_id 1 to create a new PerturbLayer object from inherited base classes: nn with example: obj = PerturbLayer(in_channels, out_channels, nmasks, level, filter_size, debug, use_act, stride, act, unique_masks, mix_maps, train_masks, noise_type, input_size)