注意:上面这张图最后fc4096应该是fc1000,画错了
总的来说,VGG16由13个卷积层和3个全连接层组成,一共16层(池化层不算层数,因为不包含需要学习的权重和偏置)。
其中的13个卷积层可以分成5个VGG块:
- 输入层:图片大小为
3×224×224
- 第1块:2个conv3-64组成(con3-64中3代表卷积核大小为3×3,64代表64个卷积核)
- 第一个卷积:64个3×3卷积核,padding=1,stride=1
输入:3×224×224
输出:64×224×224
再经过ReLu激活函数 - 第二个卷积:64个3×3卷积核,padding=1,stride=1
输入:64×224×224
输出:64×224×224
再经过ReLu激活函数 - 最大池化:2×2,stride=2,padding=0
输入:64×224×224
输出:64×112×112
- 第一个卷积:64个3×3卷积核,padding=1,stride=1
- 第2块:2个conv3-128组成
- 第一个卷积:128个3×3卷积核,padding=1,stride=1
输入:64×112×112
输出:128×112×112
再经过ReLu激活函数 - 第二个卷积:128个3×3卷积核,padding=1,stride=1
输入:128×112×112
输出:128×112×112
再经过ReLu激活函数 - 最大池化:2×2,stride=2,padding=0
输入:128×112×112
输出:128×56×56
- 第一个卷积:128个3×3卷积核,padding=1,stride=1
- 第3块:3个conv3-256组成
- 第一个卷积:256个3×3卷积核,padding=1,stride=1
输入:128×56×56
输出:256×56×56
再经过ReLu激活函数 - 第二个卷积:256个3×3卷积核,padding=1,stride=1
输入:256×56×56
输出:256×56×56
再经过ReLu激活函数 - 第三个卷积:256个3×3卷积核,padding=1,stride=1
输入:256×56×56
输出:256×56×56
再经过ReLu激活函数 - 最大池化:2×2,stride=2,padding=0
输入:256×56×56
输出:256×28×28
- 第一个卷积:256个3×3卷积核,padding=1,stride=1
- 第4块:3个conv3-512组成
- 第一个卷积:512个3×3卷积核,padding=1,stride=1
输入:256×28×28
输出:512×28×28
再经过ReLu激活函数 - 第二个卷积:512个3×3卷积核,padding=1,stride=1
输入:512×28×28
输出:512×28×28
再经过ReLu激活函数 - 第三个卷积:512个3×3卷积核,padding=1,stride=1
输入:512×28×28
输出:512×28×28
再经过ReLu激活函数 - 最大池化:2×2,stride=2,padding=0
输入:512×28×28
输出:512×14×14
- 第一个卷积:512个3×3卷积核,padding=1,stride=1
- 第5块:3个conv3-512组成
- 第一个卷积:512个3×3卷积核,padding=1,stride=1
输入:512×14×14
输出:512×14×14
再经过ReLu激活函数 - 第二个卷积:512个3×3卷积核,padding=1,stride=1
输入:512×14×14
输出:512×14×14
再经过ReLu激活函数 - 第三个卷积:512个3×3卷积核,padding=1,stride=1
输入:512×14×14
输出:512×14×14
再经过ReLu激活函数 - 最大池化:2×2,stride=2,padding=0
输入:512×14×14
输出:512×7×7
- 第一个卷积:512个3×3卷积核,padding=1,stride=1
- 全连接层1:先通过nn.Flatten()将512×7×7展开到25088
输入:25088
输出:4096
再经过ReLu激活函数
再经过dropout=0.5 - 全连接层2:
输入:4096
输出:4096
再经过ReLu激活函数
再经过dropout=0.5 - 全连接层3
输入:4096
输出:1000
- 最终输出层:
输入:1000
输出:2
(将 1000 维映射到 2 维,二分类任务:猫和狗)