跳到主要内容

加层为什么没用 — 弯折才是能力的来源

这一章讲三件事: 为什么「多叠几层」这个想法本身是错的; 真正让模型变强的那一下是什么;以及它换走了你什么。 它在全书链条里的位置: 第 02、03 章那台机器只会画直线,而现实里的关系大多是弯的。 这一章是全书第一次「加能力」,也是第一笔明码标价的交易—— 后面每一章都在做同样的事:加一样能力,付一样代价。

1. 先看现象:同一份数据,还能不能更准

第 03 章那个线性模型的成绩是:测试集均方误差 25,折回美元是平均差 5000 美元左右1。 基准是 9250 美元,所以它确实有用。但 5000 美元买房子还是差得离谱。

书的第一反应和你一样:加一层试试。

model.add(tf.layers.dense({
inputShape: [12], units: 50, activation: 'sigmoid', kernelInitializer: 'leCunNormal'
}));
model.add(tf.layers.dense({units: 1}));

这个模型有两层。第一层叫隐藏层——「隐藏」的意思很朴素: 它的输出不出现在模型外面,你既不给它喂正确答案,也看不到它吐什么2。 第二层是输出层,和第 03 章那个模型一模一样。

书里给这类模型起了个名字:多层感知机(multilayer perceptron,常缩写成 MLP)。 它有两个特征:数据一路向前不回头,以及至少有一个隐藏层3

成绩:测试集均方误差 1415,折回美元是 370039004。比 5000 好了两成多。

但这一章真正要回答的不是「好了多少」,而是「好在哪一步」。 因为如果你只把 activation: 'sigmoid' 那一行注释掉,其余一个字不改, 成绩会立刻退回 25 ——和单层线性模型没有区别5

多的那一层没有带来任何东西。带来东西的是那一行 activation

2. 顶层全景

┌──────────── 隐藏层:50 个单元 ────────────┐
12 个标准化后的数 →│ 每个单元:12 个数各乘一个权重、加总、加偏差 │→ 50 个数
│ 然后 ⚡ 每个数各自过一遍 sigmoid ⚡ │
└────────────────────────────────────────┘

输出层:50 个数 × 50 个权重 + 1 个偏差

1 个数:预测的房价

图说:整张图里只有 ⚡ 那一步是新的。去掉它,这两层会在代数上塌成一层 ——
下一节用两行算式证明这件事。

参数账也算得清清楚楚(书里的 model.summary() 直接打出来了)6:

输出形状参数个数怎么来的
隐藏层(密集,50 单元)[null, 50]65012 × 50 个核 + 50 个偏差
输出层(密集,1 单元)[null, 1]5150 × 1 个核 + 1 个偏差
合计701第 03 章那个线性模型是 13 —— 54 倍

3. 承重节:直线叠直线,还是直线

这一节是本章的地基。它是全书唯一一个可以纯用代数算完的结论。

先算给你看

假设有两层,每层都只做「乘一个数、加一个数」这件事:

第一层: f(x) = k₁ × x + b₁
第二层: g(x) = k₂ × x + b₂

把第一层的输出喂给第二层(这个动作叫「级联」):

h(x) = g(f(x))
= k₂ × (k₁ × x + b₁) + b₂
= (k₂ × k₁) × x + (k₂ × b₁ + b₂)
└────┬───┘ └─────┬────┘
新的斜率 新的截距

图说:h 仍然是一条直线,只是斜率和截距换了个数。
叠一百层结果一样 —— 你花了一百层的算力,买到的还是一条直线。

这就是第 1 节那个实验的全部解释。sigmoid 注释掉之后, 那个「两层模型」在数学上和一层完全等价,所以成绩退回 25 一点也不奇怪7

书把这件事列为搭多层网络时最常见的陷阱,并且给了个警告: 这么干不只是白费算力,还会带来计算上的不稳定——去掉 sigmoid 之后的损失曲线抖得明显更厉害8

那加一下弯折会怎样

第 1 节那一行 activation: 'sigmoid' 配的这种函数,正式名字叫激活函数—— 它夹在两层中间,负责把上一层算出来的每个数各自弯一下。 这一章用的这个 sigmoid 是一个挤压函数:不管你给它多大或多小的数,它都挤进 0 到 1 之间9

