跳到主要内容

卷积神经网络 — 看图的正确姿势

这一章讲三件事: 卷积层和 Dense 层的根本区别是什么; 卷积、汇聚这两个运算在特征图上各干了什么;以及小数据集上图像分类的完整打法 (从头训练 → 数据增强 → 特征提取 → 微调)。 计算机视觉是深度学习最早、最成功的战场——第 01 章那个 2012 拐点, 就是用这一章的卷积神经网络打下来的。

1. 顶层全景

一张图进 Dense 层,要先拉直成一维向量——像素之间的空间关系就此丢失。 卷积神经网络(convnet)不换这个思路:它保持图像的二维结构,用小窗口在图上滑动, 对每个位置做同一个变换。全书第一个卷积网络长这样1:

输入 (28, 28, 1)
→ Conv2D(32, 3×3, relu) → (26, 26, 32)
→ MaxPooling2D(2×2) → (13, 13, 32)
→ Conv2D(64, 3×3, relu) → (11, 11, 64)
→ MaxPooling2D(2×2) → (5, 5, 64)
→ Conv2D(128, 3×3, relu) → (3, 3, 128)
→ Flatten → Dense(10, softmax)

图说:卷积层负责「看」,通道数越往后越多(32→64→128);
汇聚层负责「缩」,特征图越往后越小。最后展平,接熟悉的 Dense 分类器。

同一个 MNIST 任务,第 02 章的密集网络测试精度 97.8%,这个小卷积网络 99.1%—— 错误率相对降低了约 60%2

本章的主走查是后面的猫狗分类:Kaggle 25000 张猫狗照片里取的小子集 (2000 训练/1000 验证/2000 测试),同一批数据,四种打法,精度从 69.5% 一路走到 98.5%3

2. 卷积:局部模式、平移不变、空间层次

2.1 Dense 与卷积的根本区别

书里一句话点破:Dense 层从输入特征空间中学到的是全局模式(涉及所有像素的模式), 卷积层学到的是局部模式(在输入图像的二维小窗口中发现的模式)——窗口通常只有 3×3 或 5×54

这个区别换来两个性质5:

平移不变性。 在图片右下角学到的模式,在左上角也能认出来—— 因为扫全图用的是同一个变换。Dense 模型没有这种好事:模式换个位置,它就得重新学一遍。 视觉世界恰好是平移不变的(猫在左在右都是猫),所以这个性质让卷积网络用更少的数据就能学出泛化

空间层次结构。 第一层学小局部模式(边缘、纹理),第二层学「由第一层模式组成的更大模式」 (眼睛、耳朵),再往上是「猫」这样的完整概念——视觉世界本身就具有空间层次, 卷积网络顺着这个结构学,一层比一层抽象6

2.2 特征图、滤波器、响应图

卷积的输入输出都是特征图:一个 3 阶张量,两个空间轴(高、宽)加一个深度轴(通道)。 输入图的深度轴是颜色(RGB 为 3,灰度为 1);输出特征图的深度轴不再是颜色, 而是滤波器——每个滤波器负责编码输入的某一方面,高层的滤波器可能编码「输入中包含一张人脸」这种概念7

以 MNIST 的第一层为例:输入 (28, 28, 1),输出 (26, 26, 32)—— 这一层算了 32 个滤波器,每个滤波器产出一个 26×26 的数值网格, 叫响应图:它表示「这个滤波器负责的模式,在输入的每个位置上各出现了多强」8

2.3 卷积到底是怎么算的

机制本身只有一句话:在输入特征图上滑动小窗口,每个位置取一个 3 维图块, 和同一个卷积核做点积,得到一个数;所有位置的数拼起来,就是输出特征图9:

输入图块 (3, 3, 输入通道) ──点积──► 一个数
窗口滑到下一个位置 ──点积──► 又一个数
……滑完整张图,拼成 (高, 宽) 的响应图;32 个滤波器就重复 32 遍

图说:卷积核(一组学出来的权重)对所有位置复用——这就是平移不变性的来源。

这里出现的「卷积核」和上一节的「滤波器」是同一个东西,两个名字。 说「滤波器」时是在讲它的职责(它负责认哪一种模式), 说「卷积核」时是在讲它的形状(3×3×输入通道 的那一小堆权重)—— 32 个滤波器就是 32 个卷积核,不是两级零件。 两个名字出门都会撞见,所以都留着。

输出的高宽为什么比输入小?边界效应:5×5 的图上,能放下 3×3 窗口中心的位置只有 3×3 个—— 边缘的像素当不了中心。想让输出和输入同尺寸,就在边缘补一圈零,这叫填充; Keras 里 padding="valid" 是不填充,"same" 是补到同尺寸10

