【问题标题】:How to count the amount of layers in a CNN?如何计算 CNN 中的层数?
【发布时间】:2017-08-27 19:07:56
【问题描述】:

ResNet-18 的 Pytorch 实现。 有如下结构,看起来是54层,而不是18层。

那为什么叫“18”呢?它实际上有多少层?


ResNet (
  (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
  (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True)
  (relu): ReLU (inplace)
  (maxpool): MaxPool2d (size=(3, 3), stride=(2, 2), padding=(1, 1), dilation=(1, 1))
  (layer1): Sequential (
    (0): BasicBlock (
      (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True)
      (relu): ReLU (inplace)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True)
    )
    (1): BasicBlock (
      (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True)
      (relu): ReLU (inplace)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True)
    )
  )
  (layer2): Sequential (
    (0): BasicBlock (
      (conv1): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True)
      (relu): ReLU (inplace)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True)
      (downsample): Sequential (
        (0): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True)
      )
    )
    (1): BasicBlock (
      (conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True)
      (relu): ReLU (inplace)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True)
    )
  )
  (layer3): Sequential (
    (0): BasicBlock (
      (conv1): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True)
      (relu): ReLU (inplace)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True)
      (downsample): Sequential (
        (0): Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True)
      )
    )
    (1): BasicBlock (
      (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True)
      (relu): ReLU (inplace)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True)
    )
  )
  (layer4): Sequential (
    (0): BasicBlock (
      (conv1): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True)
      (relu): ReLU (inplace)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True)
      (downsample): Sequential (
        (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True)
      )
    )
    (1): BasicBlock (
      (conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True)
      (relu): ReLU (inplace)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True)
    )
  )
  (avgpool): AvgPool2d (
  )
  (fc): Linear (512 -> 1000)
)

【问题讨论】:

  • 它被设计成 18 层,可能是通过实验,所以没有“为什么”我们可以告诉你。
  • 谢谢,但是必须有办法通过代码来统计层数,比如CNN,我们可以通过__init__()来统计层数,但是ResNet-18有layer1~4,每一层都会调用_make_layer(),就像上面的输出一样,有54层。
  • 我要做的是记录每一层的渐变,所以我需要弄清楚网络中有多少层。
  • 我觉得你想要的和你问的不一样。

标签: neural-network deep-learning pytorch resnet deep-residual-networks


【解决方案1】:

从您的输出中,我们可以知道有 20 个卷积层(一个 7x7 卷积层、16 个 3x3 卷积层和 3 个用于下采样的 1x1 卷积层)。基本上,如果忽略 1x1 conv,算上 FC(线性)层,层数是 18。

我还写了an example,介绍了如何通过 graphviz 在 pytorch 中可视化你的架构,希望它能帮助你理解你的架构。

【讨论】:

  • 谢谢,所以层数不严格?
  • 基本上我们通常只计算卷积层和全连接层的数量。但是在resnet中,我不确定是否应该计算shortcut卷积层。应该由作者自己定义。
【解决方案2】:

为什么 ResNet-18 有 18 层?

嗯,那么答案很简单,神经网络中的层数是一个超参数(意味着您可以根据需要对其进行调整)。在 ResNet 论文中,作者通过训练不同层的多个模型(如 18、34、50)来对准确性、错误率等进行适当的研究。因此他们遵循的命名约定是 ResNet-18、ResNet- 34、ResNet-50...

为什么 ResNet-18 的架构(您在问题中提供的)有超过 18 层?

人们计算深度神经网络模型层数的方法有很多种,有些人也计算输入/输出层数,有些人计算池化层数。

但是作者在 ResNet 论文中所做的方式是他们只计算了所有的卷积层和全连接层,没有别的。 但是你给出的模型架构,有18层以上! 只是因为1x1 convolution层,作者称它们为投影层,这些层仅用于将输入维度 (x) 与残差块的维度 (F(x)) 匹配,以便它们可以相加 (y=F(x)+x)。因此,如果不计算这些预测 (1x1 convs.),您会看到有 18 层,因此名称为 ResNet-18

【讨论】:

  • 你的解释很好,但是在ResNet-18中,原论文没有投影层。请相应地查看我的评论和您的答案。如果我们谈论 50,所有转化率。包括投影和全连接层在内的层数为 50。如果我错了,请纠正我...谢谢!
  • 我引用了原始论文:“我们考虑两个选项:(A) 快捷方式仍然执行恒等映射,为增加维度填充了额外的零条目。此选项没有引入额外的参数;(B) Eqn.(2) 中的投影快捷方式用于匹配维度(通过 1×1 卷积完成)。" -Page 4....可以看到他们提出了 2 个选项,如果您使用填充,则不需要投影,也不会花费您任何额外的参数或 (1x1) 卷积层,但是,在投影选项中,额外的 num.参数和转换层数。
猜你喜欢
  • 1970-01-01
  • 2015-07-23
  • 2021-09-24
  • 1970-01-01
  • 2020-09-19
  • 1970-01-01
  • 2020-04-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多