卷积和池化在空间上干活,全连接层在最后收尾:把 (C, H, W) 摊平成一维,映射到类别数。 参数大头在这里。实测 32×13×13 摊平成 5408 维,接 128 个单元要 692352 个参数, 而一个 3×3×32→32 的卷积层只有 9248 个——差 75 倍。 摊平的顺序必须和权重对应。换框架时顺序不同,权重就搬不过去。
5.3 的卷积层和 5.8 的池化层都保留三维形状,这一节把它压平。 5.10 节会把「卷积 + 池化 + 全连接」拼成完整网络训练一遍。 第 4 章 MNIST 那一节其实一直在用全连接层,只是输入是已经摊平好的 784 维。
一、为什么最后要摊平
卷积输出是「哪个位置有什么特征」,分类要的是「整张图是什么」。这两个问题的形状不一样。 摊平加全连接,等于让每个类别都能对「任意位置上的任意特征」加权。 这也是它丢位置信息的机制:谁在哪不重要,只看有没有。 分类恰恰不需要位置,所以这里丢得起。换成检测,就丢不起了。
二、参数从这里开始爆炸
5408 乘 128 加 128 等于 692352。一个层就占了整个网络参数的 98.7%。 这是卷积网络里最反直觉的一件事:你以为卷积层是大头,其实全连接层才是。 所以 VGG 那种一亿四千万参数的网络,绝大部分在最后三个全连接层里,卷积层加起来反而没多少。 这也解释了为什么剪枝往往从全连接层下手。
三、摊平的顺序
NumPy 里 (C, H, W) 转一维是「通道优先」:先第 0 通道的全部像素,再第 1 通道。 这个顺序必须和全连接层的权重对应。有的框架用通道在后(H, W, C),摊平出来顺序完全不同。 这是迁移学习里踩得最多的坑:权重能加载、形状也对,但结果全错。而且不报错, 只能靠准确率异常发现。
四、为什么不干脆全用卷积
全卷积网络确实存在,用 1×1 卷积代替全连接,参数能少很多。 代价是它保留了空间维度,输出是一张「每个位置的类别」的图,不是单个类别。 分类任务上两者都能用, 但全连接层的实现更简单、更通用,所以至今是默认写法。5.12 节会讲 1×1 卷积到底怎么省参数。
五、另一种收尾:全局平均池化
对每个通道的整张特征图取平均,得到 C 个数,直接接 softmax。参数为零。 它把 692352 个参数直接砍掉。代价是丢掉全部位置信息。 所以它在分类上很好(还能顺带抑制过适),在需要定位的任务上不行。 现代分类网络(ResNet 之后)基本都用它替掉大全连接层。
六、动手 Demo:摊平之后,参数从这里开始爆炸
算一笔账:32×13×13 的特征图摊平后接 128 个单元,参数是多少;同一个网络里一个 3×3 卷积层又是多少。 再看一眼摊平的顺序。
c, h, wd = 32, 13, 13
flat = c * h * wd
fc = flat * 128 + 128
conv = 3 * 3 * 32 * 32 + 32
print("摊平后维度", flat)
print("全连接 128 单元,参数", fc)
print("一个 3×3 卷积层,参数", conv)
print("两者相差 %.0f 倍" % (fc / conv))
x = np.zeros((2, 2, 2))
x[0] = 1.0
x[1] = 2.0
print("通道优先摊平", x.ravel())
实跑输出:
--------------------------------------------------------------------
全连结层:摊平之后,参数从这里开始爆炸
--------------------------------------------------------------------
一卷到底之后常见的形状是 32×13×13,摊平就是 5408 维。
接一个 128 个单元的全连接层,参数 5408 乘 128 加 128 = 692352 个。
层 参数量 占比
--------------------------------------------------
一个 3×3 卷积层(32→32) 9248 1.3%
一个 128 单元全连接层 692352 98.7%
**一个全连接层的参数,是一个卷积层的 75 倍。**
卷积网络里参数的大头往往不在卷积,而在最后这几层全连接。
摊平的顺序也要注意。NumPy 里 (32, 13, 13) 转一维是按「通道、行、列」排的,
所以前 169 个数全部来自第 1 个通道。
形状 (2,2,2),通道 0 全是 1、通道 1 全是 2,摊平后:1 1 1 1 2 2 2 2
**前四个数是一组的、后四个数是另一组的,这个顺序必须和后面全连接层的权重对应上。**
换框架时顺序不同(有的是通道在后),权重就没法直接搬——这是迁移学习里踩得最多的坑。
5408 乘 128 加 128 等于 692352。这个数比前面所有卷积层加起来还多两个数量级。 表里两行:卷积层 9248 占 1.3%,全连接层占 98.7%,比值是 75 倍。 摊平那一行:形状 (2,2,2)、通道 0 全是 1、通道 1 全是 2,摊平后是 1 1 1 1 2 2 2 2。 前四个一组、后四个一组,这就是「通道优先」。 记住这个顺序。 加载别人的权重时,形状对不上会报错;形状对得上但顺序不同不会报错——后者才是最坑的。 书里 5-9 节讲全连结层,重点就是这个「摊平加全连接」的组合。 它看起来最土,但至今没有被完全替代。
30 秒实验
- 如果摊平后不接 128 而是直接接 10(输出类别),参数变成多少?
- 如果换成全局平均池化(32 个通道各取一次平均),参数是多少?
- 通道优先和行优先两种摊平方式,配同一套权重,算出来的结果会一样吗?
常见误区
- 以为卷积网络里参数最多的是卷积层。恰恰相反,最后那几层全连接才是大头。
- 忽略摊平顺序。形状对得上不代表顺序对。这种错不会报错,只会让准确率莫名其妙地低。
- 以为全连接层已经过时。全卷积网络确实流行,但分类任务的默认收尾还是全连接或全局平均池化。
自测三问(点开对答案)
1. 全连接层为什么要把三维特征摊平? —— 分类要的是整张图的一个判断,不是每个位置各自的判断。 摊平之后每个类别才能对「任意位置的任意特征」统一加权。 2. 参数量的大头在哪? —— 最后的全连接层。5408 到 128 一层就是 69 万参数,是整个网络参数量的绝大部分。 3. 摊平顺序错了会怎样? —— 不报错,但结果全错。权重形状对得上、数值也搬过去了,只是每个像素接错了位置。零件齐了。下一节把它们拼成一个完整网络端到端训练一遍,看卷积特征在真实任务上比原始像素强多少。
- ☐ (本节完,下一节 5.10 深层卷积神经网络的学习)