S(x) = 1 / (1 + e^(−x))

S(1.0) = 0.731
S(0.5) = 0.622
S(0.0) = 0.5 ← ⚠ 原书这一处印成了 0.0,应为 0.5(x = 0 时分母是 2)

图说:它是一条 S 形曲线 —— 中间陡、两头平。关键在于**它不是直线**。

弯的东西级联起来,能造出全新的形状。 书拿另一个常用的弯折函数举例: ReLU(负数一律归零,正数原样通过)。两个经过缩放的 ReLU 级联,得到的是一个中间带下降段的阶梯, 和原来的 ReLU 完全不同;再往下级联,还能造出「窗口」形状、大窗口里套小窗口的形状10

于是书给出了这一章的中心句:

神经网络本质上就是函数的级联。 每一层是一个函数,叠起来就是把它们级联; 而只有非线性函数级联起来才会长出新形状11

它能表示多丰富的关系,有个名字叫容量

容量(capacity)指的是这个模型能学的输入输出关系有多大范围12。 有了非线性隐藏层,容量就比纯线性模型大——这就是准确率提升的来源。

书举了两个能想明白的例子:人的身高和年龄,只在某个年龄段里近似成直线, 之后增长变缓、最后几乎不变;社区犯罪率和房价,也只在一定范围内才是直上直下的关系13直线表示不了这两种关系,S 形曲线可以。

一个立刻会冒出来的疑问

「换成弯的,那原来那些本来就是直的关系,是不是学不了了?」

不会。书的回答是:sigmoid 中间那一段本来就非常接近一条直线; ReLU、tanh 这些常用的弯折函数也都有近似线性的区段。 如果某个输入和输出确实是直线关系,模型完全可以把权重调到落在那一段上14

这句话值得记住,它解释了为什么「加非线性」从来不是一次冒险。

4. 容量不是加了就一直涨

那再加一层呢?书试了:再插一个 50 单元的 sigmoid 隐藏层15

模型参数量测试集均方误差折回美元
线性(第 03 章)1325约 5000
一个隐藏层70114~153700~3900
两个隐藏层325110.8~13.43280~3660

参数从 701 涨到 3251(4.6 倍),误差只从 3800 降到 3500 左右。 多出来的 2550 个参数,来自第二个隐藏层的 [50, 50] 核加 50 个偏差15

这就是边际递减。 书没有在这里深挖,但它把这个问题放进了练习题: 再加更多隐藏层会怎样?什么因素会让加层不再管用?16 真正的答案在第 11 章——那一章会告诉你,继续加下去的下场叫过拟合。

5. 主走查:同一条记录,穿过 701 个数

这一章的每个承重机制,在这条走查上各占一步。数字全部来自书里,标注除外。

我们仍然拿第 03 章那条记录:{crim: 0.3237, …, tax: 222, …, lstat: 2.94}

发生了什么具体的数 / 状态
112 个特征,标准化后进入模型形状 [1, 12]
2隐藏层第一步:12 个数各乘一个权重、加总、加偏差,做 50 遍用掉 12 × 50 + 50 = 650 个参数,得到 50 个数
3假设其中三个单元此刻算出来是 1.00.50.0这一步还没有任何弯折,如果就此打住,整个模型等价于一条直线
4⚡ 每个数各自过一遍 sigmoid1.0 → 0.731,0.5 → 0.622,0.0 → 0.5——全部被挤进 0~1
5输出层:50 个数各乘一个权重、加总、加偏差用掉 50 + 1 = 51 个参数,得到 1 个数
6全模型参数合计701 个,是线性模型 13 个的 54 倍
7训练 200 轮,拿测试集考均方误差 14~15,折回美元 3700~3900(线性模型是 5000)
8对照实验:把第 4 步删掉,其余一字不改均方误差退回 约 25,和一层线性模型没有区别
9打开隐藏层的核看一眼形状 [12, 50],600 个数
10判决这 600 个数一个也读不出含义——第 03 章那 13 个数是每个都读得懂的

第 3、4、8 三步是这条走查的心脏。 弯折加不加,只差一行代码; 而模型能力从「一条直线」变成「能拟合弯的关系」,全在这一行上。