另一个影响尺寸的是步幅:窗口每次挪几格,默认 1。步幅设成 2,窗口就隔一格挪一次, 输出的高宽各减一半——这种「主动把特征图缩小一圈」的动作叫下采样。 下一节那个最大汇聚是下采样的另一种做法,两者可以互相替代(第 09 章会讲什么时候该换哪一种)11

3. 最大汇聚:为什么要主动把图缩小

最大汇聚(max-pooling)的做法是:用 2×2 窗口、步幅 2 扫特征图, 每个窗口只留最大值——特征图高宽直接减半12

为什么主动丢信息?书里用一个反面实验回答:把卷积网络里的汇聚层全删掉13:

问题后果
没有逐级缩小第三层的 3×3 窗口只能「看到」原图 7×7 的区域——7 像素见方的视野,认不出整个数字
特征图始终很大最后一层展平后有 22×22×128 = 61952 个元素,接一个 10 输出的 Dense 就是 50 多万个参数——小模型上必然严重过拟合

所以下采样的两个作用是:把特征图元素数控制在合理范围, 以及让后面层的观察窗口覆盖原图越来越大的比例(空间层次的硬件基础)14

为什么取 max 不取平均?因为特征图编码的是「某模式在各位置是否存在」, 最大值直接回答「这个小块里它出现过没有」,平均值会把这个信号冲淡15

回到猫狗:主走查第 ① 步(从头训练 69.5%)

数据是 Kaggle 2013 年猫狗竞赛的 25000 张图(猫狗各半,543 MB), 书里特意只用一小部分:每类 1000 张训练、500 张验证、1000 张测试—— 因为真实工作里,你手上的图通常就是几千张,不是几万张16

模型是 5 组 Conv2D + MaxPooling2D(通道 32→64→128→256→256), 输入 180×180,最前面一个 Rescaling 层把像素从 [0,255] 缩到 [0,1], 最后一层 sigmoid 单输出,共 991,041 个参数17

30 轮下来:训练精度一路涨到接近 100%,验证精度停在 75%,第 10 轮就过拟合了—— 2000 张图对一个百万参数的模型来说太少。加载检查点里最好的那一版,测试精度 69.5%18

4. 数据增强:不新增信息,但把已有信息翻着花样用

小数据集上过拟合是头号敌人。第 06 章的四件工具里,dropout 和 L2 都能用, 但图像领域还有一件专属武器:数据增强—— 对训练图做随机变换(翻转、旋转、缩放),让模型不会两次看到完全相同的图19:

data_augmentation = keras.Sequential([
layers.RandomFlip("horizontal"), # 随机水平翻转 50% 的图
layers.RandomRotation(0.1), # 随机旋转 ±36° 以内
layers.RandomZoom(0.2), # 随机缩放 ±20% 以内
])

图说:这些层只在训练时起作用,评估和推断时自动失效——
就像 dropout 一样,不用你操心。

回到猫狗:主走查第 ② 步(83.5%)。 同一个模型,前面接上数据增强块、 Flatten 前加一个 Dropout(0.5),训 100 轮:过拟合推迟到第 60~70 轮才出现, 测试精度 83.5%20

但书里同时说清了它的边界:增强不产生新信息,只是把现有信息重新组合—— 输入之间仍然高度相关,所以它能缓解、不能根除过拟合21

5. 预训练模型:站在 140 万张图的肩膀上

5.1 为什么旧模型的特征可以搬家

预训练模型是在大型数据集(通常是 ImageNet:140 万张、1000 类)上训练好的模型。 它学到的特征层次结构,可以作为「视觉世界的通用模型」搬到完全不相干的任务上—— 在 ImageNet(主要是动物和日用品)上学的特征,拿去认家具也管用。 这种特征的可移植性,是深度学习对小数据问题如此有效的核心原因22

书里用的旧模型是 VGG16(2014 年,Simonyan 与 Zisserman):选它不是因为强—— 它比今天的模型又老又笨重——而是因为它的结构就是第 2 节那种「卷积+汇聚」的放大版, 不引入任何新概念23

一个图像卷积网络可以分成两段:前面一串卷积和汇聚,叫卷积基; 后面接的 Dense 分类器。复用时只搬卷积基,不搬分类器,原因有两个24:

  1. 卷积基学到的是「某概念在图中是否存在」的通用表示,还带位置信息; 分类器学到的是针对原任务 1000 类的特定判断,而且已经把空间位置信息丢掉了;
  2. 层越深,表示越专用:前几层是边缘、颜色、纹理(哪都能用), 后几层是「猫耳朵」「狗眼睛」(和原任务绑死)——新旧任务差得越远,越该只用前几层。

