第五章 深度学习 -- 卷积神经网络

第五章 卷积神经网络

一、卷积原理

1.1 卷积操作

卷积 (Convolution)是卷积神经网络(CNN)的核心运算。对图像等高维数据,全连接层有几个根本问题:参数爆炸(224×224 图像展平后 5 万维,接到 1024 维隐藏层就有 5000 万参数)、无法利用平移不变性(猫在图像左上角或右下角都应是同一只猫)、丢失空间结构信息(像素之间的相对位置)。

卷积的两个关键设计:

  • 局部连接(Local Connectivity):每个神经元只与输入的一个小区域(感受野,Receptive Field)相连,而不是全部输入。这模拟了「视觉皮层神经元只对视野中一小块区域敏感」的生物学事实。
  • 参数共享(Parameter Sharing):同一个卷积核(滤波器)在输入的所有位置上使用同一组权重。这直接利用了「猫的检测器不需要为图像的每个位置学习一个独立版本」的平移不变性。

二维卷积 。设输入为 X∈RH×WX \in \mathbb{R}^{H \times W}X∈RH×W,卷积核为 K∈Rkh×kwK \in \mathbb{R}^{k_h \times k_w}K∈Rkh×kw,则在位置 (i,j)(i, j)(i,j) 的输出为:

Y(i,j)=∑u=0kh−1∑v=0kw−1X(i+u,j+v)⋅K(u,v) Y(i, j) = \sum_{u=0}^{k_h-1} \sum_{v=0}^{k_w-1} X(i+u, j+v) \cdot K(u, v) Y(i,j)=u=0∑kh−1v=0∑kw−1X(i+u,j+v)⋅K(u,v)

更一般地,深度方向上对所有输入通道求加权和:

