引言

卷积神经网络(Convolutional Neural Network, CNN)是深度学习在计算机视觉领域最成功的模型之一。从图像分类到目标检测,从语义分割到图像生成,CNN 无处不在。

1. 为什么需要 CNN

1.1 全连接网络的问题

对于 224×224224 \times 224 的 RGB 图像,展平后有 224×224×3=150,528224 \times 224 \times 3 = 150,528 个输入。如果第一个隐藏层有 1000 个神经元,则需要约 1.5 亿个参数!

问题

  1. 参数爆炸:参数过多导致过拟合和计算困难
  2. 忽略空间结构:展平操作丢失了像素的空间关系
  3. 缺乏平移不变性:同一物体在不同位置需要重新学习

1.2 CNN 的设计直觉

CNN 的核心思想来自视觉神经科学:

  • 局部感受野:神经元只对视野中的局部区域响应
  • 权值共享:相同的特征检测器用于整个图像
  • 层次化表示:从边缘到形状到物体的逐层抽象

2. 卷积运算

2.1 数学定义

对于输入 xx 和卷积核 ww,卷积运算(实际上是互相关):

(xw)(i,j)=mnx(i+m,j+n)w(m,n)(x * w)(i, j) = \sum_{m} \sum_{n} x(i+m, j+n) \cdot w(m, n)

2.2 卷积层参数

输入H×W×CinH \times W \times C_{in}(高度 × 宽度 × 输入通道)

卷积核K×K×Cin×CoutK \times K \times C_{in} \times C_{out}

输出大小

Hout=HK+2PS+1H_{out} = \frac{H - K + 2P}{S} + 1

其中:

  • KK:卷积核大小
  • PP:填充(padding)
  • SS:步幅(stride)

2.3 多通道卷积

对于 RGB 图像(3 通道),每个卷积核也有 3 层,分别与对应通道卷积后求和:

y=c=1Cinxcwc+by = \sum_{c=1}^{C_{in}} x_c * w_c + b

2.4 1×1 卷积

1×11 \times 1 卷积不改变空间尺寸,但可以:

  • 改变通道数:降维或升维
  • 增加非线性:每个卷积后跟激活函数
  • 跨通道信息交互

3. 池化层

3.1 最大池化

取窗口内的最大值:

y=max(m,n)windowx(i+m,j+n)y = \max_{(m,n) \in \text{window}} x(i+m, j+n)

作用

  • 降低空间分辨率
  • 提供一定的平移不变性
  • 减少计算量

3.2 平均池化

y=1W(m,n)Wx(i+m,j+n)y = \frac{1}{|W|} \sum_{(m,n) \in W} x(i+m, j+n)

3.3 全局平均池化 (GAP)

对整个特征图求平均,常用于分类网络的最后:

yc=1H×Wi,jxc(i,j)y_c = \frac{1}{H \times W} \sum_{i,j} x_c(i, j)

优点:无参数,减少过拟合。

4. 激活函数

4.1 ReLU

ReLU(x)=max(0,x)\text{ReLU}(x) = \max(0, x)

优点

  • 计算简单
  • 缓解梯度消失
  • 稀疏激活

问题:Dead ReLU(神经元永久失效)

4.2 Leaky ReLU

LeakyReLU(x)={xif x>0αxif x0\text{LeakyReLU}(x) = \begin{cases} x & \text{if } x > 0 \\ \alpha x & \text{if } x \leq 0 \end{cases}

4.3 GELU

GELU(x)=xΦ(x)\text{GELU}(x) = x \cdot \Phi(x)

其中 Φ\Phi 是标准正态分布的 CDF。在 Transformer 中广泛使用。

5. 经典 CNN 架构

5.1 LeNet-5 (1998)

1
2
3
4
5
6
Input (32×32×1)
↓ Conv 5×5, 6 filters → 28×28×6
↓ AvgPool 2×2 → 14×14×6
↓ Conv 5×5, 16 filters → 10×10×16
↓ AvgPool 2×2 → 5×5×16
↓ FC 120 → FC 84 → Output 10

5.2 AlexNet (2012)

ImageNet 竞赛的突破性工作,深度学习复兴的标志。

创新点

  • 使用 ReLU 激活函数
  • 使用 Dropout 防止过拟合
  • 数据增强(随机裁剪、翻转)
  • GPU 训练

5.3 VGGNet (2014)

核心思想:使用小卷积核(3×33 \times 3)堆叠代替大卷积核。

两个 3×33 \times 3 卷积 = 一个 5×55 \times 5 感受野,但参数更少:

2×(32)=18<52=252 \times (3^2) = 18 < 5^2 = 25

VGG-16 结构

1
2
3
4
5
6
[Conv3-64] × 2 → MaxPool
[Conv3-128] × 2 → MaxPool
[Conv3-256] × 3 → MaxPool
[Conv3-512] × 3 → MaxPool
[Conv3-512] × 3 → MaxPool
FC-4096 → FC-4096 → FC-1000

5.4 GoogLeNet/Inception (2014)

Inception 模块:并行使用不同大小的卷积核,然后拼接。

1
2
3
4
5
     Input
/ | | \
1×1 3×3 5×5 MaxPool
\ | | /
Concatenate

使用 1×11 \times 1 卷积降维减少计算量。

5.5 ResNet (2015)

核心创新:残差连接(Skip Connection)

y=F(x)+x\mathbf{y} = \mathcal{F}(\mathbf{x}) + \mathbf{x}

网络学习残差 F(x)=yx\mathcal{F}(\mathbf{x}) = \mathbf{y} - \mathbf{x},而不是直接学习 y\mathbf{y}

残差块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class ResidualBlock(nn.Module):
def __init__(self, channels):
super().__init__()
self.conv1 = nn.Conv2d(channels, channels, 3, padding=1)
self.bn1 = nn.BatchNorm2d(channels)
self.conv2 = nn.Conv2d(channels, channels, 3, padding=1)
self.bn2 = nn.BatchNorm2d(channels)

def forward(self, x):
identity = x
out = F.relu(self.bn1(self.conv1(x)))
out = self.bn2(self.conv2(out))
out += identity # 残差连接
return F.relu(out)

为什么有效

  • 梯度可以直接通过跳跃连接回传
  • 允许训练非常深的网络(152+ 层)
  • 隐式集成了不同深度的网络

6. 批量归一化

6.1 定义

对于 mini-batch 中的每个特征:

x^i=xiμBσB2+ϵ\hat{x}_i = \frac{x_i - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}}