5.2 回到猫狗:主走查第 ③ 步(特征提取 97.5%)

特征提取的标准做法:冻住卷积基,只训练自己新接的小分类器25。 Keras 里冻结就是把 conv_base.trainable 设为 False—— 可训练权重列表从 26 个清空成 0 个(注意:改完要重新 compile 才生效)26

冻住的原因是:新分类器的权重是随机初始化的,训练初期传回来的梯度更新又大又乱, 如果卷积基也跟着动,之前学到的表示会被这些乱拳毁掉27

具体有两条路28:

方法做法代价与限制
快速特征提取用 predict() 把所有图过一遍卷积基,特征存成数组,单独训分类器快(CPU 每轮不到 1 秒),但不能用数据增强
端到端特征提取卷积基和新分类器接成一个模型,整体训练(卷积基冻结)慢(必须 GPU),但可以用数据增强

端到端这条路,验证精度约 98%,测试精度 97.5%—— 从 83.5% 到 97.5%,没收集一张新图,只是把别人学好的视觉常识搬了过来29

5.3 回到猫狗:主走查第 ④ 步(微调 98.5%)

最后一步是微调:分类器训好之后,把卷积基顶部几层解冻, 和新分类器一起用小学习率继续训——让这些「比较专用」的表示朝你的任务偏一点点30

先后顺序不能反:必须先冻住卷积基把分类器训好,才能解冻微调—— 分类器还是随机的时候,传回去的误差信号太大,会把卷积基顶层的表示打烂31

另外两条规矩32:

  • 只解冻顶部两三层:底层特征通用,微调回报小;解冻得越多,参数越多,小数据上越容易过拟合 (VGG16 卷积基有近 1500 万个参数);
  • 学习率要很小(书里用 1e-5):微调是「轻轻推」,不是「重新学」。

结果:测试精度 98.5%——用不到当年参赛者 10% 的数据, 打平了 2013 年那场比赛的最好成绩之一33

6. 作者的判断与证据

实测证据: 69.5% / 83.5% / 97.5% / 98.5% 四级台阶,逐级可复现; 无汇聚反例的 61952 个元素是算出来的;

作者的机制性论证(非实验证明): 「最大值比平均值保信息」 「卷积基通用、分类器专用」——这些解释合理且与经验一致,但书里给的是论证,不是对照实验;

一个诚实的提醒: 作者明说 97.5%→98.5% 这种比较对参赛者不公平—— 预训练模型的特征里已经包含了猫狗的先验知识,而当年的参赛者用不上这些特征33

判断(我们的,不是书里的): 这一章的四级台阶,后两级的力气不是从这 2000 张图里来的, 是从 ImageNet 那 140 万张图里借来的。所以「小数据也能到 98.5%」这句话要带上一个前提: 你的任务得和别人已经训过的那个任务沾边。 ImageNet 里本来就有一百多个狗品种和十几个猫品种, 猫狗分类几乎是它的子任务——这是本章能拿到的最好情况,不是通例。 换成 ImageNet 里根本没有的东西(工业 X 光片里的焊缝、卫星图上的考古遗址), 借来的先验会薄很多,四级台阶的后两级涨幅也会小很多。 如果错,会错在: 如果后来的实验表明,在 ImageNet 上学到的底层特征 (边缘、纹理、方向)对完全不相干的领域同样有大幅增益, 那「必须沾边」这个前提就下得太重了——这一条我们没有做对照实验, 书里也没有做,它是从「层越深表示越专用」那条书内结论推出来的

7. 边界与局限

  • VGG16 是 2014 年的老将。今天做特征提取,keras.applications 里的 EfficientNet、Xception 等更新模型是更好的起点;「先冻基、再小学习率微调顶层」的流程不变;
  • 数据增强的变换要和任务匹配:水平翻转对猫狗安全,对「区分字母 b 和 d」就是灾难—— 变换必须保持标签不变,这条书里没展开,来自通用知识;
  • 本章只覆盖图像分类;分割和检测在第 09 章(分割)和原书之外(检测,原书明确不讲);
  • 「测试精度会因样本集不同而波动」——书里 97.5% 和 98% 验证精度之间的落差就是实例29

