状态:草稿(2026-10-13),部分实测。 示例是在笔记本电脑 CPU(Python 3.9,numpy 2.0)上直接运行测得的值。代码位于此文件夹的
code/01_conv.py中,几秒钟即可运行完毕。论文中的数值是查阅原文并连同条件一起摘录的。 写作规则:以实测数据为基础,无法测量的内容标记为「未实测」。
目录
- 1. 为什么图像需要特殊的结构
- 2. 卷积:滑动小窗口进行乘加运算
- 3. 滤波器不是手动设定的:损失、反向传播与梯度下降
- 4. 池化与感受野:单个单元的视野范围
- 5. LeNet-5(1998):卷积 + 池化 + 反向传播的原型
- 6. AlexNet(2012):相同的思想,不同的规模
- 7. 局限性
- 8. 与我们项目的联系
- 参考文献
1. 为什么图像需要特殊的结构
手机上的一张照片包含数百万个数字(像素)。如果将这些输入投入普通的神经网络,即 全连接层(每个输入都连接到每个输出的层),连接数量就会呈指数级暴增。仅看单个将 32×32 黑白图像转换为 28×28 大小的 6 个特征图的层,情况即是如此。
| 方式 | 需要学习的数字(权重) |
|---|---|
| 全连接层 | 4,821,600 个 |
| 6 个 5×5 卷积滤波器 | 156 个 |
(直接计算, code/01_conv.py [5]. 卷积为 6 个滤波器 × (25 + 偏置 1)。)
之所以会产生 3 万倍的差异,是因为图像具有以下两种性质。
- 相邻像素之间的关联性很深(局部性)。 要识别球的轮廓,并不需要用到画面对角角落的像素。
- 相同的图案无论出现在哪里都是相同的图案(平移不变性)。 屏幕左侧的球和右侧的球可以用相同的方法来查找。
卷积是将这两种假设写入结构中的运算。它只观察小窗口(局部性),并将相同的滤波器应用于整个图像(权重共享)。这种「将假设融入结构」的做法被称为 归纳偏置,在第 7 篇中我们将看到 Vision Transformer 正是因为抛弃了这一点而付出了什么代价。
2. 卷积:滑动小窗口进行乘加运算
计算过程很简单。将 3×3 滤波器(9 个数字)重叠到图像的 3×3 窗口上,将对应位置相乘并全部相加,就能得到一个输出单元。逐个单元滑动窗口并重复此过程,即可完成输出特征图。
# code/01_conv.py 에서
def conv2d(x, k):
kh, kw = k.shape
out = np.empty((x.shape[0] - kh + 1, x.shape[1] - kw + 1))
for i in range(out.shape[0]):
for j in range(out.shape[1]):
out[i, j] = np.sum(x[i:i + kh, j:j + kw] * k)
return out
当我们将垂直边界滤波器(索贝尔滤波器)应用到一个左半部分为 0(暗)、右半部分为 1(亮)的 6×6 图像时,结果如下(实测)。
필터 출력(4×4)
[-1 0 1] [0 4 4 0]
[-2 0 2] [0 4 4 0]
[-1 0 1] [0 4 4 0]
[0 4 4 0]
仅在亮度发生变化的边界处输出为 4,其余部分为 0。滤波器是一个提出「这种图案在这里吗?」的疑问,而输出特征图则是将该疑问的答案铺展到整张图像上。实际的网络会在单层中放置数十到数百个这样的滤波器,每个滤波器寻找不同的图案(水平边界、对角线、色块等)。
另外,深度学习框架所称的「卷积」与数学教科书中的卷积不同,它是不翻转滤波器的 互相关运算。由于滤波器无论如何都是通过学习确定的,因此翻转与否并没有区别。
3. 滤波器不是手动设定的:损失、反向传播与梯度下降
早期的计算机视觉像上面的索贝尔滤波器一样由人工设计滤波器。CNN 的核心在于 从数据中学习滤波器的数字。学习方法分为三个步骤。
- 损失函数:通过一个数字来衡量当前滤波器产生的输出与正确答案相差多少。这里使用的是均方误差(MSE)。
- 反向传播:计算如果稍微改变滤波器中的 9 个数字中的每一个,损失会发生多大变化(梯度)。对于卷积而言,将「输出误差」与「输入」再次进行卷积即可得到滤波器的梯度。
- 梯度下降:沿着梯度的反方向稍微移动滤波器。
k ← k − 학습률 × 기울기.
# code/01_conv.py 에서 — 필터 k 의 기울기
for x, y in zip(X, Y):
err = conv2d(x, k) - y # 출력 오차
for a in range(3):
for b in range(3):
g[a, b] += np.mean(2 * err * x[a:a + err.shape[0], b:b + err.shape[1]])
k -= lr * g
动手实践:随机滤波器如何变成索贝尔滤波器
我们让 32 张随机图像通过索贝尔滤波器以生成「正确答案输出」,在不知道正确答案滤波器的情况下,从随机滤波器(均值 0,标准差 0.1)出发,以 0.1 的学习率进行梯度下降(实测,笔记本电脑 CPU 约 6 秒)。
| 步数 | 损失(MSE) |
|---|---|
| 0 | 1.064 |
| 10 | 0.730 |
| 50 | 0.193 |
| 100 | 0.037 |
| 200 | 0.0013 |
| 500 | 0.000000 |
经过 500 步学习到的滤波器是 [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]] ,与正确答案的最大差异为 0.0005。尽管没有人对它说「去寻找垂直边界」,但由于数据需要这样的滤波器,滤波器最终便呈现出了这种形状。如果我们把实际 CNN 第一层的滤波器画成图,边界和色块图案会浮现出来,原因也是如此。
为了验证通过反向传播求得的梯度是否正确,我们将其与 数值微分(通过稍微改变一个数字来直接测量损失变化的方法)进行了比较。最大相对误差一致,达到 6.4×10⁻¹¹。这是在信任自己编写的学习代码之前总值得做的一项检查。
4. 池化与感受野:单个单元的视野范围
卷积单层的一个输出单元仅观察输入的 3×3 区域。要识别整个球或运动员的手臂,必须看得更广。方法有两种。
- 堆叠层数。 在 3×3 之上叠放 3×3,上一层的一个单元就能看到下一层的 3×3,即输入的 5×5。
- 缩小(池化与步幅)。 将 2×2 个单元合并为一个(取最大值或平均值),相同的滤波器就能看到两倍宽的范围。
输出单元受输入影响的范围称为 感受野。每层按 r ← r + (커널 − 1) × j, j ← j × 보폭 进行计算(j 为累积步幅)。如果用 LeNet-5 和 AlexNet 的架构来计算,结果如下(直接计算, code/01_conv.py [4]).
| 网络 | 穿过各层的感受野(px) | 最终 |
|---|---|---|
| LeNet-5 | 5 → 6 → 14 → 16 → 32 | 输入 32×32 全部 |
| AlexNet | 11 → 19 → 51 → 67 → 99 → 131 → 163 → 195 | 输入 224×224 的绝大部分 |
池化也是有代价的。降低分辨率会让人类和模型失去 精确位置。虽然对于分类(「这幅图里有猫吗」)来说这不是问题,但对于需要以像素级精度知道球的坐标的任务来说却是致命的。第 3 篇(U-Net·HRNet)正是处理这个问题的。
5. LeNet-5(1998):卷积 + 池化 + 反向传播的原型
LeCun 等人在 1998 年的论文中介绍了用于识别手写数字(MNIST)的 LeNet-5。输入为 32×32 黑白图像。数据中的数字最大也不过 20×20 并且位于 28×28 方格的中央,但他们故意将输入设得更大(这与上述感受野计算中最后一层看到整个 32×32 输入相契合)。
- 结构:卷积(C1)→ 子采样(S2)→ 卷积(C3)→ 子采样(S4)→ 卷积(C5)→ 全连接 → 输出。除去输入,共有 7 层。
- 规模:连接数为 340,908 个,但 需要学习的数字约为 6 万个。这归功于权重共享。
- 结果(论文):MNIST 测试集错误率为 0.95%。当向 6 万张训练数据中添加通过几何变形(平移、缩放、扭曲、倾斜)生成的 54 万张图像后,错误率降至 0.8% 。
这篇论文展示的是:「特征无需人工设计,可以通过卷积结构和反向传播从头到尾进行学习」。然而,受限于 1998 年的算力和数据,很难处理超出如手写数字般小巧清晰的图像。
6. AlexNet(2012):相同的思想,不同的规模
14 年后,Krizhevsky、Sutskever 和 Hinton 的 AlexNet 在 ImageNet 竞赛(ILSVRC,1000 个类别,约 120 万张训练图像)中以巨大优势获胜。其结构思想与 LeNet 相同,改变的是规模和一些学习技巧。
| 项目 | AlexNet(论文) |
|---|---|
| 规模 | 6000 万个参数,65 万个神经元,5 层卷积 + 3 层全连接 |
| 输入 | 224×224×3 |
| 训练 | 将网络拆分部署在当时的两张桌面 GPU(3GB 内存)上,历时 5–6 天,将 120 万张图像迭代约 90 次 |
| ILSVRC-2012 测试 top-5 错误率 | 15.3%(7 个 CNN 的集成)对比第 2 名的 26.2%。单模型验证集为 18.2% |
| ILSVRC-2010 测试 | top-1 37.5%,top-5 17.0%(测试时 10 个裁剪画面的平均值) |
「top-5 错误率」是指模型选出的前 5 个答案中没有正确答案的比例。15.3% 是集成模型的数据,这是一个经常被漏掉的条件。
通过查看论文中实际测量的内容,可以看出是什么造成了差异以及「为什么要这样设计」。
- ReLU。 将激活函数从 tanh 替换为
max(0, x)后,4 层 CNN 在 CIFAR-10 上达到 25% 训练错误率的速度加快了 6 倍 (论文图 1)。当数值较大时,tanh 的梯度接近于 0,而 ReLU 在正数方向上的梯度始终为 1。要在有限的时间内训练大型网络,这种差异是决定性的。 - 数据增强。 从 256×256 的图像中随机裁剪出 224×224 并进行左右翻转,实际上将训练数据增加了 2048 倍。沿主成分方向抖动颜色的增强使得 top-1 错误率降低了 1% 以上。论文解释说,如果没有增强,6000 万个参数将会把数据死记硬背下来。
- Dropout。 在训练期间以 0.5 的概率关闭全连接层的神经元。这使得神经元无法过分依赖彼此,从而减少了过拟合。但代价是收敛所需的迭代次数大约翻倍。
- 重叠池化(窗口 3,步幅 2)将 top-1/top-5 错误率降低了 0.4%/0.3%, 局部响应归一化降低了 1.4%/1.2%。局部响应归一化后来被批归一化(第 2 篇)取代,几乎不再使用。
- GPU。 由于卷积涉及大量重复的相同计算,因此非常适合 GPU 的并行运算。由于内存不足而将网络平分到两个 GPU 上的做法也是这篇论文的著名亮点。
总结来说,AlexNet 给我们的教训不是「某一个新点子」,而是 大数据 + 快速计算 + 使大型网络得以训练的各种技巧的组合。此后十年的视觉模型大都建立在这个公式之上。
7. 局限性
- 丢失位置。 反复进行池化有利于分类,但会使精确的位置信息变得模糊(第 3 篇)。
- 难以进行深层堆叠。 AlexNet 只有 8 层。如果堆叠得更深,反而会出现无法训练的问题,解决这一问题的是 ResNet(第 2 篇)。
- 需要大量标签。 就像 ImageNet 一样,需要几十万到数百万张带有标签的图片。无需标签即可学习的方法将在探讨自监督学习的姊妹系列中介绍。
- 对缩放和旋转较弱。 卷积虽然对位置平移具有鲁棒性,但无法在结构上保证物体变大或旋转的情况。因此,我们需要通过数据增强来教导模型。
8. 与我们项目的关联
TT Score 的寻球模型(WASB·BlurBall)在 2026 年仍然是 卷积神经网络。原因与本文所述完全一致。
- 球很小(在模型输入中直径仅约 3px),且会快速模糊。寻找这种图案非常契合“小窗口 + 权重共享”的归纳偏置。
- 大约 150 万个参数的小型网络就已经足够,处理单个窗口只需 10.5ms(服务器 GPU 实测)。对于实时判定而言,这个速度与准确率同样重要。
详细的结构与实测请参考《TT Score 模型解剖第 2 篇:寻球》。下一篇文章将介绍使深层网络得以训练的残差连接和批归一化。
蒂蒂小结。 我们从没对过滤器说过“去寻找垂直边界”,但在走了 500 步之后,它就变成了索贝尔过滤器。数据会促使过滤器自动变成想要的形状。
参考文献
- LeCun, Y., Bottou, L., Bengio, Y., Haffner, P. (1998). Gradient-Based Learning Applied to Document Recognition. Proceedings of the IEEE, 86(11), 2278–2324. https://doi.org/10.1109/5.726791
- Krizhevsky, A., Sutskever, I., Hinton, G. E. (2012). ImageNet Classification with Deep Convolutional Neural Networks. NeurIPS 2012. https://papers.nips.cc/paper_files/paper/2012/hash/c399862d3b9d6b76c8436e924a68c45b-Abstract.html
- 示例代码与输出:此文件夹中的
code/01_conv.py,code/01_conv.out.txt