ResNet-18的torch实现源码解读

ResNet-18的torch实现源码解读

  • Input: 3x224x224

  • Layer-0: conv1 + bn1 + relu + maxpool

    • conv1: 3->64通道。上下左右补3像素,卷积核7x7,步长2像素(尺寸减半112x112)。没有偏置项
    • bn1+relu: 先批归一化,再激活
    • maxpool: 上下左右补1像素,池化核3x3,步长为2(尺寸再减半56x56)
  • Layer-1: self._make_layer(block, 64, layers[0])

    1. BasicBlock-1
      • conv1: 64->64通道。上下左右补1像素,卷积核3x3,步长1像素。没有偏置项

      • bn1+relu: 先批归一化,再激活

      • conv2: 64->64通道。上下左右补1像素,卷积核3x3,步长1像素。没有偏置项

      • bn2: 批归一化

      • 残差连接: 由于特征图尺寸没变,因此直接相加即可(=本Block的输入+bn2的输出)

      • relu: 最后relu激活(先残差后激活)

    2. BasicBlock-2
      • conv1: 64->64通道。上下左右补1像素,卷积核3x3,步长1像素。没有偏置项

      • bn1+relu: 先批归一化,再激活

      • conv2: 64->64通道。上下左右补1像素,卷积核3x3,步长1像素。没有偏置项

      • bn2: 批归一化

      • 残差连接: 由于特征图尺寸没变,因此直接相加即可(=本Block的输入+bn2的输出)

      • relu: 最后relu激活(先残差后激活)

  • Layer-2: self._make_layer(block, 128, layers[1], stride=2, dilate=replace_stride_with_dilation[0])

    1. BasicBlock-1

      • conv1: 64->128通道。上下左右补1像素,卷积核3x3,步长2像素(尺寸减半28x28)。没有偏置项

      • bn1+relu: 先批归一化,再激活

      • conv2: 128->128通道。上下左右补1像素,卷积核3x3,步长1像素。没有偏置项

      • bn2: 批归一化

      • 残差连接: 由于特征图尺寸变化,因此要将本Block的输入做1x1卷积后,使得和bn2的输出相同尺寸后,再相加)

        • downsample
          • 对本Block的输入:64->128通道。做1x1卷积变换,步长2像素(尺寸减半28x28)。没有偏置项
          • 批归一化
      • relu: 最后relu激活(先残差后激活)

    2. BasicBlock-2

      • conv1: 128->128通道。上下左右补1像素,卷积核3x3,步长1像素。没有偏置项

      • bn1+relu: 先批归一化,再激活

      • conv2: 128->128通道。上下左右补1像素,卷积核3x3,步长1像素。没有偏置项

      • bn2: 批归一化

      • 残差连接: 由于特征图尺寸没变,因此直接相加即可(=本Block的输入+bn2的输出)

      • relu: 最后relu激活(先残差后激活)

  • Layer-3: self._make_layer(block, 256, layers[2], stride=2, dilate=replace_stride_with_dilation[1])

    1. BasicBlock-1

      • conv1: 128->256通道。上下左右补1像素,卷积核3x3,步长2像素(尺寸减半14x14)。没有偏置项

      • bn1+relu: 先批归一化,再激活

      • conv2: 256->256通道。上下左右补1像素,卷积核3x3,步长1像素。没有偏置项

      • bn2: 批归一化

      • 残差连接: 由于特征图尺寸变化,因此要将本Block的输入做1x1卷积后,使得和bn2的输出相同尺寸后,再相加)

        • downsample
          • 对本Block的输入:128->256通道。做1x1卷积变换,步长2像素(尺寸减半14x14)。没有偏置项
          • 批归一化
      • relu: 最后relu激活(先残差后激活)

    2. BasicBlock-2

      • conv1: 256->256通道。上下左右补1像素,卷积核3x3,步长1像素。没有偏置项

      • bn1+relu: 先批归一化,再激活

      • conv2: 256->256通道。上下左右补1像素,卷积核3x3,步长1像素。没有偏置项

      • bn2: 批归一化

      • 残差连接: 由于特征图尺寸没变,因此直接相加即可(=本Block的输入+bn2的输出)

      • relu: 最后relu激活(先残差后激活)

  • Layer-4: self._make_layer(block, 512, layers[3], stride=2, dilate=replace_stride_with_dilation[2])

    1. BasicBlock-1

      • conv1: 256->512通道。上下左右补1像素,卷积核3x3,步长2像素(尺寸减半7x7)。没有偏置项

      • bn1+relu: 先批归一化,再激活

      • conv2: 512->512通道。上下左右补1像素,卷积核3x3,步长1像素。没有偏置项

      • bn2: 批归一化

      • 残差连接: 由于特征图尺寸变化,因此要将本Block的输入做1x1卷积后,使得和bn2的输出相同尺寸后,再相加)

        • downsample
          • 对本Block的输入:256->512通道。做1x1卷积变换,步长2像素(尺寸减半7x7)。没有偏置项
          • 批归一化
      • relu: 最后relu激活(先残差后激活)

    2. BasicBlock-2

      • conv1: 512->512通道。上下左右补1像素,卷积核3x3,步长1像素。没有偏置项

      • bn1+relu: 先批归一化,再激活

      • conv2: 512->512通道。上下左右补1像素,卷积核3x3,步长1像素。没有偏置项

      • bn2: 批归一化

      • 残差连接: 由于特征图尺寸没变,因此直接相加即可(=本Block的输入+bn2的输出)

      • relu: 最后relu激活(先残差后激活)

  • Layer-fc:

    1. avgpool: nn.AdaptiveAvgPool2d((1, 1))保持通道数不变,将每个特征图平均池化为1x1尺寸
    2. flatten: torch.flatten(x, 1) 从维度1开始往后flatten,也就是将shape从(bs, 512, 1, 1)——>(bs, 512)
    3. fc: 最后将512映射为num_classes维度