8. 可带走的

  1. Dense 学全局模式,卷积学局部模式——局部 + 复用 = 平移不变性 + 空间层次;
  2. 特征图的深度轴:输入是颜色,输出是滤波器;每个滤波器产一张响应图;
  3. 卷积 = 滑窗取图块,和同一个卷积核做点积;尺寸由边界效应(填充)步幅控制;
  4. 最大汇聚的两个作用:控数量、扩视野;取 max 因为特征编码的是「是否存在」;
  5. 卷积网络的通用模式:通道越往后越多,特征图越往后越小;
  6. 小数据打法四级台阶:从头训练 → 数据增强 → 冻结卷积基特征提取 → 小学习率微调顶层;
  7. 数据增强不产生新信息,只重组旧信息——能缓解,不能根除;
  8. 复用时只搬卷积基不搬分类器;先冻基训分类器,才能解冻微调;
  9. 微调三规矩:只解冻顶两三层、学习率很小、改完 trainable 要重新 compile

9. 原文地图

主题原书章原文位置
第一个卷积网络与 99.1%计算机视觉深度学习入门text/15-ch08.txt:34(搜「Conv2D」) · text/15-ch08.txt:115(搜「60%」)
全局 vs 局部、两个性质计算机视觉深度学习入门text/15-ch08.txt:119(搜「全局模式」) · text/15-ch08.txt:127(搜「平移不变性」) · text/15-ch08.txt:132(搜「空间层次结构」)
特征图、滤波器、响应图计算机视觉深度学习入门text/15-ch08.txt:136(搜「特征图」) · text/15-ch08.txt:141(搜「滤波器」) · text/15-ch08.txt:153(搜「响应图」)
卷积的滑窗机制计算机视觉深度学习入门text/15-ch08.txt:172(搜「滑动」)
边界效应、填充、步幅计算机视觉深度学习入门text/15-ch08.txt:203(搜「5×5」) · text/15-ch08.txt:217(搜「valid」) · text/15-ch08.txt:222(搜「步幅」)
无汇聚反例与 max 的理由计算机视觉深度学习入门text/15-ch08.txt:288(搜「61 952」) · text/15-ch08.txt:298(搜「最大值而不是均值」)
猫狗数据与从头训练计算机视觉深度学习入门text/15-ch08.txt:384(搜「543」) · text/15-ch08.txt:670(搜「69.5%」)
数据增强计算机视觉深度学习入门text/15-ch08.txt:677(搜「数据增强」) · text/15-ch08.txt:773(搜「83.5%」) · text/15-ch08.txt:718(搜「只能将现有信息重新组合」)
预训练与卷积基计算机视觉深度学习入门text/15-ch08.txt:317(搜「预训练模型」) · text/15-ch08.txt:804(搜「卷积基」) · text/15-ch08.txt:818(搜「密集连接分类器」)
冻结与特征提取计算机视觉深度学习入门text/15-ch08.txt:1008(搜「冻结」) · text/15-ch08.txt:1024(搜「trainable」) · text/15-ch08.txt:1097(搜「97.5%」)
微调与 98.5%计算机视觉深度学习入门text/15-ch08.txt:1102(搜「微调」) · text/15-ch08.txt:1107(搜「分类器已经训练好」) · text/15-ch08.txt:1218(搜「1500 万」) · text/15-ch08.txt:1250(搜「98.5%」)