第 9、10 步是这一章的代价。 下一节讲它。

6. 代价:那 600 个数,从此没人读得懂

第 03 章末尾你刚学会读权重:正负号说方向,绝对值说分量,RM(房间数)是 +3.39, LSTAT(辍学率)是 −3.80,一条条都对得上常识。

现在同一个动作在这个模型上还能做,但读不出任何东西了。

原因不难想:隐藏层那 50 个单元,每一个都是 12 个特征的某种加权混合。 第 7 号单元代表什么?没有名字。它不是「房间数」也不是「犯罪率」, 它是模型为了拟合数据自己造出来的一个中间量。 书的说法是:很难去界定隐藏层的 50 个输出分别象征的意义; 创建这些高维空间维度是为了让模型能在其中学习非线性关系,而人脑并不擅长处理这个17

原书这里有一处数对不上,当场说明: 书在这一段写「隐藏层由 50 个单元组成, 这意味着其权重尺寸为 [18, 50],该核有 900 个单独的权重参数」17但同一章前面 model.summary() 的输出写得很清楚:这个核的形状是 [12, 50], 加上 50 个偏差共 650 个参数6。输入只有 12 个特征,不可能是 18。 本章按 [12, 50]、600 个核参数写。 结论不受影响:几百个,一个也读不出来。

书自己把这笔交易明说了:

选择深度模型而不是浅层模型,本质上是牺牲一些可解释性来换取更大的模型容量。18

这是全书第一笔明码标价的交易,也是第 22 章那个落点的第一块砖。 到那一章你会看到,这笔交易的账单远不止「读不懂」这么轻。

7. 两种数:训练会改的,和你自己定的

这一节回答:units: 50 这个 50 是谁定的。

到这里为止,模型里出现过的数其实分两类,混起来就什么都想不清楚: 一类是训练自己调的,叫权重;另一类是训练全程一动不动、由你定的,叫超参数19

权重超参数
谁定的训练自己调的你定的
什么时候变每一批数据都在变训练全程一动不动
例子那 701 个核和偏差隐藏层几个、每层多少单元、用哪个激活函数、学习率、训几轮、批多大
怎么定反向传播 + 梯度下降没有自动办法——见下面

「超」这个字的意思是它们比权重高一层:超参数决定了权重有多少个、初值是什么、 以及训练时按什么规矩更新19

为什么超参数不能像权重一样自动调

因为它们大多是离散的,梯度下降在它们身上根本用不了。

回想第 02 章:梯度是「朝哪挪损失涨得最快」。可**「隐藏层要 50 个单元还是 51 个」 这件事上没有『挪一丁点』这种操作**——单元数只能是整数,优化器的类型更是几个名字里挑一个。 书的说法是:验证集损失对它们是不可微的,所以在超参数空间做梯度下降是不现实的20

于是只剩三条土办法21:

  1. 继承。 你的问题和一个已经解决好的问题像,就照抄它的设定,再在小范围里搜一搜;
  2. 凭经验猜。 老手的直觉大多不是最优,但通常是个不错的起点;
  3. 网格搜索。 要调的东西少于四个时可以用:把每个超参数的候选值列出来,做叉积,一组一组全试一遍。

网格搜索长这样22:

单元数的候选: {10, 20, 50, 100, 200} 5 个
学习率的候选: {1e-5, 1e-4, 1e-3, 1e-2} 4 个
叉积: 5 × 4 = 20 组

对每一组: 按这组设定建模 → 完整训练一遍 → 记下验证集损失
最后挑: 验证集损失最低的那一组

图说:20 组就要完整训练 20 次。再加一个要调的东西,次数就乘上去 ——
所以书说超参数一多,网格搜索就不现实了,得换随机搜索或贝叶斯方法。

候选值的范围又是怎么定的? 书很坦白:这个领域目前也没有正式的答案, 靠经验和直觉,还受算力限制——单元太多,训练和推断都会慢到不能忍23

8. 作者的判断与证据

