计算机视觉与深度学习-Lecture5 and Lecture6
Lecture 5:Image Classification with CNNs
卷积神经网络(Convolutional Neural Networks, CNNs)
传统的线性分类器使用单一的权重矩阵 WWW 尝试直接从原始像素映射到类别得分。而神经网络通过堆叠多层结构,将线性分类器进行泛化,使得模型能够学习到更加复杂的特征。
基于特征表示的图像分类(Feature Representation)
CNN 的核心思想是特征提取(Feature Extraction)。它不直接对原始像素进行分类,而是:
- 特征提取器(Feature Extractor):通过多层卷积与激活函数,将原始的低级图像像素(如边缘、颜色)转化为高水平的抽象语义表示。
- 分类器(Classifier):在网络末端使用全连接层(FC Layer)作为分类器,对提取出的高维特征进行分类。
卷积层(Convolutional Layer)
卷积层是 CNN 的核心构建块。它通过一组可学习的滤波器(Filters / 卷积核)对输入图像进行局部扫描。
1. 卷积操作与特征图(Feature Maps)
- 局部连接(Local Connectivity):每个滤波器在空间上(宽度和高度)都很小,但深度(Channels)必须与输入数据的深度完全一致。例如,输入图像尺寸为 32×32×332 \times 32 \times 332×32×3(RGB 三通道),则一个滤波器的尺寸可以是 5×5×35 \times 5 \times 35×5×3。
- 滑动与内积:滤波器在输入的宽度和高度上以一定的步长滑动,在每个位置计算滤波器权重与输入局部区域的点积(Dot Product),并加上一个偏置,最终生成一张二维的激活图(Activation Map / Feature Map)。
- 多通道堆叠:如果我们使用 KKK 个不同的滤波器,就会生成 KKK 张二维特征图。将它们在深度方向上堆叠起来,就得到了尺寸为 Height×Width×K\text{Height} \times \text{Width} \times KHeight×Width×K 的输出特征图。

- 非线性激活:由于卷积操作本身是纯线性的,为了让网络能够逼近非线性函数,每个卷积层后面必须紧跟一个激活函数(如 ReLU)。
2. 边界填充(Padding)与空间尺寸计算
当滤波器在输入上滑动时,会导致两个问题:
- 尺寸萎缩:每次经过卷积,特征图的空间尺寸(H 和 W)都会不断缩小。
- 边缘信息丢失:图像边缘的像素被滤波器扫过的次数远少于中心像素。
为了解决这两个问题,我们在输入图像的外圈填充零,这被称为 零填充(Zero-Padding, PPP)。
空间输出尺寸的核心计算公式:
对于输入尺寸为 WWW,滤波器尺寸为 FFF,步幅为 SSS,零填充为 PPP 的情况,输出尺寸 WoutW_{\text{out}}Wout 为:
Wout=W−F+2PS+1W_{\text{out}} = \frac{W - F + 2P}{S} + 1Wout=SW−F+2P+1
注意:计算结果必须为整数,否则说明该步幅/填充的配置在物理上无法整除滑动,框架会抛出异常或进行下取整处理。
3. 感受野(Receptive Field)
- 定义:特征图上的某一个像素,在输入图像(或前几层特征图)上所能“看到”的局部区域大小。
- 放大机制:随着网络层数的加深,感受野会逐步放大。虽然第一层卷积只能看到 3×33 \times 33×3 的局部局部,但第二层卷积在第一层的基础上再做 3×33 \times 33×3 卷积,实际上间接看到了输入图像上更广阔的区域。
- 快速增大感受野:引入步幅(Stride, S>1S > 1S>1)或空洞卷积(Dilated Convolution),可以让感受野以更快的速度覆盖整张图像。
池化层(Pooling Layer)
池化层是另一种实现下采样(Downsampling)、降低特征图空间尺寸的手段。
1. 工作原理
池化层独立地作用于每个通道。例如,对于一个尺寸为 64×224×22464 \times 224 \times 22464×224×224 的特征图,池化层会:
- 单独拿出每一个 224×224224 \times 224224×224 的二维通道进行空间上的缩水。
- 缩水完成后再按原顺序堆叠回去。
- 结果:保持通道数(646464)完全不变,但显著减小了空间尺寸(H 和 W)。