Footnotes

  1. 出处:「计算机视觉深度学习入门」第 34 段(text/15-ch08.txt:34,搜「Conv2D」)与第 57 段(text/15-ch08.txt:57,搜「summary」)。

  2. 出处:「计算机视觉深度学习入门」第 115 段(text/15-ch08.txt:115,搜「99.1%」)与第 115 段(text/15-ch08.txt:115,搜「60%」)。

  3. 出处:「计算机视觉深度学习入门」第 309 段(text/15-ch08.txt:309,搜「5000 张」)与第 384 段(text/15-ch08.txt:384,搜「543」)。

  4. 出处:「计算机视觉深度学习入门」第 119 段(text/15-ch08.txt:119,搜「全局模式」)。

  5. 出处:「计算机视觉深度学习入门」第 127 段(text/15-ch08.txt:127,搜「平移不变性」)与第 132 段(text/15-ch08.txt:132,搜「空间层次结构」)。

  6. 出处:「计算机视觉深度学习入门」第 148 段(text/15-ch08.txt:148,搜「视觉模块的空间层次结构」)。

  7. 出处:「计算机视觉深度学习入门」第 136 段(text/15-ch08.txt:136,搜「特征图」)与第 141 段(text/15-ch08.txt:141,搜「滤波器」)。

  8. 出处:「计算机视觉深度学习入门」第 152 段(text/15-ch08.txt:152,搜「32 个滤波器」)与第 153 段(text/15-ch08.txt:153,搜「响应图」)。

  9. 出处:「计算机视觉深度学习入门」第 172 段(text/15-ch08.txt:172,搜「滑动」)与第 174 段(text/15-ch08.txt:174,搜「卷积核」)。

  10. 出处:「计算机视觉深度学习入门」第 203 段(text/15-ch08.txt:203,搜「5×5」)与第 217 段(text/15-ch08.txt:217,搜「valid」)。

  11. 出处:「计算机视觉深度学习入门」第 222 段(text/15-ch08.txt:222,搜「步幅」)。

  12. 出处:「计算机视觉深度学习入门」第 241 段(text/15-ch08.txt:241,搜「最大汇聚」)。

  13. 出处:「计算机视觉深度学习入门」第 253 段(text/15-ch08.txt:253,搜「结构错误」)、第 284 段(text/15-ch08.txt:284,搜「7×7」)与第 288 段(text/15-ch08.txt:288,搜「61 952」)。

  14. 出处:「计算机视觉深度学习入门」第 291 段(text/15-ch08.txt:291,搜「下采样的原因」)。

  15. 出处:「计算机视觉深度学习入门」第 162 段(text/15-ch08.txt:162,搜「是否存在」)与第 298 段(text/15-ch08.txt:298,搜「最大值而不是均值」)。

  16. 出处:「计算机视觉深度学习入门」第 387 段(text/15-ch08.txt:387,搜「几千个样本」)。

  17. 出处:「计算机视觉深度学习入门」第 444 段(text/15-ch08.txt:444,搜「32 增大到 128」)与第 505 段(text/15-ch08.txt:505,搜「991,041」)。

  18. 出处:「计算机视觉深度学习入门」第 660 段(text/15-ch08.txt:660,搜「过拟合的特征」)与第 670 段(text/15-ch08.txt:670,搜「69.5%」)。

  19. 出处:「计算机视觉深度学习入门」第 677 段(text/15-ch08.txt:677,搜「数据增强」)与第 694 段(text/15-ch08.txt:694,搜「RandomFlip」)。

  20. 出处:「计算机视觉深度学习入门」第 761 段(text/15-ch08.txt:761,搜「60 ~ 70 轮」)与第 773 段(text/15-ch08.txt:773,搜「83.5%」)。

  21. 出处:「计算机视觉深度学习入门」第 718 段(text/15-ch08.txt:718,搜「只能将现有信息重新组合」)。

  22. 出处:「计算机视觉深度学习入门」第 781 段(text/15-ch08.txt:781,搜「预训练模型」)与第 787 段(text/15-ch08.txt:787,搜「可移植性」)。

  23. 出处:「计算机视觉深度学习入门」第 792 段(text/15-ch08.txt:792,搜「VGG16」)。

  24. 出处:「计算机视觉深度学习入门」第 804 段(text/15-ch08.txt:804,搜「卷积基」)与第 818 段(text/15-ch08.txt:818,搜「密集连接分类器」)与第 827 段(text/15-ch08.txt:827,搜「模型中的深度」)。

  25. 出处:「计算机视觉深度学习入门」第 1008 段(text/15-ch08.txt:1008,搜「冻结」)。

  26. 出处:「计算机视觉深度学习入门」第 1024 段(text/15-ch08.txt:1024,搜「trainable」)与第 1064 段(text/15-ch08.txt:1064,搜「重新编译」)。

  27. 出处:「计算机视觉深度学习入门」第 1011 段(text/15-ch08.txt:1011,搜「很大破坏」)。

  28. 出处:「计算机视觉深度学习入门」第 911 段(text/15-ch08.txt:911,搜「NumPy 数组」)与第 915 段(text/15-ch08.txt:915,搜「端到端」)。

  29. 出处:「计算机视觉深度学习入门」第 1084 段(text/15-ch08.txt:1084,搜「98%」)与第 1097 段(text/15-ch08.txt:1097,搜「97.5%」)。 2

  30. 出处:「计算机视觉深度学习入门」第 1102 段(text/15-ch08.txt:1102,搜「微调」)。

  31. 出处:「计算机视觉深度学习入门」第 1107 段(text/15-ch08.txt:1107,搜「分类器已经训练好」)。

  32. 出处:「计算机视觉深度学习入门」第 1215 段(text/15-ch08.txt:1215,搜「通用的可复用特征」)、第 1218 段(text/15-ch08.txt:1218,搜「1500 万」)与第 1232 段(text/15-ch08.txt:1232,搜「1e-5」)。

  33. 出处:「计算机视觉深度学习入门」第 1250 段(text/15-ch08.txt:1250,搜「98.5%」)与第 1253 段(text/15-ch08.txt:1253,搜「10%」)。 2