书里给了证据的:

  • 去掉 sigmoid,两层模型退回单层水平。 这是书自己做的对照实验, 只注释一行、其余不动,误差从 14~15 回到约 255
  • 加非线性隐藏层能提准确率。 有具体数字:25 → 1415 → 10.813.4415
  • 级联线性函数仍是线性。 这是代数恒等式,书写出了完整推导7
  • 隐藏层权重读不出含义。 书直接把核打印出来给你看了一屏数17

属于作者判断、书里没给证据的:

  • 「深度模型换容量、牺牲可解释性」是一句总结性判断,书紧接着承认 研究者仍在尝试找更好的解释办法,并且已有一些进展18
  • 「先继承、再凭直觉、最后网格搜索」这三条策略,是行业经验的归纳,不是实验结论21
  • 书用「人脑并不擅长处理高维空间中的非线性关系」解释可解释性的丧失17—— 这是一个直觉说法,不是可验证的命题。

判断(我们的,不是书里的): 这一章最容易被读浅的地方,是把它当成「加层技巧」。 它真正建立的是一条贯穿全书的记账习惯:每加一样能力,就问「我付出了什么」。 这一章付的是可解释性;第 06 章付的是算力和数据规模;第 17 章付的是训练稳定性。 如果错,会错在: 如果读者只把这本书当 API 手册用,这条记账线对他没有价值—— 他只需要知道「隐藏层要配激活函数」这一条操作规矩就够了。

9. 边界与局限

  • 本章的对照实验只在波士顿房价这一个数据集上做过。 书没有换数据集验证。
  • 书没有讲清「该配多少单元」。 50 这个数从哪来?书的回答是:靠试 (而且把网格搜索留成了练习题)24
  • 激活函数只讲了 sigmoid 一个,ReLU 只画了图。 ReLU 真正上场要到第 06 章。
  • 书没有讲批标准化、残差连接这些让深层网络训得动的东西。 第 01 章列过名字, 批标准化的机制到第 11 章的武器表里才回来,残差连接全书没讲。
  • 「加层的边际递减」只给了数,没给原因。 原因(过拟合)要到第 11 章。
  • 超参数优化只给了网格搜索的伪代码。 随机搜索、贝叶斯方法书里只留了两篇参考文献25

10. 可带走的

  1. 直线叠直线还是直线,这是两行代数就能算出来的:k₂(k₁x + b₁) + b₂ 仍是一条直线。 只加层不加非线性,是纯浪费;
  2. 能力来自每层中间那一下弯折,这个弯折函数叫激活函数。 sigmoid 把任何数挤进 0~1;S(1.0)=0.731,S(0.5)=0.622,S(0.0)=0.5;
  3. 神经网络就是函数的级联,而只有非线性函数级联才会长出新形状;
  4. 容量 = 这个模型能表示多丰富的输入输出关系。 非线性隐藏层把容量顶上去;
  5. 加了非线性不会丢掉直的关系——sigmoid 中段本来就近似直线;
  6. 具体成绩: 线性 13 个参数、误差 5000 美元;一个隐藏层 701 个参数、37003900; 两个隐藏层 3251 个参数、32803660。边际在递减;
  7. 代价是可解释性。 线性模型那 13 个数每个都读得懂;隐藏层这 600 个数一个也读不出来。 深度学习是拿可解释性换容量,这是全书第一笔明码标价的交易;
  8. 分清两种数: 训练会改的叫权重(701 个);训练不改、由你定的叫超参数 (层数、单元数、激活函数、学习率、轮次、批尺寸);
  9. 超参数不能用梯度下降调,因为它们大多是离散的、不可微。只能继承、凭经验、 或者网格搜索(5 个单元数 × 4 个学习率 = 训练 20 次);
  10. 这一章的实验方法本身值得学会: 想知道某个部件有没有用, 把它删掉、其余一字不改,再跑一遍

11. 原文地图