2. 常见池化方法
| 方法 | 英文 | 运作机制 | 物理/数学意义 |
|---|---|---|---|
| 最大池化 | Max Pooling | 在滑动窗口内取像素的最大值作为输出。 | 提取最强烈的特征信号,具有轻微的平移不变性。 |
| 平均池化 | Average Pooling | 在滑动窗口内计算所有像素的平均值。 | 保留整体背景或平滑信息,常用于网络末端(全局平均池化)。 |
卷积与池化在 CNN 中的关系与演进
- 经典架构:在传统的 CNN 架构(如 LeNet, AlexNet, VGG)中,通常采用“卷积层(提取特征) →\rightarrow→ 激活函数 →\rightarrow→ 池化层(下采样、减小计算量)”交替堆叠的模式。
- 现代趋势:在很多现代网络(如 ResNet)中,人们开始减少甚至放弃使用显式的池化层,而是直接通过设置卷积层的步幅 S=2S=2S=2(Stride=2)来直接实现下采样。
- 不变性结论:通过卷积(局部连接与权重共享)和池化,CNN 能够学习到具有平移不变性(Translation Invariance)的特征——即图像中某个特征(如猫的耳朵)无论出现在图像的左上角还是右下角,网络都能够识别出来,其特征表达不取决于其具体空间位置。
核心代码实现(PyTorch 风格)
以下是如何在 PyTorch 中定义带有激活和池化的经典卷积块:
Python
import torch
import torch.nn as nn
class SimpleCNNBlock(nn.Module):
def __init__(self):
super(SimpleCNNBlock, self).__init__()
# 定义一个卷积层:输入通道 3 (RGB), 输出通道 32, 卷积核 3x3, 步长 1, 填充 1
# 根据尺寸公式:W_out = (W - 3 + 2*1)/1 + 1 = W,空间尺寸保持不变
self.conv = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, stride=1, padding=1)
# 激活函数
self.relu = nn.ReLU()
# 最大池化层:窗口 2x2, 步长 2
# 空间尺寸直接减半 (H -> H/2, W -> W/2),通道数保持 32 不变
self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
def forward(self, x):
x = self.conv(x) # 卷积
x = self.relu(x) # 激活
x = self.pool(x) # 池化下采样
return x
Lecture 6:CNN Architectures & Training
一、 如何构建 CNN(How to Build CNNs?)
1. 卷积网络中的层(Layers in CNNs)
除了基础的卷积层、池化层和全连接层外,现代 CNN 还包含用于稳定训练和正则化的关键层:
- 层归一化(Layer Normalization, LN):在单个样本内部对该层所有激活值进行归一化。
- 第一步(规范化):利用当前层特征的均值 μ\muμ 和方差 σ2\sigma^2σ2 将其转换为标准正态分布:x^=x−μσ2+ϵ\hat{x} = \frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}}x^=σ2+ϵx−μ。
- 第二步(缩放与平移):引入可学习参数 γ\gammaγ 和 β\betaβ 恢复模型表达力:y=γx^+βy = \gamma \hat{x} + \betay=γx^+β。
- 随机失活(Dropout):一种在训练时引入随机性的正则化层。每次前向传播时以概率 ppp 随机将部分神经元置为 0,防止模型过拟合。在测试时,所有神经元保持常活(Always active),输出乘以 (1−p)(1-p)(1−p) 进行缩放。
2. 激活函数(Activation Functions)
用于向网络中引入非线性能力。常见激活函数对比如下:
- Sigmoid:f(x)=11+e−xf(x) = \frac{1}{1 + e^{-x}}f(x)=1+e−x1。容易导致梯度消失(Gradient Vanishing),现代网络中已很少在隐藏层使用。
- ReLU:f(x)=max(0,x)f(x) = \max(0, x)f(x)=max(0,x)。最常用的经典激活函数,计算极快,有效缓解梯度消失。
- GELU:f(x)=x⋅Φ(x)f(x) = x \cdot \Phi(x)f(x)=x⋅Φ(x)。高斯误差线性单元,融合了随机正则化思想,在现代视觉(如 ViT)和大语言模型中最为常用。
3. CNN 经典架构(CNN Architectures)
- AlexNet 与 VGG:早期经典网络。VGG 证明了通过模块化地反复堆叠小尺寸卷积核(如 3×33 \times 33×3)可以有效加深网络。
- 残差网络(ResNet):针对深层网络中“56层表现不如20层”的网络退化问题,何恺明老师提出了残差块(Residual Block)。它引入了跳跃连接(Skip Connection),让输入 xxx 跨越卷积层与输出相加。网络不再硬性学习理想映射 H(x)H(x)H(x),而是学习残差 F(x)=H(x)−xF(x) = H(x) - xF(x)=H(x)−x,从而保证即使网络极深,性能也绝不会退化。
4. 权重初始化(Weight Initialization)
错误的初始化会导致梯度消失或神经元对称。
-
何氏初始化(Kaiming / He Initialization):专为带有 ReLU 激活函数的深层网络设计。为了保持每层信号的方差稳定,随机采样权重的标准差应为:
σ=2in_features\sigma = \sqrt{\frac{2}{\text{in\_features}}}σ=in_features2
二、 如何训练 CNN(How to Train CNNs?)
1. 数据预处理(Data Preprocessing)
- 标准做法:对训练集进行标准化,算出每个像素通道(R, G, B)的平均值(Mean)**和**标准差(Std)。
- 工业惯例:在实际训练中,大家通常直接复用 ImageNet 数据集的经典均值和标准差对图像进行缩放与中心化。
2. 数据增强(Data Augmentation)
- 核心目的:在训练时通过对图像进行实时的随机几何或颜色变换,扩充数据集,提升模型的泛化能力。
- 常见手段:随机水平翻转(Horizontal Flip)、随机裁剪(Random Crop)、颜色抖动(Color Jitter)等。
3. 迁移学习(Transfer Learning)
现实中很少有人从头训练大型 CNN,通常会先在海量的 ImageNet 上完成预训练:
- 小数据集:冻结(Freeze)预训练模型除最后一层外的所有权重,仅重新训练最后一层全连接分类头(FC Head)。
- 大数据集:以极小的学习率放开部分或全部预训练层,在全新任务上进行微调(Fine-tuning)。
- 💡 进阶:LoRA 技术(低秩适应):微调时保持原模型大权重矩阵 W0W_0W0 冻结,在旁路引入两个极小的低秩矩阵 AAA 和 BBB(中间维度 r≪维度r \ll \text{维度}r≪维度)。更新量表示为 ΔW=B×A\Delta W = B \times AΔW=B×A,需要训练的参数量直接降低 99% 以上,大幅节省显存。
4. 超参数选择策略(Hyperparameter Selection)
寻找最优超参数(如学习率、正则化强度)的闭环五步法:
- 检查初始损失:关闭正则化,运行一轮前向传播,确保初始 Loss 符合数学预期(如 10 分类任务的交叉熵 Loss 应 ≈−ln(0.1)≈2.3\approx -\ln(0.1) \approx 2.3≈−ln(0.1)≈2.3)。
- 在小数据集上过拟合:仅用 5~20 个样本训练,若模型无法在几轮内让 Loss 降到 0(准确率 100%),说明代码逻辑或 LR 有严重错误。
- 寻找让 Loss 下降的学习率:使用全量数据并关闭正则化,测试一系列学习率(如 10−1,10−3,10−510^{-1}, 10^{-3}, 10^{-5}10−1,10−3,10−5),找出能让 Loss 快速平稳下降的区间。
- 粗网格搜索(Coarse Grid):在对数区间内挑选超参数组合,每组参数仅快速训练 1~5 个 Epoch,初步筛选出优秀范围。
- 精细网格搜索(Refine Grid):在筛选出的狭小范围内细化步长,延长训练时间。紧密观察 Loss 和准确率曲线,若验证集表现下滑(过拟合),则调大正则化或微调学习率,直到收敛。
(Coarse Grid)**:在对数区间内挑选超参数组合,每组参数仅快速训练 1~5 个 Epoch,初步筛选出优秀范围。 - 精细网格搜索(Refine Grid):在筛选出的狭小范围内细化步长,延长训练时间。紧密观察 Loss 和准确率曲线,若验证集表现下滑(过拟合),则调大正则化或微调学习率,直到收敛。
更多推荐




所有评论(0)