跳到主要内容

卷积神经网络:把像素变成线条

这一章讲三件事: 卷积这一步运算在干什么(以及为什么它就是「特征工程」); CNN 靠什么两条性质比 Dense 省了天量参数;数据不够怎么补、黑箱怎么看进去。 从本章起进入书的应用篇:第 0610 章影像,第 1113 章文字与语音,第 14 章强化学习。

1. 起点:Dense 看图的方式不对

上一章的 MNIST 模型准确率 97%+,但书里一开场就挑它的毛病:Dense 把每个像素当成一个独立特征,而人不是这么看图的。三条不一致1:

  1. 手写数字集中在图中央,中央像素应该比边缘重要——Dense 里两者地位平等;
  2. 像素之间相关(「1」是一竖条,相邻像素明暗一致),Dense 却当它们互相独立;
  3. 人看的是线条和轮廓,不是 784 个孤立的点。

结论:卷积层干的就是特征工程——把「像素」这种低级特征换成「线条」这种高级特征,再交给 Dense 去辨识2。卷积的直觉:把图形逐步抽象化,删掉色彩、背景这些不必要的信息;书里展示了一张人像经过三层卷积后的样子——轮廓已经依稀可辨3

2. 卷积到底是什么:一格一格算给你看

卷积=拿一个小方块(滤波器/卷积核)在图上滑动,每到一个位置,把重叠的数对应相乘再全部加总,得到输出的一个格子。 书里的步骤拆解4:

原图(局部) 滤波器 对应相乘
┌─────────┐ ┌───────┐
│ 1 2 3 │ │ 1 0 1 │ 1×1 + 2×0 + 3×1
│ 4 5 6 │ × │ 0 1 0 │ = 4×0 + 5×1 + 6×0
│ 7 8 9 │ │ 1 0 1 │ 7×1 + 8×0 + 9×1
└─────────┘ └───────┘
加总 = 一个输出格 → 滑动一格 → 重复

图说:数字为演示编排,展示「对应相乘再求和」的机制;
书中以同样的流程配真实图例(图6.3/6.4)。

关键认知:滤波器决定卷积「认什么」。 书里把同一个机制换了几个滤波器跑了一遍,效果立竿见影5:

滤波器设计效果场景
周围点取平均模糊(7×7 小模糊,21×21 更糊)消红眼/噪声(图像上的随机杂点)
中间点权重突出锐化,对比更明显增强特征
凸显外围差异Laplacian 边缘检测,出轮廓提取线条
列方向渐变Sobel X,垂直线线条特征
行方向渐变Sobel Y,水平线线条特征

两个工程参数:Padding(same=边缘补零保持尺寸不变;valid=不补,图会缩小)、Stride(步长,一次滑 2 格能减少计算量)6

而 CNN 最反直觉的一点在这里:用哪个滤波器,不是程序员选的——滤波器里的数字本身就是权重,由反向传导训练出来。书里强调「卷积矩阵不是固定的,而是由反向传导推估出来的,与传统的图像处理不同」7。传统图像处理的滤波器是人凭经验设计的;CNN 只说「第一层给我 32 个滤波器」,每个滤波器长什么样,训练自己说了算。

3. 池化:把四个格子变成一个数

卷积的输出(特征图)又多又大——滤波器个数是 4 的倍数起跳,输出=批数×宽×高×滤波器数。池化(Pooling)把每个滑动窗口压成一个数:取最大值(MaxPooling)或平均值8。书里的逐格演示:2×2 窗口、步长 2,左上窗口里四个数最大是 6,记下 6;右滑两格,最大是 8;以此类推——尺寸缩一半,每个区域「有没有这个特征」的信息保留在最大值里9

主走查:从一张 28×28 的图,算出每一层的尺寸与参数

现在把第 04 章的 MNIST 模型换成 CNN(两组「卷积+池化」),每一层的输出尺寸和参数个数都能用笔算出来——这是「黑箱不黑」的一步,书里原样验算10:

输入 28×28
→ Conv2D(32 个 3×3 滤波器):
尺寸公式 W_out=(W−F+2P)/S+1 = (28−3+0)/1+1 = 26
参数 = 32 × (3×3×1 + 1) = 320 ← 3×3=9 个权重 ×1 通道,+1 偏差
→ MaxPooling2D(2×2): (26−2)/2+1 = 13
→ 第二层 Conv2D(64 个 3×3):参数 = 64 × (3×3×32 + 1) = 18496

公式里 W=输入宽、F=滤波器宽、P=补零圈数、S=步长;池化不补零,所以没有 2P 那一项。对照第 04 章:那是「数出 1290 个参数」,这里是「算出整座塔」——模型大小彻底透明。 换上 CNN 后 MNIST 准确率 0.9892,比 Dense 版略高11