Yc′(i,j)=∑c=1Cin∑u,vXc(i+u,j+v)⋅Kc,c′(u,v)+bc′ Y_{c'}(i, j) = \sum_{c=1}^{C_{in}} \sum_{u, v} X_c(i+u, j+v) \cdot K_{c, c'}(u, v) + b_{c'} Yc′(i,j)=c=1∑Cinu,v∑Xc(i+u,j+v)⋅Kc,c′(u,v)+bc′

其中 c′c'c′ 是输出通道索引。每个输出通道 c′c'c′ 对应一个卷积核 K:,c′∈RCin×kh×kwK_{:, c'} \in \mathbb{R}^{C_{in} \times k_h \times k_w}K:,c′∈RCin×kh×kw。

PyTorch 实现:

python 复制代码
import torch
import torch.nn as nn

# 二维卷积
conv = nn.Conv2d(
    in_channels=3,        # 输入通道数(如 RGB 图像为 3)
    out_channels=64,      # 输出通道数(即卷积核个数)
    kernel_size=3,        # 卷积核尺寸 3x3,也可写 (3, 3)
    stride=1,             # 步幅
    padding=1,            # 填充
    bias=True,            # 是否使用偏置(默认 True)
)
x = torch.randn(8, 3, 224, 224)   # (B, C, H, W)
y = conv(x)                       # (8, 64, 224, 224)

关键参数:

  • in_channels:输入通道数。对图像,RGB 为 3;对特征图,等于上一层的 out_channels。
  • out_channels:本层卷积核数量,也是输出通道数。
  • kernel_size:卷积核边长,常用 1、3、5、7;3×3 是最常见的「甜点」尺寸。
  • stride:步幅,默认 1;大于 1 时会下采样。
  • padding:输入四周的零填充,默认 0;padding=1(对应 3×3 卷积)可保持输入输出尺寸一致。
  • dilation:空洞卷积的膨胀率,默认 1;>1 时扩大感受野而不增加参数。
  • groups:分组卷积,默认 1;= in_channels 时为 Depthwise 卷积。

卷积核尺寸的偏好。两个 3×3 卷积堆叠的感受野相当于一个 5×5,但参数更少(2 × 3² = 18 vs 5² = 25)、非线性更强(经过两次 ReLU)。VGG 论文系统比较了 3×3、5×5、7×7 组合,结论是「多层小卷积核」优于「单层大卷积核」。1×1 卷积虽不感受空间,但能跨通道做线性组合,常用于通道数调整(GoogLeNet、ResNet 的 Bottleneck)。

感受野(Receptive Field)。输出特征图上每个像素「看到」输入图像的面积。感受野随深度按乘法增长:两个 3×3 卷积堆叠,第二层每个像素的感受野是 5×5(对第一层输出),对应原始输入是 5×5。理解感受野对设计架构(确保深层神经元能「看到」足够大的区域)与诊断模型(为什么某个目标检测不到)都很重要。

反卷积(Transposed Convolution) 。又称转置卷积或分数步长卷积,常用于上采样(语义分割、生成模型)。它不是卷积的严格逆运算,而是把输入的每个元素与卷积核做加权求和后散布到更大的输出中。注意:反卷积的输出可能存在「棋盘格伪影」,现代实践中常被 Upsample + Conv 或 PixelShuffle 替代。

1.2 填充与步幅

填充(Padding)。在输入四周补零(或镜像、反射等其他策略),让卷积后输出尺寸可与输入相同,或精确控制到某个目标尺寸。

设输入 Hi×WiH_i \times W_iHi×Wi,卷积核 kh×kwk_h \times k_wkh×kw,步幅 sss,填充 ppp (单边宽度,总填充为 2p2p2p),则输出尺寸为:

Ho=⌊Hi+2p−khs⌋+1 H_{o} = \left\lfloor \frac{H_i + 2p - k_h}{s} \right\rfloor + 1 Ho=⌊sHi+2p−kh⌋+1

常见配置:

配置 效果 用途
kernel=3, padding=1, stride=1 尺寸不变 通用特征提取
kernel=5, padding=2, stride=1 尺寸不变 早期 CNN(LeNet、AlexNet)
kernel=3, padding=0, stride=1 尺寸减小 2 缩小特征图
kernel=3, padding=1, stride=2 尺寸减半 下采样
kernel=1, padding=0, stride=1 尺寸不变,仅通道调整 1×1 卷积

为什么需要 padding=1 保持尺寸 。深层 CNN 堆叠几十层,若每层都缩小,几层后特征图就太小(224 → 222 → 220 → ...),且边缘信息被逐渐「磨掉」。保持尺寸 + 配合步幅下采样,是现代 CNN 的标准做法。

PyTorch 自动 padding 。nn.Conv2d 的 padding 参数接受整数(均匀填充)或元组(分别为 H/W 指定)。功能相同的 nn.ZeroPad2d 等模块可显式填充,但不常用。

步幅(Stride) 。卷积核在输入上每次移动的距离。stride > 1 等价于先卷积再下采样,比「卷积 + MaxPool」节省计算。在 ResNet 的 Bottleneck 中,降采样常用 stride=2 的 3×3 卷积实现。

相同填充(Same Padding)与有效填充(Valid Padding)。这两个术语常在论文里出现:

  • Same Padding :填充后输出尺寸 = 输入尺寸(padding = (k-1)/2 当 stride=1)。
  • Valid Padding:不填充,输出尺寸 < 输入尺寸。

计算示例。输入 5×5,卷积核 3×3:

  • padding=0, stride=1:输出 3×3。
  • padding=1, stride=1:输出 5×5(保持)。
  • padding=0, stride=2:输出 2×2(不规则时按 floor 计算)。
  • padding=1, stride=2:输出 3×3。

1.3 池化

**池化(Pooling)**是下采样手段之一,对特征图局部区域做汇聚,降低空间分辨率。早期 CNN 把它当作标配,现代架构中部分被「步幅卷积」替代。

最大池化(Max Pooling)。取局部区域的最大值:

text 复制代码
输入 (单通道 4x4):
1  3  2  4
5  6  1  2
7  8  3  0
2  4  1  5

2x2 MaxPool, stride=2:
6  4
8  5

平均池化(Average Pooling)。取局部区域的平均值,平滑但容易模糊。

全局平均池化(Global Average Pooling, GAP) 。对每个通道整个特征图求平均,得到 CCC 维向量,直接用于分类。这是现代 CNN 取代全连接层的标配(Lin et al., 2013, NIN)。优点:

  • 显著减少参数(全连接层经常占总参数的 80%+)。
  • 强化特征图与类别置信度的对应关系(每个通道对应一个类别)。
  • 对输入尺寸更鲁棒。

PyTorch:

python 复制代码
max_pool = nn.MaxPool2d(kernel_size=2, stride=2)   # 默认 stride=kernel_size
avg_pool = nn.AvgPool2d(kernel_size=2, stride=2)
gap = nn.AdaptiveAvgPool2d(1)                      # 输出固定为 1x1,与输入尺寸无关

自适应池化(Adaptive Pooling) 。nn.AdaptiveAvgPool2d(output_size) 根据目标输出尺寸自动计算 kernel 与 stride,无论输入多大都能得到目标尺寸。在不同尺寸输入的迁移学习或检测中非常有用。

池化 vs 步幅卷积。两者都能降低空间分辨率,效果类似但有差异:

  • 池化是无参数的固定操作,不增加模型容量。
  • 步幅卷积有可学习参数,能学到更复杂的下采样。
  • 实践中:ResNet 之后,大多数架构用 stride=2 的卷积替代 MaxPool ;但首层前的 MaxPool2d(3, 2)(AlexNet 风格)仍常见。

为什么仍需要池化。即使有步幅卷积,池化仍有独特价值:

  • 强化局部平移不变性(对小幅平移/噪声不敏感)。
  • 显著降低计算量(尤其早期层)。
  • 某些语义任务(显著性检测、传统特征)更友好。

二、经典网络

2.1 LeNet 与 AlexNet

LeNet-5(LeCun et al., 1998)是 CNN 的开山之作,用于手写数字识别(MNIST)。结构:

text 复制代码
Input(32x32) → Conv(5x5, 6) → AvgPool → Conv(5x5, 16) → AvgPool → FC(120) → FC(84) → Output(10)

关键贡献:

  • 提出「Conv → Pool → Conv → Pool → FC」的基本范式。
  • 验证了「端到端学习」在手写数字识别上的可行性。
  • 受限于当时算力(无 GPU),网络规模很小。

AlexNet(Krizhevsky et al., 2012)是深度学习时代的起点。在 ImageNet 2012 比赛上,以 15.3% top-5 错误率夺冠,远低于第二名的 26.2%。

关键创新:

  • ReLU 激活取代 Sigmoid,缓解梯度消失,让更深网络可训练。
  • Dropout 减少过拟合。
  • 双 GPU 训练(当时单卡显存不够),这间接催生了现代分布式训练。
  • 数据增强(Random Crop、Horizontal Flip、Color Jitter)。
  • Local Response Normalization(LRN):现在已被 BN 取代。
  • 使用了 5 个卷积层 + 3 个全连接层,约 6000 万参数。
python 复制代码
import torchvision.models as models
alexnet = models.alexnet(weights='AlexNet_Weights.DEFAULT')

AlexNet 证明了「更深 + GPU + 大量数据」能让 CNN 显著超越传统方法,直接引发了 2012 年起的深度学习浪潮。

ZFNet(Zeiler & Fergus, 2013)是 AlexNet 的改进版,主要调整了超参数(第一层 11×11 卷积改为 7×7,步幅从 4 改为 2),并用可视化技术理解 CNN 内部表征,是「可解释性」早期工作。

2.2 VGG 与 ResNet

VGG(Simonyan & Zisserman, 2014, Visual Geometry Group, Oxford)系统研究了「深度」对 CNN 性能的影响,提出用「多层小卷积核堆叠」代替「大卷积核」。

核心设计:全部使用 3×3 卷积 + 2×2 MaxPool,堆叠 13-19 层。VGG-16 与 VGG-19 是最常用的版本。

贡献与影响:

  • 证明「小卷积核深堆叠」效果优于「大卷积核浅堆叠」。
  • 结构简单规整,易于理解和实现,成为后续很多工作的 baseline。
  • 缺点:参数巨大(VGG-16 有 1.38 亿参数,大部分在全连接层),推理慢,显存占用大。
  • 现代实践中已被 ResNet 等取代。

ResNet(He et al., 2015, Deep Residual Learning for Image Recognition, CVPR 2016 Best Paper)是 CNN 发展史上的关键转折,首次让「超百层」CNN 真正可训练,并横扫 ILSVRC 2015 全部赛道(分类、检测、定位、COCO 检测/分割)。

核心问题 :随着深度增加,「退化问题(degradation problem)」出现------更深网络的训练误差反而比浅层网络更高。这与过拟合不同(训练误差本身在增加),也不是普通的梯度消失(BN 已经在用)。它表明深层网络「难以优化」。

核心思想:残差连接 。把需要学习的映射 H(x)H(x)H(x) 改为 F(x)+xF(x) + xF(x)+x,其中 FFF 是堆叠的卷积层,+x+x+x 是恒等快捷连接(identity shortcut):

y=F(x,{Wi})+x y = F(x, \{W_i\}) + x y=F(x,{Wi})+x

  • 若最优 HHH 接近恒等映射,网络只需让 F→0F \to 0F→0------比「让 H→xH \to xH→x」容易得多(因为 F=0F=0F=0 是 L2 正则化的自然吸引点)。
  • 反向传播时,梯度 ∂L∂x\frac{\partial \mathcal{L}}{\partial x}∂x∂L 至少包含来自 shortcut 的 ∂L∂y\frac{\partial \mathcal{L}}{\partial y}∂y∂L 一份(不会因为 FFF 的梯度消失而归零)。

结构。ResNet 仍是 4-stage backbone,每 stage 由若干 residual block 堆叠。每个 stage 第一个 block 做下采样(stride=2 + 通道翻倍),后续 block 保持尺寸。

两种 block:

  • BasicBlock(用于 ResNet-18/34):两个 3×3 卷积。
  • Bottleneck(用于 ResNet-50/101/152):1×1(降维)→ 3×3 → 1×1(升维),减少参数与计算。

主流 ResNet 变体:

模型 Block 类型 堆叠数 层数 参数量
ResNet-18 BasicBlock (2,2,2,2) 18 11.7M
ResNet-34 BasicBlock (3,4,6,3) 34 21.8M
ResNet-50 Bottleneck (3,4,6,3) 50 25.6M
ResNet-101 Bottleneck (3,4,23,3) 101 44.5M
ResNet-152 Bottleneck (3,8,36,3) 152 60.2M

ResNet-50 是「性价比」最高的选择------参数比 ResNet-152 少很多,效果接近。

ResNet 在 ImageNet 2015 上以 3.57% top-5 错误率(6 模型集成)夺冠,首次明确超越人类水平(约 5%)。

残差连接的深远影响 。残差连接不仅解决了 CNN 的深度问题,其「y=F(x)+xy = F(x) + xy=F(x)+x」公式几乎一字不差地迁移到了 Transformer 的每个子层(后接 LayerNorm):

y=LayerNorm(x+Sublayer(x)) y = \text{LayerNorm}(x + \text{Sublayer}(x)) y=LayerNorm(x+Sublayer(x))

没有 ResNet 的「优化可训练性」遗产,Transformer 的几十层到几百层堆叠根本无法实现。残差连接是现代深度学习架构的隐藏支柱。

预激活 ResNet(He et al., 2016, Identity Mappings in Deep Residual Networks)将 BN+ReLU 放在卷积之前(Conv → BN → ReLU 顺序变成 BN → ReLU → Conv),让 shortcut 路径「完全干净」(不被 ReLU 污染),支持 1001 层网络的稳定训练。

ResNet 之后的重要 CNN:

  • ResNeXt(Xie et al., 2017):引入「分组卷积」与「cardinality」概念,在同等参数下表现优于 ResNet。
  • Wide ResNet(Zagoruyko & Komodakis, 2016):证明「加宽」比「加深」更划算,50 层宽 ResNet 可超过 152 层窄 ResNet。
  • DenseNet(Huang et al., 2017):每一层都连接到所有后续层,极致特征复用,但显存占用大。
  • MobileNet / EfficientNet:面向移动端的高效 CNN(深度可分离卷积、神经架构搜索)。
  • ConvNeXt(Liu et al., 2022):把 Swin Transformer 的设计思想回迁到纯 CNN,在 ImageNet 上达到与 Swin 相当的水平,证明「现代」CNN 仍可与 Transformer 比肩。
python 复制代码
import torchvision.models as models
resnet50 = models.resnet50(weights='ResNet50_Weights.DEFAULT')

三、实践要点

3.1 迁移学习

迁移学习 (Transfer Learning)是现代深度学习的核心工程范式之一:在大数据集 (如 ImageNet)上预训练的模型,在目标任务上微调,通常能显著优于从零训练。

为什么有效。预训练模型学到了「通用的视觉特征」(边缘、纹理、部件),这些特征对大多数视觉任务都有用。微调只需让模型把通用特征适配到任务特定的语义上。

两种主要策略:

1. 特征提取(Feature Extraction)。冻结预训练 backbone,只训练新加的分类头:

python 复制代码
import torchvision.models as models
import torch.nn as nn

backbone = models.resnet50(weights='ResNet50_Weights.DEFAULT')
for param in backbone.parameters():
    param.requires_grad = False        # 冻结 backbone

# 替换最后一层
backbone.fc = nn.Linear(backbone.fc.in_features, num_classes)
# backbone.fc 默认为可训练(requires_grad=True)
  • 适用:数据极少(数百到数千样本)、任务与预训练数据相似。
  • 优点:训练快,显存小,不易过拟合。
  • 缺点:在数据量充足时效果上限低于微调全部参数。

2. 微调(Fine-Tuning)。解冻全部(或部分)参数,用较小的学习率在目标数据上继续训练:

python 复制代码
backbone = models.resnet50(weights='ResNet50_Weights.DEFAULT')
# 全部参数默认 requires_grad=True,直接训练即可
backbone.fc = nn.Linear(backbone.fc.in_features, num_classes)

# 关键:对 backbone 用小学习率(如新分类头的 1/10)
optimizer = torch.optim.AdamW([
    {'params': backbone.fc.parameters(), 'lr': 1e-3},
    {'params': [p for n, p in backbone.named_parameters() if 'fc' not in n], 'lr': 1e-4},
], weight_decay=0.01)
  • 适用:数据量中等(数千到数万)、任务与预训练数据有差异。
  • 优点:上限更高。
  • 缺点:训练慢,显存大,有破坏预训练特征的风险(学习率过大时)。

3. 渐进解冻(Progressive Unfreezing)。先冻结 backbone,训练分类头 → 解冻最后几个 stage,继续训练 → 解冻全部,微调。NLP 预训练(ULMFiT, Howard & Ruder, 2018)首先提出,在视觉中也常有效。

学习率的选择(微调的核心):

  • 预训练模型参数:用小学习率(10−510^{-5}10−5 到 10−410^{-4}10−4),保留预训练知识。
  • 新分类头:用大学习率(10−310^{-3}10−3 到 10−410^{-4}10−4),快速适配任务。
  • 通用原则:学习率比从零训练小 10-100 倍。

数据量与策略对应:

目标数据量 推荐策略
< 1000 张 特征提取(冻结 backbone)
1000 - 10,000 微调顶层 + 渐进解冻
> 10,000 全部微调
> 100,000 考虑从零训练(若任务与预训练差异大)

输入尺寸的匹配。预训练模型通常在 224×224 上训练。微调时如果用 384×384,有两种方式:

  • 直接 resize 输入到 384×384(简单,但需要 backbone 能处理任何尺寸,全卷积网络 OK,带 FC 的需要 Global Average Pooling 替换 FC)。
  • 保持 224×224,简单粗暴。

预处理必须匹配 。ImageNet 预训练模型用 mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225] 做 Normalize。微调时必须用相同的统计量,否则模型会「看到」完全不同的输入分布,效果严重下降。若目标数据集与 ImageNet 差异大,可考虑用目标数据集本身的统计量重新 Normalize(但需要重新微调,不能直接用预训练权重)。

常用预训练模型库:

  • torchvision.models:ResNet、VGG、DenseNet、EfficientNet、ViT、Swin 等,集成度高,适合图像任务。
  • timm(PyTorch Image Models):Ross Wightman 维护,200+ 架构,持续更新,是研究界事实标准。
  • Hugging Face transformers:ViT、CLIP、Swin 等,适合多模态与 Transformer 架构。

保存与加载:

python 复制代码
# 保存
torch.save({
    'model_state_dict': model.state_dict(),
    'optimizer_state_dict': optimizer.state_dict(),
    'epoch': epoch,
    'best_acc': best_acc,
}, 'checkpoint.pth')

# 加载
checkpoint = torch.load('checkpoint.pth', map_location='cpu')
model.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])

