CNN 卷积神经网络
图像识别的基石 — 从卷积操作到 ResNet
- 卷积层通过局部感受野和参数共享大幅减少参数量
- 池化层降低空间维度,增强平移不变性
- VGG 证明了"更深的网络 + 小卷积核"优于"浅层 + 大卷积核"
- ResNet 的残差连接解决了深层网络的退化问题
为什么需要 CNN?
假设我们有一张 224×224 的彩色图片,展平后有 224×224×3 = 150,528 个像素。 如果第一个隐藏层有 1000 个神经元,仅第一层就需要 1.5 亿个参数!这不仅计算量巨大,而且容易过拟合。
更重要的是,全连接层把像素展平,完全丢失了空间信息 — 它不知道哪些像素是相邻的,也无法识别局部特征(如边缘、纹理)。
类比:想象你第一次看一幅画 — 你不会同时注意每一个像素。 你会先看局部的纹理和线条,再组合成更大的形状,最后理解整幅画的内容。CNN 做的正是同样的事情。
CNN 的三大核心思想
局部感受野
每个神经元只看输入的一小块区域,而不是整个图像
权重共享
同一个卷积核在整张图上滑动,参数量大幅减少
池化
降低空间分辨率,提取主要特征,增强平移不变性
📊 卷积操作手推
下面展示一个 5×5 输入与 3×3 卷积核的运算过程。 点击单元格可以编辑输入值和卷积核!修改后特征图会自动更新。
输入 (5×5)
| 0 | 1 | 2 | 3 | 4 | |
|---|---|---|---|---|---|
| 0 | 1 | 0 | 1 | 0 | 1 |
| 1 | 0 | 1 | 0 | 1 | 0 |
| 2 | 1 | 0 | 1 | 0 | 1 |
| 3 | 0 | 1 | 0 | 1 | 0 |
| 4 | 1 | 0 | 1 | 0 | 1 |
卷积核 (3×3)
| 0 | 1 | 2 | |
|---|---|---|---|
| 0 | 1 | 0 | 1 |
| 1 | 0 | 1 | 0 |
| 2 | 1 | 0 | 1 |
当前步骤详情
输出特征图 (3×3) 点击单元格查看计算步骤
| 0 | 1 | 2 | |
|---|---|---|---|
| 0 | 4 | 2 | 4 |
| 1 | 2 | 5 | 2 |
| 2 | 4 | 2 | 4 |
💡 观察:卷积核在输入上滑动,每到一个位置就做逐元素相乘再求和。 3×3 的核在 5×5 的输入上滑动,输出是 3×3(即 5-3+1=3)。这就是卷积操作的本质!
📊 池化操作手推
池化(Pooling)用于降低空间分辨率。最常用的是最大池化(Max Pooling): 在每个 2×2 区域中取最大值。 点击输入单元格可以编辑!
输入 (4×4)
| 0 | 1 | 2 | 3 | |
|---|---|---|---|---|
| 0 | 1 | 3 | 2 | 4 |
| 1 | 5 | 6 | 1 | 2 |
| 2 | 3 | 2 | 8 | 7 |
| 3 | 4 | 1 | 3 | 5 |
Max Pooling 输出 (2×2)
| 0 | 1 | |
|---|---|---|
| 0 | 6 | 4 |
| 1 | 4 | 8 |
池化说明
💡 池化的作用: ① 降低维度,减少计算量; ② 提取主要特征,丢弃不重要的细节; ③ 提供平移不变性 — 即使目标稍微移动,池化后的输出也几乎不变。
🏗️ 经典架构演进
CNN 的发展经历了从简单到复杂的演进过程。每一个里程碑都带来了关键的创新。
LeNet-5
由 Yann LeCun 提出,是第一个成功的 CNN,用于手写数字识别(MNIST)。 它证明了卷积网络可以有效学习图像特征。
结构流程
32×32 → Conv1
6@28×28 → Pool1
6@14×14 → Conv2
16@10×10 → Pool2
16@5×5 → FC
120 → FC
84 → 输出
10
创新:首次成功将卷积 + 池化 + 全连接组合用于图像识别,奠定了 CNN 的基本架构。
VGG
VGG 的核心思想非常简单:用多个 3×3 小卷积核堆叠代替大卷积核。 例如,两个 3×3 卷积的感受野等价于一个 5×5,但参数更少、非线性更强。
VGG-16 简化结构
224×224 → 2×Conv
64 → Pool → 2×Conv
128 → Pool → 3×Conv
256 → ... → FC
1000
LeNet vs VGG 对比
| 特性 | LeNet-5 | VGG-16 |
|---|---|---|
| 深度 | 5 层 | 16 层 |
| 输入尺寸 | 32×32 | 224×224 |
| 卷积核 | 5×5 | 3×3 |
| 参数量 | ~60K | ~138M |
创新:证明了"更深 + 更小卷积核"比"更浅 + 更大卷积核"效果更好。
ResNet
网络越深,理论上应该越好。但实际上,超过一定深度后,训练误差反而上升(不是过拟合,是训练误差!)。 这是因为深层网络的梯度消失问题。
ResNet 的解决方案极其优雅:残差连接(Skip Connection)。 不直接学习目标映射 H(x),而是学习残差 F(x) = H(x) - x, 最终输出 F(x) + x。
残差块 (Residual Block)
VGG vs ResNet 对比
| 特性 | VGG-16 | ResNet-50 |
|---|---|---|
| 深度 | 16 层 | 50 层 |
| Skip Connection | 无 | 有 |
| 参数量 | ~138M | ~25M |
| Top-5 错误率 | 7.3% | 3.6% |
为什么残差连接有效?
- • 梯度高速公路:梯度可以通过 skip connection 直接回传,不经过非线性变换
- • 学习更容易:学习 F(x) ≈ 0 比学习 H(x) = x 更简单
- • 集成效果:ResNet 相当于多个不同深度网络的集成
DenseNet
DenseNet 把"连接"做到了极致:每一层都与前面所有层相连。 第 l 层的输入是前面所有层输出的拼接(concatenation),而不是相加。
🎮 互动实验:卷积参数探索
拖动滑块改变卷积参数,观察输出特征图尺寸如何变化。
💻 PyTorch 代码
import torch
import torch.nn as nn
# 2D 卷积层
conv = nn.Conv2d(
in_channels=3, # 输入通道数(RGB=3)
out_channels=16, # 输出通道数(卷积核个数)
kernel_size=3, # 卷积核大小 3×3
stride=1, # 步长
padding=1 # 填充(保持尺寸不变)
)
# 输入: (batch, channels, height, width)
x = torch.randn(1, 3, 32, 32) # 1张 32×32 RGB图
out = conv(x)
print(out.shape) # torch.Size([1, 16, 32, 32])
# 查看参数量
params = sum(p.numel() for p in conv.parameters())
print(f"参数量: {params}") # 448 = 3×16×3×3 + 16
# 最大池化层
pool = nn.MaxPool2d(
kernel_size=2, # 2×2 窗口
stride=2 # 步长=2,尺寸减半
)
x = torch.randn(1, 16, 32, 32)
out = pool(x)
print(out.shape) # torch.Size([1, 16, 16, 16])
# 自适应池化(输出固定尺寸)
adaptive_pool = nn.AdaptiveAvgPool2d((1, 1))
out = adaptive_pool(x)
print(out.shape) # torch.Size([1, 16, 1, 1])
class SimpleCNN(nn.Module):
def __init__(self):
super().__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 32, 3, padding=1), # 32×32→32×32
nn.ReLU(),
nn.MaxPool2d(2), # 32×32→16×16
nn.Conv2d(32, 64, 3, padding=1), # 16×16→16×16
nn.ReLU(),
nn.MaxPool2d(2), # 16×16→8×8
)
self.classifier = nn.Sequential(
nn.Flatten(), # 64×8×8 = 4096
nn.Linear(4096, 128),
nn.ReLU(),
nn.Linear(128, 10), # 10 类分类
)
def forward(self, x):
x = self.features(x)
x = self.classifier(x)
return x
# 使用
model = SimpleCNN()
x = torch.randn(1, 3, 32, 32)
print(model(x).shape) # torch.Size([1, 10])
🧠 小测验
- UNet — UNet 是 CNN 的编码器-解码器变体
- MLP — 卷积层是特殊的全连接层
- Autoencoder — 卷积自编码器的结构基础
1. 卷积操作的本质是什么?
2. ResNet 的核心创新是什么?
3. 池化的作用是什么?
📝 总结
卷积操作
局部感受野 + 权重共享,用小卷积核在图像上滑动提取特征。参数量远少于全连接层。
池化操作
降低空间分辨率,提取主要特征,提供平移不变性。最常用的是 2×2 最大池化。
架构演进
LeNet → VGG → ResNet → DenseNet。核心趋势:更深、更小卷积核、更好的梯度流。
核心思想
CNN 的核心是"局部特征提取 + 层次化组合" — 从边缘到纹理,从纹理到部件,从部件到物体。