扁平世界的困境
你已经知道单个[[artificial-neuron|人工神经元]]做的事:它取来各个输入,每个乘以一个[[weight|权重]],加起来,再加上一个[[bias-term|偏置]],然后把这一个数往下传。这串操作里的每一步都是直线运算——缩放与相加,仅此而已。这恰恰就是[[linear-map|线性映射]]的定义,而它有一个看似平淡却要命的性质:一个接一个地做,你永远得不到任何新东西。
下面这个结论,每个人第一次听到都会惊讶。设想你把十层这样的神经元叠起来,每一层喂给下一层,中间不放任何激活——一个又深又唬人的网络。从数学上看,整座塔会坍塌。把十个权重矩阵相乘,你得到的只是一个矩阵;这十层的行为与单单一层*完全相同*。深度全白搭,它在你的数据上最多只能画出一个平面。它弯不下来。
解决办法小得几乎令人难为情。在每个神经元算出它的加权和之后,我们让这个数再多过一道工序——一个简单的、*非直*的函数——然后才往下传。这道工序就是[[activation-function|激活函数]]。它是水管上的那个折弯,那一点小小的弯折在一整层里重复,就让下一层得以叠出一道褶子,再下一层叠出褶子之上的褶子。一弯接一弯,网络便获得了描摹任意曲线的自由。
为什么一个弯折就够了
每个神经元只加一个朴素的弯折,竟能换来这么多,感觉像是作弊。但它背后有一条货真价实的定理。[[universal-approximation-theorem|通用逼近定理]]说:一个只含一层这种弯折神经元的[[hidden-layer|隐藏层]]网络——只要神经元够多——就能把你想要的*任何*连续函数逼近到你要求的任意精度。非线性正是开启这扇门的那一味原料。它划开了「只会画直尺的工具」与「什么都能画的工具」之间的界限。
这个弯折还得悄悄承担一件事:它必须是*可微的*(或足够接近可微)。记得网络靠把权重往降低误差的方向轻推来学习,而要知道那个方向,我们需要每一步的斜率。所以激活函数不能是随便哪个起伏——它必须是一个我们能算出斜率、并把斜率往回传的函数。记住这一点;它解释了接下来四个经典激活函数为何长成那副模样。
压缩派:sigmoid 与 tanh
最古老的弯折是[[sigmoid-function|sigmoid]],一条平滑的 S 形曲线。给它任何一个数——负一百万也好,正一百万也好——它都温和地把答案挤进 0 到 1 之间。大的负数被压平向 0,大的正数被压平向 1,而正中间它陡峭地穿过 0.5。它的吸引力很直观:输出读起来像一个柔和的「这个神经元开到几分?」,或者一个概率。几十年里它都是默认选项,至今仍是「是/否」分类器*最后*那个神经元的自然之选。
它的近亲是[[tanh-activation|tanh]],同样的 S 形,但挤进 −1 到 1,并以零为中心。这个「以零为中心」是实打实的改进:当一层的输出在零附近保持平衡时,下一层的梯度表现更好,学习往往也更快。如果你在隐藏层里非要用一个压缩型激活,tanh 几乎总是胜过 sigmoid。
但这两个压缩派都共享一个不声不响的缺陷,它一度让深度学习停滞了好些年。看那 S 形两端平坦的尾巴:在那里,曲线几乎水平,所以斜率几乎为零。在一个深堆叠里,学习信号是靠把这些斜率一层接一层地*相乘*往回传的。把许多接近零的数相乘,信号还没传到靠前的层就缩减成乌有——那些层便不再学习。这就是著名的[[vanishing-gradient|梯度消失]]问题,是压缩派的阿喀琉斯之踵。
ReLU:偷懒的天才
打破僵局的那个激活函数,简单到几乎有点欺负人。[[relu|ReLU]]——修正线性单元——只做一件事:输入若为正,原样放行;若为负,输出零。整个函数就这么多。它看上去像一块平坦的地板,到零点处突然向上翘起。没有指数运算,没有要计算的曲线——只是「好消息留下,坏消息丢掉」。
def relu(x):
return x if x > 0 else 0
# slope (what backprop sends back):
# x > 0 -> 1 (full signal passes, undimmed)
# x < 0 -> 0 (this neuron is 'off', no signal)
#
# sigmoid(x) slope peaks at just 0.25 and fades to ~0 in the tails;
# relu's slope is a clean 1 wherever it's active -> gradients survive depth.那个干净的斜率 1 就是魔法所在。学习信号流经激活的 ReLU 神经元时不被削弱,于是即便是很深的堆叠也能持续训练。再加上它的计算便宜到尘埃里,你就明白为什么 ReLU 成了视觉、语言乃至几乎一切领域中隐藏层的默认激活。[[deep-learning|深度学习]]热潮的大半,就坐在这个一行的小把戏之上。
ReLU 并非完美无瑕,它的怪癖值得坦白说说。因为对任何负输入,它的输出和斜率都是零,一个神经元可能被推进负区并*留*在那里——它的梯度为零,于是再也不更新。人们管这叫「死掉的 ReLU」。补救办法是一点小改动(leaky ReLU、GELU 之类,让负的一侧也漏过一丝),但主旨不变:朴素的 ReLU 仍是隐藏层里头一个值得一试的明智之选。
Softmax:委员会的投票
另外三个激活函数都一次只作用于一个神经元。[[softmax|Softmax]]是个异类:它一次看*一整排*末端神经元,把它们的原始分数变成一组加起来恰好等于 1 的概率。设想一个分类器,最后一层每个类别配一个神经元——猫、狗、鸟。Softmax 取来这三个分数,相当于回答:「70% 是猫,25% 是狗,5% 是鸟。」它放大领先者、压低其余者,但总和永远保持在 100%。
这正是为什么 softmax 几乎只待在多类分类器的*输出端*,从不出现在隐藏层。它是那一层,把网络内部的意见翻译成干净、可比较的答案。还有一句诚实的提醒值得带着:softmax 给出的那个看上去自信的 99%,*并不*是经过校准的真相——模型完全可能既响亮又流利地犯错。Softmax 给你的是一个整齐的分布,而非这个分布正确的保证。
它在我们的搭建中处在哪一环
退一步,看看你现在手里这套东西的形状。一个神经元做它的加权和;一个激活把结果弯折;一层就是一排这样的神经元;中间夹着弯折的若干层叠在一起,就是一个[[multilayer-perceptron|多层感知机]]——一个真正有表达力的网络。激活函数正是那个唯一的部件,立在「一张高级电子表格」与「能学会一张脸的曲线、一句话的语法的东西」之间。
- 一个输入到来,流过各层——每个神经元先求和,再用它的激活函数弯折。这就是上一篇里见过的前向传播。
- 在末端,sigmoid 或 softmax 把原始分数塑造成可用的答案或概率。
- 误差被测量出来,然后往回送——关键在于,每个激活函数的*斜率*决定了有多少学习信号能从它身上流回去。
- 权重轻轻挪动一点;在数据上反复,直到这些弯折安顿成一个贴合的形状。
上面第三步,正是通往下文的那座桥。激活为何必须可微,梯度消失为何要紧,ReLU 那干净的斜率 1 为何是一次突破——这一切都指向我们至今只点到为止的一套机制:网络如何把自己的错误往回传,从而自我教导。这套机制就是[[backpropagation|反向传播]],正是下一篇导读的主题。如今它要作用的每一个部件,你都已经握在手里。