只保存权重(不保存优化器状态)更轻量,适合纯推理部署:torch.save(model.state_dict(), 'model.pth')。

迁移学习的「保命」检查清单:

  • 确认输入预处理(mean/std、resize 尺寸)与预训练时一致。
  • 确认最后一层输出维度匹配目标类别数。
  • 用小学习率起步,密切观察 loss 曲线(若 loss 上升说明学习率过大)。
  • 数据量小时,先冻结 backbone 训练分类头,再解冻。
  • 监控验证集指标,早停(Early Stopping) 防止过拟合。

3.2 检测与分割(概念级)

本教程以图像分类为主线,但 CNN 的另外两大视觉任务------目标检测 与语义分割------值得建立概念级理解(细节超出本书范围):

目标检测(Object Detection) 。回答"图里有什么、在哪里":输出数量不定的 (类别, 边界框, 置信度) 集合。与分类的本质区别:输出不定长且含空间定位。

  • 两阶段(Faster R-CNN 家族):先用区域建议网络(RPN)筛出"可能有物体"的候选框,再对每个候选做分类与框精修。准但慢。
  • 单阶段(YOLO、SSD):一次前向直接在密集网格/锚点上回归框与类别。快,实时检测的主流。
  • Transformer 路线(DETR, 2020):把检测建模为集合预测,用二分图匹配取代手工设计的锚点与后处理。
  • 共同难点:正负样本极度不平衡(一张图的背景框远多于目标框)、分类与框回归的多任务权衡。