4. CNN 为什么不臃肿:两条假设

一个网络动辄几十万参数,卷积凭什么反而省?书里给了两条结构性假设12:

  1. 部分连接:Dense 里每个神经元连接上一层的全部;卷积的输出神经元只连接滑动窗口覆盖的那几个输入。书里的比喻:在手臂上拍一下,手臂以外的神经元收不到信号——收得到的那个小范围叫感知域(Reception Field)。连接少了,要估的权重自然少了;
  2. 权重共享:同一个滤波器扫遍全图,所有位置用的是同一套数字——因为「检测竖线」这件事在图中央和角落用的是同一种知识。一套滤波器服务全图,参数再次大减。

两条合起来,CNN 的参数量(待调的权重个数)远小于同规模 Dense,训练才跑得动。同时它们也解释了 CNN 的性格:因为权重共享,不管目标在图中央还是角落,它都认得出——这既是优点,也埋着第 09 章末尾的缺点(位置无差异,五官挪位的脸照样「认出」)。

色彩通道也是输入的一部分:单色图通道数为 1,RGB 为 3,每个通道分别卷积。值不值得保留颜色?书里拿 Cifar10 做了对照实验:同一模型,灰阶化后准确率只有 32%,彩色 70%13——颜色本身就是特征(狮子金黄、口罩白块)。

5. 数据增补:没钱收数据,就把一张图变十张

书里先交代一个尴尬的实测:MNIST 模型对测试集 98%,但对作者用鼠标手写的数字就差很多——因为 MNIST 是纸上书写再扫描的,有深浅不一的灰阶和锯齿,和鼠标笔迹不是一种东西;真要用,得自己收集数据14。可上哪找上万个写字的人?于是轮到数据增补(Data Augmentation):把一张正常的图程序化地变成很多张有缺陷的图——旋转、偏移、拉近拉远、调亮度、镜像——模型见过带缺陷的样本,上线遇到缺陷就不慌15

实测结果很诚实:

  • MNIST 加增补后,测试集准确率没提升——测试集本来就是「纸上扫描」风格,不缺这些变化;但作者手写的「9」,原模型认不出,增补后认出了;
  • 代价:训练时间从 5s 拉长到 12s(两倍多)16;
  • 宠物猫狗数据集实战:过滤坏文件(表头无 JFIF 的不是真图片)、增补、较复杂的类 ResNet 模型,5 轮约 76%,原作者训 50 轮到 96%;随机下载一张测试,「是猫的概率 97.27%」17

数据增补的第三方库(如 Albumentations,70 多种效果)能补框架没有的花样(颜色增补等)18

6. 可解释 AI:看进黑箱一眼

第 04 章说神经网络是黑箱,本章末尾给了两个「往里看」的工具(XAI)19:

  • 重建中间层:拿 VGG16 把一张鸟图逐层卷积,再把每层输出还原成图看——第一层滤波器各抓各的线条(有的抓到,有的全黑);第 9 层还能看出线条,第 17 层已经抽象到认不出是鸟。你看得到「逐步抽象」确实在发生,只是没人读得懂它的逻辑;
  • SHAP 归因:借博弈论的 Shapley Value(原本用来分「团队里每人贡献多少」),给每个像素算「对识别为每个数字的贡献率」。书里的结果显示:红色高贡献区集中在图像中央——数字本来就写在中央,与人类直觉一致20。还有 Class Activation Mapping 能直接画出「热区」(猴子的头和颈部是辨识关键)21

XAI 的价值书里点了两条:确认模型「看对地方」(垃圾进垃圾出的把关),以及反过来指导收集什么数据——既然中央最要紧,样本就应该覆盖各种中央变化22

7. 可带走的

  1. CNN 的动机是「像人一样看图」:中央重要、像素相关、看轮廓——卷积层=自动化的特征工程;
  2. 卷积=滑窗乘积和:同一机制换滤波器就是模糊/锐化/边缘检测(Sobel 分管垂直线、水平线);CNN 里滤波器是训练出来的,不是设计的;
  3. Padding 管尺寸,Stride 管步速;Conv1D 用于语音/文字(只看上下文),Conv2DTranspose=反卷积,从特征图重建图像(第 09 章 AutoEncoder 的原料);
  4. 池化=窗口取最大/平均,尺寸减半;输出尺寸 W_out=(W−F+2P)/S+1 与参数个数都能手算(26、320、13、18496);
  5. 省参数靠两条:部分连接(感知域)+权重共享;这两条同时带来「位置无差异」的性格;
  6. 颜色是特征:Cifar10 灰阶 32% vs 彩色 70%;
  7. 数据增补解决「真实样本与训练集不同源」:鼠标写的 9 从认不出到认得出;代价是训练时间翻倍;注意先过滤坏文件(JFIF 表头检查);
  8. XAI 两板斧:重建中间层看「逐步抽象」,SHAP 逐像素归因看「看哪里」——中央热区与人类直觉一致;
  9. 真实项目与刷榜的差距在数据端:MNIST 98% 不代表能认你写的字——数据同源比模型精巧更重要。

