📕 第5章 卷积神经网络
📄 一句话概括

一层 3×3 只看 3×3。叠三层,最上面那个点就看到了 7×7。感受野随层数线性增长,每层加 2。 同样 7×7 的感受野,三层 3×3 只要 27744 个参数,一层 7×7 要 50208 个,是 55%。 省下的不只是参数,还多了两次非线性。这就是 VGG 的核心论点:深度比宽度划算。

📝 本节和前面几节的关系

5.3 的卷积层是单层的,这一节讲堆叠。 5.10 节会把堆起来的网络整个训练一遍。 层数多了梯度传不回去,这个问题第 4 章的反向传播里已经埋下伏笔。

一、感受野是什么

输出上的一个点,对应输入上的一块区域。这块区域就是它的感受野。 第一层是 3×3;第二层的一个点来自第一层的 3×3,而第一层的每个点又是 3×3,所以第二层看到 5×5。 感受野决定「这个神经元能看见多大的东西」。 分类要看整张图,所以最后一层的感受野必须覆盖全图,否则它根本看不到边缘信息。

二、感受野怎么算

每叠一层 3×3,感受野边长加 2。三层堆出 7×7,五层 11×11。 一般式是 r_out = r_in + (k − 1) × j,其中 j 是前面所有步幅的乘积,叫跳跃距离。 有步幅时感受野增长更快:步幅 2 让 j 翻倍,同样层数能覆盖两倍的范围。这也是 5.6 节的一个用法。

三、堆叠的三重好处

第一,参数省。实测 27744 对 50208,只有 55%。 第二,非线性多。三层插了三次 ReLU,一层只插一次。 能表示的函数族大得多,这才是「深」的真正含义。 第三,层次感。 浅层学边缘、中层学部件、深层学物体——这种分层不是设计出来的,是堆层加非线性自然长出来的。

四、VGG 的结构

2014 年的 VGG 就是「全部用 3×3,一路堆到 16 层或 19 层」。 它的贡献不是准确率,是把这个「只用小核、靠深度换感受野」的配方固定下来了。 现在看 VGG 参数很多(一亿四千万),但结构极整洁,是理解卷积网络最好的样本, 很多教材都拿它当骨架图。

五、层数不是越多越好

层数上去,梯度要穿过更多层。 梯度消失和「退化」会一起出现——不是过适,是训练集上的误差都降不下去。 2015 年的 ResNet 用残差连接解决:给梯度留一条直通的短路,让「恒等映射」变成容易学的东西。 这是本书范围之外,但要知道有这件事。 实践里 3×3 是默认选择,因为它是「能看邻居、又不至于太贵」的最小奇数核。 1×1 看不了邻居,5×5 的参数量是它的 2.8 倍。

六、动手 Demo:三层 3×3 抵一层 7×7

算两件事:一是叠若干层 3×3 之后的感受野边长; 二是在 32 通道的前提下,比较「一层 7×7」和「三层 3×3」的参数。

c = 32

# 三层 3×3 的感受野:每层边长加 2
r = 1
for n in range(1, 4):
    r = r + 2
    print("%d 层 3×3  感受野 %d×%d" % (n, r, r))

p3 = 3 * (3 * 3 * c * c + c)      # 三层 3×3
p1 = 7 * 7 * c * c + c            # 一层 7×7
print("一层 7×7 参数 %d" % p1)
print("三层 3×3 参数 %d" % p3)
print("后者是前者的 %.0f%%" % (100.0 * p3 / p1))

实跑输出:

--------------------------------------------------------------------
深层卷积神经网络:三层 3×3 抵一层 7×7
--------------------------------------------------------------------

  一个 3×3 的核,输出上每个点看到输入的 3×3。再叠一层,看到的范围就变大。

  结构          感受野
  ------------------------
  1 层 3×3      3×3
  2 层 3×3      5×5
  3 层 3×3      7×7
  5 层 3×3      11×11

  每叠一层,感受野边长加 2(核边长 3 减 1)。所以三层堆出 7×7 的感受野。

  做法          参数量        非线性次数
  ----------------------------------------
  一层 7×7      50208         1
  三层 3×3      27744         3

  同样的感受野,三层 3×3 只用 55% 的参数,却多插了两次 ReLU。
  **VGG 那篇论文讲的就是这件事:深度比宽度划算。**

  多出来的非线性才是关键。
  **一层 7×7 再宽也只是一个线性变换加一次弯折;三层 3×3 能表示「先找边缘、再用边缘拼角、**
  **再用角拼形状」这样的分层结构。**

感受野那一列是 3×3、5×5、7×7、11×11。每加一层加 2,是等差数列。 参数那一列才是重点:一层 7×7 要 50208 个,三层 3×3 只要 27744 个,55%。 这笔账可以直接算:一层 7×7 是 49 个权重,三层 3×3 是 3 乘 9 等于 27 个。 27 除以 49 约等于 0.55,和实测的 55% 完全对上。 但计算量不是这个比例。三层要跑三次,中间结果还要存下来。 所以堆层是用「算力和内存」换「参数和非线性」。 书里 5-4 节拿 VGG 举例, 想说的就是这笔交换值得——在参数预算固定时,把预算摊到更多层上,效果比堆在一层好。

30 秒实验

  1. 四层 3×3 的感受野多大?参数是一层 9×9 的百分之多少?
  2. 如果中间插一个步幅 2 的池化,第二层的感受野会怎么变?
  3. 为什么说「5×5 的核贵 2.8 倍」?(提示:25 除以 9)

常见误区

  1. 以为感受野是「能看到的像素数」。它是边长,面积要平方。7×7 是 49 个像素,不是 7 个。
  2. 以为堆层一定比大核好。参数省、非线性多,但中间结果要存、要算,算力和内存都更贵。
  3. 以为层数越多越好。没有残差连接的话,堆到十几层就开始退化, 而且退化表现是「训练集误差也降不下去」,和过适完全不同。
自测三问(点开对答案) 1. 三层 3×3 的感受野多大? —— 7×7。每叠一层边长加 2(核边长 3 减 1),三层就是 3 加 2 加 2 加 2。 2. 同样 7×7 感受野,三层 3×3 的参数是一层 7×7 的多少? —— 约 55%。因为三层是 27 个权重、一层是 49 个,27 除以 49 约 0.55。 3. 堆层换来的是什么? —— 更少的参数、更多的非线性、以及分层的特征。代价是算力和内存,不是准确率。

前面所有例子的输出都比输入小。照这样堆十层,图就缩没了。下一节看补零怎么把尺寸撑住。

相关笔记