本节摘要:这是激活函数存在的全部理由——引入非线性。本节用一句话证明"多层线性叠起来还是线性",并用二维分类的直觉说明为什么线性表达不够用,最后用一个极简网络演示非线性如何让决策边界从一条直线变成任意曲线。
上一节我们把三要素摆上了天平,现在轮到给"表达力"这个砝码开个头。你可能听过这种说法:"不加激活函数,多少层都白搭。"这句话不是夸张,是数学上能当场格出来的。本节把这句话推到台前,讲清楚它到底在说什么。
考虑没有任何中间变换的网络。每一层做的事就是:拿上一层输出做一次线性加权再加偏置。设两个连续层的变换分别是 y = W₁x + b₁ 和 z = W₂y + b₂,把前一个代进后一个:
z = W₂(W₁x + b₁) + b₂ = (W₂W₁)x + (W₂b₁ + b₂)
右边的系数 W₂W₁ 还是一个矩阵,W₂b₁ + b₂ 还是一个向量,也就是说两步线性变换合起来仍然是线性变换。推而广之,无论叠多少层,整个网络化简到底仍然是一条直线、一张平面、一个超平面。我们叠了五十层,表达能力却白白压回了单层。
想出一条直线,永远没本事画出一条把两类点绕圈包住的弯曲边界。这就是"白纸"的意思:表达空间摊平了,再多层也撑不出曲线的立体感。
一旦在前向里夹进一个非线性函数,上面那条"可合并"的等式立刻失效——W₂(σ(W₁x + b₁)) 没法再化简,两个相邻层各自独立地对表达空间做不同方向的弯折。理论上,只要隐藏层足够宽且激活函数足够灵活,网络就能以任意精度逼近任意连续函数。这条性质就是俗称的"万能逼近"。
这里值得强调一个容易误解的点:非线性给的是"可能性",不是"必然成功"。 就好比毛笔给了你能写出狂草的能力,但真要把字写好的仍是练法。激活函数只是确保网络"理论上能表达",真正表达得好不好,还依赖损失与优化器是否把参数导向合适的峰谷(这正是后面三章的事)。
用一个最典型的例子来说服自己:异或问题(XOR)。四组输入,输出是 0 或 1,但两类点在二维平面上呈对角交叉,任何一条直线都没法把 0 和 1 分开。
def xor_cannot_split(): # 目标:把 0 类和 1 类用一条直线分开 points = { (0,0): 0, (1,1): 0, (0,1): 1, (1,0): 1, } # 任取一条直线 ax+by+c=0,都存在至少一个 0 类点与 1 类点落在同侧 # 例:直线 y = -x + 0.5 会把 (0,1) 和 (1,0) 分到不同侧,却把两个 0 类也拆开 return "线性模型必然误分类至少一个样本"
给这个网络接一个超平面,无论如何旋转平移都过不了关。但只要在两节点之间插一层非线性的激活函数,2 个隐藏节点 + ReLU 就能作出能包住对角两类的边界。这也是历史上"单层感知机搞不定 XOR、加一层就解决"那场争论的核心:突破性不在层数,而在非线性。
💡 关键直觉:判一个地方要不要激活函数,就问自己一句——"这里如果只有线性变换,表达会不会被摊平?"每个隐藏层都该有它自己的"弯折",否则就白叠一层。
有些框架里你会看到把激活函数用在"输出层"当纯缩放,也有新手把线性激活(即不加激活)用在中间层想"减少复杂度"。前者要看任务(回归输出层确实常用线性激活,下一节会讲),后者基本是误区——中间某一层是线性,它前后两层照样能弯折,问题没那么大;但若每层都线性,才真正白纸化。真正的取舍发生在"每一层都用 act"这套默认之上,而不是"随便哪一层省掉"。
⚠️ 常见坑:以为只要"加一层"就自动获得非线性。如果这一层夹的激活本身是线性(或未加激活),在外层的加权求和一合并,照样塌回一条直线。判断依据永远是"有没有非线性函数夹在层间",而不是"层够不够多"。
讲完表达力,别忘了第 1.2 节强调过的另一重身份——激活函数还站在反向路上。非线性带来的不只是"能表达复杂",还顺带决定了"信号传得远不远"。
具体说:反向传播时,每一层的梯度都要乘上激活函数的导数(斜率)。如果激活几乎处处平坦(饱和),那导数接近 0,梯度就会被一截截削掉,传不到前面几层——这就是第 2 章 2.4 要讲的梯度消失。因此评估一个激活函数,从来都是两件事一起看:
| 激活函数 | 前向表达(非线性) | 反向斜率(梯度供给) |
|---|---|---|
| Sigmoid | 有 | 两端饱和,看低 |
| Tanh | 有 | 两端饱和,居中 |
| ReLU | 有(分段线性) | 正区恒 1、负区恒 0 |
| Leaky/ELU/Swish | 有 | 负区留活口,较稳 |
这张表是 2.2 与 2.4 的总纲。现在先把它记住:"会表达"和"梯度给劲"是两把尺子,别只量一把。
Q:是否每一层都必须加激活?
A:隐藏层几乎必然要为"弯折"加;但输出层按任务不同——回归常用线性激活(不加),分类用 Sigmoid/Softmax。所以严格说"每层必须有激活"不完全准确,正确的说法是"每个需要引入非线性的隐藏层都该加,输出层看任务"。
Q:只有一个隐藏层不带激活,危害大吗?
A:不大,因为前后层仍有非线性彼此弯折。真正"白纸化"的是"所有层都线性",那才会塌回单层。所以不必为一两层偶尔缺激活而过度紧张,重点是不系统的、整路都缺。
Q:把激活放在损失之前会有问题吗?
A:没问题——这正是输出层激活的位置。真正要注意的是"损失 + 输出激活"的组合要匹配(比如 Softmax 配交叉熵),这一节不展开,第 3 章会专门讲这一类"婚配"。
非线性证明了激活函数的必要性,下一节就逐一看台上这些候选——从 Sigmoid 到 Swish,谁更配得上默认位。