语义分割(Semantic Segmentation)。回答"每个像素属于什么类别":输出与输入同尺寸的逐像素类别图。

  • 核心矛盾:分类骨干不断下采样(分辨率越来越低),而分割需要像素级输出。
  • 编码器-解码器结构 :骨干当编码器,解码器逐级上采样恢复分辨率;跳跃连接(skip connection) 把编码器的高分辨率浅层特征直接传给解码器,补偿下采样丢失的空间细节。U-Net(Ronneberger et al., 2015)是这一结构的代表------它也是第八章扩散模型的主流骨干。
  • 实例分割(Mask R-CNN 等)进一步区分"同一类别的不同个体"。

三任务对比:

任务 输出 代表模型 共享方式
分类 单标签 ResNet、ViT 骨干直接输出
检测 不定数量的框 + 类别 YOLO、Faster R-CNN、DETR 骨干 + 检测头
分割 逐像素类别图 U-Net、DeepLab 骨干 + 解码器

理解"预训练骨干 + 任务特定头"这一模式,就抓住了现代视觉的工程结构------这也是 §3.1 迁移学习如此重要的原因。

相关推荐
水如烟1 小时前
孤能子视角:SEP《人工智能的认识论》EIS读法·理解——理解幻觉与解压缩幻觉:同一缺口,两份报告
人工智能
冬奇Lab2 小时前
一天一个开源项目(第249篇):Hallmark —— 一个拒绝“AI 味”的设计 Skill,用 48 套材质主题和浏览器 Linter 约束编程助手
人工智能·开源·资讯
GlobalInfo2 小时前
全球包装检测用3D轮廓传感器市场调研:2026年规模预计达1.87亿美元,食品医药与电商物流需求推动增长
大数据·人工智能·3d
paopaokaka_luck2 小时前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法
AI视频工具指南2 小时前
怎么用AI写爱情短剧?
人工智能
Jsundoku2 小时前
第四章 深度学习 -- 训练技巧
人工智能·深度学习
HDU-Dade3 小时前
【校招笔试真题】简要介绍 Self-Attention 的前沿算法
人工智能·算法
在所不辞兄3 小时前
【零基础学智能仿真-63】ABACUS作业工具与MCP接口
人工智能·深度学习·神经网络·机器学习·智能仿真
楚山之石3 小时前
【Medical Image Analysis】深度学习医学图像合成综述:伪CT、合成MRI与合成PET的架构、性能与临床边界
图像处理·人工智能·学习·mr·mri