3、深度学习基础回顾(下):卷积神经网络(CNN)原理、池化层、全连接层、感受野与特征图
好,咱们接着聊。上一节我们把神经网络的“骨架”搭好了,知道了数据怎么往前传、梯度怎么往回传。但说实话,如果只用全连接层去处理图像,那效率太低了。一张 256x256 的彩色图片,拉成一维向量就是 196,608 个像素点。第一层要是 1000 个神经元,光这一层的参数量就接近 2 亿。这谁扛得住?
所以,计算机视觉领域必须要有自己的“专用武器”——卷积神经网络(CNN)。我当年刚接触 CV 时,第一感觉就是:这玩意儿简直是给图像量身定做的。
核心思想:CNN 通过局部连接和权值共享,大幅降低了参数量,同时保留了图像的空间结构信息。说白了,它不再把图像看成是一堆孤立的像素点,而是看成有局部纹理、边缘、形状的“小区域”。
3.1 卷积层:图像特征的“扫描仪”
卷积层在做什么?你可以把它想象成一把小手电筒,在图像上滑动着照。每次只照一个局部小窗口(这个窗口就叫卷积核或滤波器),然后计算这个小窗口里的像素值和卷积核的“匹配程度”。
举个例子,一个 3x3 的卷积核,在 5x5 的输入上滑动,步长为 1,就会生成一个 3x3 的特征图。这个特征图上的每个值,都代表了原图某个局部区域与卷积核的响应强度。
# 一个简单的 2D 卷积操作(伪代码)
import numpy as np
input_image = np.random.randn(5, 5) # 假设输入是 5x5
kernel = np.array([[1, 0, -1],
[1, 0, -1],
[1, 0, -1]]) # 垂直边缘检测核
output_feature_map = np.zeros((3, 3))
for i in range(3):
for j in range(3):
# 提取局部区域
region = input_image[i:i+3, j:j+3]
# 点积运算
output_feature_map[i, j] = np.sum(region * kernel)
print(output_feature_map)
你看,代码其实不复杂。但这里有几个关键参数,我建议你记牢了:
| 参数 | 含义 | 我的经验 |
|---|---|---|
| 卷积核大小 | 通常 3x3 或 5x5 | YOLOv9 里几乎全是 3x3,效率高、堆叠效果好 |
| 步长 | 卷积核每次滑动的像素数 | 步长=2 可以快速降采样,但容易丢失细节 |
| 填充 | 在输入边缘补 0,控制输出尺寸 | 我习惯用 same 填充,保持特征图大小不变 |
| 通道数 | 卷积核的个数,决定输出特征图的深度 | 越深层的通道数越多,YOLOv9 的 backbone 通道数从 64 涨到 512 |
我的小技巧:刚开始调参时,别纠结步长和填充的数学公式。你只需要记住:输出尺寸 = (输入尺寸 - 卷积核大小 + 2 * 填充) / 步长 + 1。算不明白?直接写代码打印 shape 看看,比手算快多了。
3.2 池化层:降维打击,保留精华
卷积层提取完特征后,特征图往往还很大。这时候就需要池化层出场了。它的作用很简单:在局部区域内取一个代表值,把特征图“压缩”一下。
最常见的两种:
- 最大池化:取窗口内的最大值。我特别喜欢用它,因为它能保留最强烈的特征响应,比如边缘、角点。
- 平均池化:取窗口内的平均值。它更平滑,适合在网络的最后几层使用。
举个例子,一个 2x2 的最大池化,步长为 2,能把 4x4 的特征图直接压缩成 2x2。参数量?零。计算量?几乎可以忽略。这就是池化层的魅力——免费的下采样。
我曾经踩过的坑:有一回做小目标检测,用了太多池化层,结果小目标的特征被“池”没了。后来我改用步长为 2 的卷积来做下采样,效果好了不少。记住:池化层会丢失位置信息,对检测任务要慎用。
3.3 全连接层:特征整合器
卷积和池化把图像变成了高维特征图,但最终我们要输出类别概率或边界框坐标。这时候就需要全连接层来“收尾”。
全连接层会把前面展平的特征向量,通过矩阵乘法映射到输出空间。在 YOLOv9 里,全连接层用得不多,因为检测头通常用卷积来实现。但理解它的原理,对理解分类网络(比如 ResNet)很有帮助。
# 全连接层的前向传播
import torch.nn as nn
fc_layer = nn.Linear(in_features=512, out_features=10) # 512维 -> 10类
output = fc_layer(feature_vector) # 输出 logits
说白了,全连接层就是“把所有信息揉在一起,然后做决策”。但它的缺点也很明显:参数量巨大。一个 4096 到 1000 的全连接层,就有 400 万个参数。所以现代检测网络都在尽量用卷积替代全连接。
3.4 感受野:神经元在看多大范围?
这个概念特别重要,尤其是做目标检测时。感受野指的是特征图上的一个点,对应到输入图像上的区域大小。
你想想看,如果感受野太小,网络只能看到局部纹理,认不出大物体。如果感受野太大,又可能忽略细节。YOLOv9 的设计里,就特别注重感受野的平衡。
计算感受野有个递推公式:
r_out = r_in + (kernel_size - 1) * stride_in
其中 r_in 是上一层的感受野,stride_in 是之前所有步长的乘积。举个例子,两层 3x3 卷积(步长=1),感受野是 5x5。三层就是 7x7。所以堆叠小卷积核,可以高效扩大感受野。
关键结论:YOLOv9 的 backbone 通过堆叠 3x3 卷积和 ELAN 结构,让深层特征图拥有足够大的感受野,既能看清大目标,又不丢失小目标的细节。这就是它检测精度高的原因之一。
3.5 特征图:网络眼中的世界
特征图是 CNN 的“中间产物”。每一层卷积都会生成一组特征图,它们代表了网络从不同角度对图像的理解。
- 浅层特征图:关注边缘、颜色、纹理。比如一个垂直边缘检测核,会在特征图上“点亮”所有垂直边缘的位置。
- 中层特征图:开始组合出形状、部件。比如车轮、车窗、车灯。
- 深层特征图:抽象出完整的物体概念。比如“这是一辆车”。
YOLOv9 的一个创新点,就是通过 PGI(可编程梯度信息)机制,让浅层和深层的特征图能更好地协同工作。浅层提供精细的位置信息,深层提供丰富的语义信息,两者结合,检测效果自然更好。
3.6 本章小结:CNN 的核心三板斧
回顾一下,CNN 能成为 CV 领域的基石,靠的就是这三板斧:
- 卷积层:局部连接 + 权值共享,高效提取空间特征。
- 池化层:降采样,减少计算量,增强平移不变性。
- 全连接层:特征整合,输出最终结果(在检测网络里逐渐被卷积替代)。