8. 原文地图

主题原书章原文位置
Dense 看图方式的三条不一致6-1 卷积神经网络简介text/41-ch06-6-1.txt:5(搜「应该不会逐点辨识」)
卷积=特征工程6-1 卷积神经网络简介text/41-ch06-6-1.txt:13(搜「特征提取(Feature Extraction」)
逐步抽象化6-1 卷积神经网络简介text/41-ch06-6-1.txt:15(搜「抽样化(Abstraction」)
卷积步骤、滤波器6-2 卷积text/42-ch06-6-2.txt:5(搜「乘积和」运算」)
Padding 与 Stride6-2 卷积text/42-ch06-6-2.txt:43(搜「Padding='same'」) · text/42-ch06-6-2.txt:49(搜「Stride=2」)
反卷积与 AutoEncoder 伏笔6-2 卷积text/42-ch06-6-2.txt:53(搜「反卷积(Deconvolution」)
各式滤波器效果6-3 各式卷积text/43-ch06-6-3.txt:19(搜「模糊化(Blur」) · text/43-ch06-6-3.txt:35(搜「Laplacian边缘检测」) · text/43-ch06-6-3.txt:41(搜「Sobel X轴」)
池化取最大值6-4 池化层text/44-ch06-6-4.txt:15(搜「最大值为6」) · text/44-ch06-6-4.txt:5(搜「4的倍数」)
尺寸与参数手算(主走查)6-5 CNN模型实践text/45-ch06-6-5-cnn.txt:33(搜「W_out =(W-F+2P)/S+1」) · text/45-ch06-6-5-cnn.txt:37(搜「28-3+2*0」) · text/45-ch06-6-5-cnn.txt:39(搜「320」) · text/45-ch06-6-5-cnn.txt:41(搜「(26-2)/ 2 +1 = 13」) · text/45-ch06-6-5-cnn.txt:43(搜「18496」)
CNN 准确率 0.98926-5 CNN模型实践text/45-ch06-6-5-cnn.txt:21(搜「0.9892」)
部分连接与感知域、权重共享6-5 CNN模型实践text/45-ch06-6-5-cnn.txt:47(搜「感知域(Reception Field」) · text/45-ch06-6-5-cnn.txt:53(搜「权重共享(Weight Sharing」)
灰阶 32% vs 彩色 70%6-5 CNN模型实践text/45-ch06-6-5-cnn.txt:79(搜「准确率只有32%」) · text/45-ch06-6-5-cnn.txt:89(搜「准确率提升为70%」)
MNIST 与鼠标笔迹不同源6-6 影像数据增补text/46-ch06-6-6.txt:7(搜「鼠标撰写的样式有所差异」)
增补的定义与代价6-6 影像数据增补text/46-ch06-6-6.txt:9(搜「自动产生各种变形」) · text/46-ch06-6-6.txt:51(搜「由原本的5s拉长至12s」)
宠物数据实战 97.27%6-6 影像数据增补text/46-ch06-6-6.txt:73(搜「JFIF」) · text/46-ch06-6-6.txt:91(搜「50 epochs」) · text/46-ch06-6-6.txt:95(搜「97.27%」)
Albumentations6-6 影像数据增补text/46-ch06-6-6.txt:99(搜「Albumentations」)
XAI 目的与垃圾进垃圾出6-7 可解释的AItext/47-ch06-6-7-ai.txt:7(搜「垃圾进」)
重建中间层6-7 可解释的AItext/47-ch06-6-7-ai.txt:29(搜「VGG16为知名」) · text/47-ch06-6-7-ai.txt:55(搜「第17层图像处理结果」)
SHAP 与中央热区6-7 可解释的AItext/47-ch06-6-7-ai.txt:71(搜「Shapley Value是博弈论」) · text/47-ch06-6-7-ai.txt:97(搜「中央位置是辨识的重点区域」) · text/47-ch06-6-7-ai.txt:101(搜「Class Activation Mapping」)

Footnotes

  1. 出处:「6-1 卷积神经网络简介」第 5 段(text/41-ch06-6-1.txt:5,搜「应该不会逐点辨识」)。三条理由在同段的 (1)(2)(3) 点。

  2. 出处:「6-1 卷积神经网络简介」第 13 段(text/41-ch06-6-1.txt:13,搜「特征提取(Feature Extraction」)。原文明确把它对应到机器学习流程第 3 步特征工程。

  3. 出处:「6-1 卷积神经网络简介」第 15 段(text/41-ch06-6-1.txt:15,搜「抽样化(Abstraction」)。

  4. 出处:「6-2 卷积」第 5 段(text/42-ch06-6-2.txt:5,搜「乘积和」运算」)。五步流程在同段。

  5. 出处:「6-3 各式卷积」第 19 段(text/43-ch06-6-3.txt:19,搜「模糊化(Blur」)、第 29 段(text/43-ch06-6-3.txt:29,搜「锐化(Sharpen」)、第 35 段(text/43-ch06-6-3.txt:35,搜「Laplacian边缘检测」)与第 41 段(text/43-ch06-6-3.txt:41,搜「Sobel X轴」)。

  6. 出处:「6-2 卷积」第 43 段(text/42-ch06-6-2.txt:43,搜「Padding='same'」)与第 49 段(text/42-ch06-6-2.txt:49,搜「Stride=2」)。

  7. 出处:「6-1 卷积神经网络简介」第 25 段(text/41-ch06-6-1.txt:25,搜「反向传导推估出来」)。

  8. 出处:「6-4 池化层」第 5 段(text/44-ch06-6-4.txt:5,搜「4的倍数」)。

  9. 出处:「6-4 池化层」第 15 段(text/44-ch06-6-4.txt:15,搜「最大值为6」)与第 17 段(text/44-ch06-6-4.txt:17,搜「最大值为8」)。

  10. 出处:「6-5 CNN模型实践」第 33 段(text/45-ch06-6-5-cnn.txt:33,搜「W_out =(W-F+2P)/S+1」)、第 37 段(text/45-ch06-6-5-cnn.txt:37,搜「28-3+2*0」)、第 39 段(text/45-ch06-6-5-cnn.txt:39,搜「320」)、第 41 段(text/45-ch06-6-5-cnn.txt:41,搜「(26-2)/ 2 +1 = 13」)与第 43 段(text/45-ch06-6-5-cnn.txt:43,搜「18496」)。

  11. 出处:「6-5 CNN模型实践」第 21 段(text/45-ch06-6-5-cnn.txt:21,搜「0.9892」)。

  12. 出处:「6-5 CNN模型实践」第 47 段(text/45-ch06-6-5-cnn.txt:47,搜「感知域(Reception Field」)与第 53 段(text/45-ch06-6-5-cnn.txt:53,搜「权重共享(Weight Sharing」)。

  13. 出处:「6-5 CNN模型实践」第 79 段(text/45-ch06-6-5-cnn.txt:79,搜「准确率只有32%」)与第 89 段(text/45-ch06-6-5-cnn.txt:89,搜「准确率提升为70%」)。「狮子金黄、口罩白块」的例子在同章第 65 段(搜「狮子大部分是金黄色」)。

  14. 出处:「6-6 影像数据增补」第 7 段(text/46-ch06-6-6.txt:7,搜「鼠标撰写的样式有所差异」)。

  15. 出处:「6-6 影像数据增补」第 9 段(text/46-ch06-6-6.txt:9,搜「自动产生各种变形」)。

  16. 出处:「6-6 影像数据增补」第 49 段(text/46-ch06-6-6.txt:49,搜「准确度并没有提升」)与第 51 段(text/46-ch06-6-6.txt:51,搜「由原本的5s拉长至12s」)。「自绘的 9 认得出」在第 55 段(搜「原来的模型无法正确辨识笔者写的9」)。

  17. 出处:「6-6 影像数据增补」第 73 段(text/46-ch06-6-6.txt:73,搜「JFIF」)、第 91 段(text/46-ch06-6-6.txt:91,搜「50 epochs」)与第 95 段(text/46-ch06-6-6.txt:95,搜「97.27%」)。

  18. 出处:「6-6 影像数据增补」第 99 段(text/46-ch06-6-6.txt:99,搜「Albumentations」)。

  19. 出处:「6-7 可解释的AI」第 7 段(text/47-ch06-6-7-ai.txt:7,搜「垃圾进」)。

  20. 出处:「6-7 可解释的AI」第 71 段(text/47-ch06-6-7-ai.txt:71,搜「Shapley Value是博弈论」)与第 97 段(text/47-ch06-6-7-ai.txt:97,搜「中央位置是辨识的重点区域」)。

  21. 出处:「6-7 可解释的AI」第 101 段(text/47-ch06-6-7-ai.txt:101,搜「Class Activation Mapping」)。猴子热区见第 103 段(搜「猴子的头」)。

  22. 出处:「6-7 可解释的AI」第 105 段(text/47-ch06-6-7-ai.txt:105,搜「收集数据时」)。