主题原书章原文位置
线性模型误差约 5000 美元、加一层的动机第 3 章text/14-ch03.txt:19(搜「5000美元以内」)
双层模型代码、隐藏层、多层感知机第 3 章text/14-ch03.txt:23(搜「multiLayerPerceptronRegressionModel1Hidden」) · text/14-ch03.txt:38(搜「多层感知机」)
model.summary() 输出:650 / 51 / 701第 3 章text/14-ch03.txt:45(搜「dense_Dense1」) · text/14-ch03.txt:58(搜「12 × 50 + 50 = 650」)
双层模型成绩 1415、37003900 美元、54 倍参数第 3 章text/14-ch03.txt:72(搜「3700~3900美元」)
sigmoid 挤压、算例、可微第 3 章text/14-ch03.txt:76(搜「挤压」) · text/14-ch03.txt:83(搜「0.731」) · text/14-ch03.txt:87(搜「光滑且可微」)
非线性与容量:身高年龄、犯罪率房价第 3 章text/14-ch03.txt:99(搜「身高与年龄」)
sigmoid 中段近似直线,不丢线性关系第 3 章text/14-ch03.txt:101(搜「非常接近于一条直线」)
级联线性仍是线性(完整推导)第 3 章text/14-ch03.txt:108(搜「k2 * (k1 * x + b1) + b2」) · text/14-ch03.txt:108(搜「最后的结果仍是线性函数」)
级联 ReLU 长出新形状;神经网络 = 函数级联第 3 章text/14-ch03.txt:110(搜「窗口」)
容量的定义第 3 章text/14-ch03.txt:114(搜「模型能够学习的输入和输出关系的范围」)
三层模型:3251 参数、10.8~13.4第 3 章text/14-ch03.txt:137(搜「3251个参数」) · text/14-ch03.txt:139(搜「10.8~13.4」)
去掉 sigmoid 的对照实验:退回 25第 3 章text/14-ch03.txt:159(搜「上升至接近25」) · text/14-ch03.txt:161(搜「必须在隐藏层中添加非线性激活函数」)
隐藏层权重读不出;[18, 50] / 900 那处矛盾第 3 章text/14-ch03.txt:185(搜「900个单独的权重参数」)
牺牲可解释性换容量第 3 章text/14-ch03.txt:187(搜「牺牲一些可解释性」)
超参数的定义与清单第 3 章text/14-ch03.txt:197(搜「超参数」) · text/14-ch03.txt:201(搜「模型中密集层的数量」)
为什么超参数不可微、不能梯度下降第 3 章text/14-ch03.txt:221(搜「不可微的」)
三条策略与网格搜索 5×4=20第 3 章text/14-ch03.txt:223(搜「继承」) · text/14-ch03.txt:227(搜「网格搜索」) · text/14-ch03.txt:231(搜「hyperparameterGridSearch」)
候选范围怎么定;随机搜索与贝叶斯第 3 章text/14-ch03.txt:243(搜「没有正式的答案」) · text/14-ch03.txt:245(搜「贝叶斯方法」)

