CNN经典架构:NiN、VGG、GoogleNet
发展时间线
AlexNet (2012) → NiN (2013) → VGG/GoogleNet (2014) → ResNet (2015)
这三个经典CNN架构都是在AlexNet之后、ResNet之前的重要里程碑,它们各自引入了影响深远的创新思想。
1. NiN (Network in Network, 2013)
核心思想
用 1×1 卷积增强局部感受野的非线性表达能力
创新点
1×1 卷积层(重要创新!)
# 传统卷积后直接激活
conv = nn.Conv2d(64, 128, kernel_size=3)
out = F.relu(conv(x))
# NiN:卷积后加 1×1 卷积(mlpconv层)
conv = nn.Conv2d(64, 128, kernel_size=3)
nin1 = nn.Conv2d(128, 128, kernel_size=1) # 1×1 卷积
nin2 = nn.Conv2d(128, 128, kernel_size=1) # 再一个 1×1
out = F.relu(nin2(F.relu(nin1(F.relu(conv(x))))))
1×1 卷积的作用:
- 跨通道信息融合(在同一空间位置,混合不同通道特征)
- 增加非线性(多加几个ReLU)
- 降维/升维(改变通道数)
全局平均池化(Global Average Pooling, GAP)
# 传统做法:展平 + 全连接
x = x.view(x.size(0), -1) # 展平
x = nn.Linear(7*7*512, 4096)(x) # 巨大的全连接层
x = nn.Linear(4096, 1000)(x)
# NiN 做法:全局平均池化
x = F.adaptive_avg_pool2d(x, (1, 1)) # 每个通道平均成一个值
x = x.view(x.size(0), -1) # 展平,无需全连接
GAP 的优势:
- 大幅减少参数:AlexNet 最后全连接层占总参数90%+
- 防止过拟合:没有那么多参数需要拟合
- 保持空间信息:每个通道对应一个类别的"置信度图"
网络结构示意
输入图像 (224×224×3)
↓
[Conv 11×11 → 1×1 Conv → 1×1 Conv] + ReLU + MaxPool
↓
[Conv 5×5 → 1×1 Conv → 1×1 Conv] + ReLU + MaxPool
↓
[Conv 3×3 → 1×1 Conv → 1×1 Conv] + ReLU + MaxPool
↓
[Conv 3×3 → 1×1 Conv → 1×1 Conv] + ReLU
↓
Global Average Pooling (1×1×1000)
↓
Softmax
影响
- 开创了 1×1 卷积的先河,后续网络(如GoogleNet、ResNet)大量使用
- GAP 成为标配,几乎所有现代网络都用
2. VGG (2014)
核心思想
更深的网络 + 简单重复的小卷积核
创新点
全部使用 3×3 小卷积
# 为什么用 3×3 而不是 7×7?
# 两个 3×3 卷积的感受野 = 一个 5×5
# 三个 3×3 卷积的感受野 = 一个 7×7
# 但参数量:
# 一个 7×7:C × C × 7 × 7 = 49C²
# 三个 3×3:3 × (C × C × 3 × 3) = 27C²
# 结论:3×3 更少参数,更多非线性(3个ReLU vs 1个)
深度优先策略
VGG-16/VGG-19:通过堆叠简单模块达到很深的深度
网络结构(VGG-16)
VGG16 = [
# Block 1: 64 通道
Conv3×3(64) → Conv3×3(64) → MaxPool,
# Block 2: 128 通道
Conv3×3(128) → Conv3×3(128) → MaxPool,
# Block 3: 256 通道
Conv3×3(256) → Conv3×3(256) → Conv3×3(256) → MaxPool,
# Block 4: 512 通道
Conv3×3(512) → Conv3×3(512) → Conv3×3(512) → MaxPool,
# Block 5: 512 通道
Conv3×3(512) → Conv3×3(512) → Conv3×3(512) → MaxPool,
# 全连接层
FC(4096) → FC(4096) → FC(1000)
]
特点:
- 规律性强:全是 3×3 卷积 + 2×2 池化
- 通道数翻倍:64 → 128 → 256 → 512
- 容易理解和实现
代码示例
class VGG16(nn.Module):
def __init__(self):
super().__init__()
# 每个block:若干3×3卷积 + MaxPool
self.block1 = nn.Sequential(
nn.Conv2d(3, 64, 3, padding=1),
nn.ReLU(),
nn.Conv2d(64, 64, 3, padding=1),
nn.ReLU(),
nn.MaxPool2d(2, 2)
)
self.block2 = nn.Sequential(
nn.Conv2d(64, 128, 3, padding=1),
nn.ReLU(),
nn.Conv2d(128, 128, 3, padding=1),
nn.ReLU(),
nn.MaxPool2d(2, 2)
)
# ... 更多 block
优缺点
优点:
- ✅ 结构简单,容易理解和实现
- ✅ 证明了"更深的网络 = 更好的性能"
- ✅ 迁移学习效果好(特征通用性强)
缺点:
- ❌ 参数量巨大(VGG-16:138M 参数,主要在全连接层)
- ❌ 计算量大,训练慢
- ❌ 内存占用高
3. GoogleNet / Inception v1 (2014)
核心思想
多尺度特征融合 + 降低计算量