yi=γx^i+βy_i = \gamma \hat{x}_i + \beta

其中 γ,β\gamma, \beta 是可学习参数。

6.2 作用

  1. 加速训练:允许更大的学习率
  2. 正则化效果:mini-batch 统计带来噪声
  3. 减少内部协变量偏移

7. PyTorch 实现

7.1 简单 CNN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import torch
import torch.nn as nn
import torch.nn.functional as F

class SimpleCNN(nn.Module):
def __init__(self, num_classes=10):
super().__init__()
# 卷积层
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
self.bn1 = nn.BatchNorm2d(32)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.bn2 = nn.BatchNorm2d(64)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
self.bn3 = nn.BatchNorm2d(128)

# 池化层
self.pool = nn.MaxPool2d(2, 2)

# 全连接层
self.fc1 = nn.Linear(128 * 4 * 4, 256)
self.fc2 = nn.Linear(256, num_classes)
self.dropout = nn.Dropout(0.5)

def forward(self, x):
# 卷积块 1: 32×32 → 16×16
x = self.pool(F.relu(self.bn1(self.conv1(x))))
# 卷积块 2: 16×16 → 8×8
x = self.pool(F.relu(self.bn2(self.conv2(x))))
# 卷积块 3: 8×8 → 4×4
x = self.pool(F.relu(self.bn3(self.conv3(x))))

# 展平
x = x.view(x.size(0), -1)

# 全连接
x = self.dropout(F.relu(self.fc1(x)))
x = self.fc2(x)
return x

7.2 使用预训练模型

1
2
3
4
5
6
7
8
9
10
11
12
13
import torchvision.models as models

# 加载预训练 ResNet-18
model = models.resnet18(pretrained=True)

# 替换最后一层进行微调
num_classes = 10
model.fc = nn.Linear(model.fc.in_features, num_classes)

# 冻结前面的层(可选)
for param in model.parameters():
param.requires_grad = False
model.fc.requires_grad = True

7.3 训练循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = SimpleCNN().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

for epoch in range(num_epochs):
model.train()
for images, labels in train_loader:
images, labels = images.to(device), labels.to(device)

optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()

# 验证
model.eval()
correct = 0
total = 0
with torch.no_grad():
for images, labels in val_loader:
images, labels = images.to(device), labels.to(device)
outputs = model(images)
_, predicted = torch.max(outputs, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()

print(f"Epoch {epoch+1}, Accuracy: {100*correct/total:.2f}%")

8. CNN 的理论理解

8.1 感受野

LL 层的感受野大小:

RFL=RFL1+(KL1)×i=1L1SiRF_L = RF_{L-1} + (K_L - 1) \times \prod_{i=1}^{L-1} S_i

深层神经元"看到"的输入区域更大。

8.2 特征可视化

浅层学习:边缘、颜色、纹理
中层学习:角点、形状、纹理组合
深层学习:物体部件、语义概念

8.3 平移等变性

卷积具有平移等变性:

Tt(fg)=(Ttf)gT_\mathbf{t}(f * g) = (T_\mathbf{t} f) * g

输入平移导致输出相同平移。

总结

CNN 的核心设计原则:

  1. 局部连接:减少参数,利用空间局部性
  2. 权值共享:同一特征检测器检测整张图
  3. 层次表示:从低级到高级特征逐层抽象
  4. 池化下采样:降低分辨率,增加感受野
  5. 残差连接:训练更深的网络

参考资料

  • LeCun, Y. et al. Gradient-based learning applied to document recognition, 1998
  • Krizhevsky, A. et al. ImageNet Classification with Deep Convolutional Neural Networks, 2012
  • He, K. et al. Deep Residual Learning for Image Recognition, 2015
  • CS231n: Convolutional Neural Networks