Footnotes

  1. 出处:「第 3 章 添加非线性:升级加权和」第 19 段(text/14-ch03.txt:19,搜「5000美元以内」)。这个数和第 03 章那个 5.03 千美元是同一件事。

  2. 出处:「第 3 章」第 38 段(text/14-ch03.txt:38,搜「其输出在模型外是不可见的」)。

  3. 出处:「第 3 章」第 38 段(text/14-ch03.txt:38,搜「多层感知机」)。原文给的两个特征是:简单的无环拓扑结构(前馈神经网络),以及至少有一个隐藏层。

  4. 出处:「第 3 章」第 72 段(text/14-ch03.txt:72,搜「3700~3900美元」)。原文同时给出测试集均方误差 14~15,并说明具体数字因随机初始化而不同。 2

  5. 出处:「第 3 章」代码清单 3-3 与第 159 段(text/14-ch03.txt:159,搜「上升至接近25」)。原文的原话是:「如果不使用 sigmoid 激活函数,双层神经网络就和单层线性回归模型没什么两样!」 2

  6. 出处:「第 3 章」第 45~58 段(text/14-ch03.txt:45,搜「dense_Dense1」;text/14-ch03.txt:58,搜「12 × 50 + 50 = 650」)。原文明确说这个核的形状是 [12, 50]、偏差形状是 [50] 2

  7. 出处:「第 3 章」第 103~108 段(text/14-ch03.txt:108,搜「k2 * (k1 * x + b1) + b2」;text/14-ch03.txt:108,搜「最后的结果仍是线性函数」)。 2

  8. 出处:「第 3 章」第 161 段(text/14-ch03.txt:161,搜「必须在隐藏层中添加非线性激活函数」)与图 3-4 说明,第 163 段(text/14-ch03.txt:163,搜「损失曲线也变得更加不平滑」)。

  9. 出处:「第 3 章」第 76 与 83 段(text/14-ch03.txt:76,搜「挤压」;text/14-ch03.txt:83,搜「0.731」)。注意: 原文这一行把 S(0.0) 的结果印成了 0.0;按同页给出的公式 S(x) = 1 / (1 + e^-x),x = 0 时分母是 2,结果应为 0.5。前两个数(0.731、0.622)都对得上公式。

  10. 出处:「第 3 章」第 110 段与图 3-3 说明,第 110 段(text/14-ch03.txt:110,搜「窗口」)。ReLU 的定义见图 3-2 说明,第 93 段(text/14-ch03.txt:93,搜「relu(x)」)。

  11. 出处:「第 3 章」第 110 段(text/14-ch03.txt:110,搜「神经网络就是函数的级联」)。

  12. 出处:「第 3 章」第 114 段(text/14-ch03.txt:114,搜「模型能够学习的输入和输出关系的范围」)。

  13. 出处:「第 3 章」第 99 段(text/14-ch03.txt:99,搜「身高与年龄」)。原文还补了一句:犯罪率和房价的关系更像是一个倒过来的 sigmoid。

  14. 出处:「第 3 章」第 101 段(text/14-ch03.txt:101,搜「非常接近于一条直线」)。

  15. 出处:「第 3 章」第 137~139 段(text/14-ch03.txt:137,搜「3251个参数」;text/14-ch03.txt:139,搜「10.8~13.4」)。多出的 2550 个参数来自形状 [50, 50] 的核加形状 [50] 的偏差。 2 3

  16. 出处:「第 3 章」练习(1),第 910~914 段(text/14-ch03.txt:912,搜「哪些因素会导致更多的隐藏层无法提升计算准确率」)。原文的提示是「观察模型在训练集上的误差」——这正是第 11 章的入口。

  17. 出处:「第 3 章」第 185 段(text/14-ch03.txt:185,搜「900个单独的权重参数」)。这一段与同章第 58 段的 model.summary() 说明互相矛盾: 那里写的是核形状 [12, 50]、该层共 650 个参数(核 600 + 偏差 50);这里写成 [18, 50]、900 个核参数。输入特征只有 12 个,18 无从解释。本章按 [12, 50] 与 600 个核参数写,并当场说明。 2 3 4

  18. 出处:「第 3 章」第 187 段(text/14-ch03.txt:187,搜「牺牲一些可解释性」)。同段承认研究者仍在尝试更好的解释办法,并给了 LIME 和 "The Building Blocks of Interpretability" 两篇参考。 2

  19. 出处:「第 3 章」第 197 段(text/14-ch03.txt:197,搜「超参数」)。原文:超参数「要比权重参数高一个层面,故而得名」。 2

  20. 出处:「第 3 章」第 221 段(text/14-ch03.txt:221,搜「不可微的」)。原文还补了一句:即使对连续且可微的超参数(比如正则化因子),追踪它的梯度计算开销通常也过大。

  21. 出处:「第 3 章」第 223~227 段(text/14-ch03.txt:223,搜「继承」)。 2

  22. 出处:「第 3 章」第 227 段与代码清单 3-4,第 231~242 段(text/14-ch03.txt:227,搜「网格搜索」;text/14-ch03.txt:231,搜「hyperparameterGridSearch」)。

  23. 出处:「第 3 章」第 243 段(text/14-ch03.txt:243,搜「没有正式的答案」)。

  24. 出处:「第 3 章」练习(6),第 924 段(text/14-ch03.txt:924,搜「近似几何序列」)。原文建议的搜索间隔是 2、5、10、20、50、100、200 这样的近似几何序列。

  25. 出处:「第 3 章」第 245 段与脚注 6、7(text/14-ch03.txt:245,搜「贝叶斯方法」;text/14-ch03.txt:247,搜「Random Search for Hyper-Parameter Optimization」)。