2. 数学基础回顾:Sigmoid与ReLU的梯度流问题

好,咱们正式开始。在讲 SwiGLU 和 Swish 之前,我必须要先带大家回顾一下两位“老前辈”——Sigmoid 和 ReLU。为什么?因为你不理解它们踩过的坑,就不知道 Swish 到底好在哪里。

说白了,深度学习这么多年,激活函数的核心就两个诉求:让梯度顺畅地流过去,以及别让神经元死掉。Sigmoid 和 ReLU 在这两个问题上,都栽过跟头。

2.1 Sigmoid:梯度消失的“元凶”

Sigmoid 函数长这样:

σ(x) = 1 / (1 + e^(-x))

它的输出范围是 (0, 1)。你想想看,当 x 很大或很小时,函数值会趋近于 0 或 1。这时候导数是多少?

σ'(x) = σ(x) * (1 - σ(x))

当 σ(x) 接近 0 或 1 时,导数就趋近于 0。这就是问题所在。

核心问题:梯度消失

在深层网络中,反向传播时梯度需要逐层相乘。Sigmoid 的导数最大只有 0.25,乘上几层之后,梯度就指数级衰减到接近 0。前面的层几乎学不到东西。

我记得在 2015 年左右,我接手过一个 8 层的全连接网络项目。当时用的就是 Sigmoid,训练了整整两天,loss 死活降不下去。后来换成 ReLU,半天就收敛了。嗯,从那以后,我再也不敢在深层网络里用 Sigmoid 了。

2.2 Sigmoid 的梯度流分析

咱们来算一笔账。假设一个 5 层的网络,每层都用 Sigmoid。反向传播时,梯度要乘以 5 个 σ'(x)。每个 σ'(x) 最大 0.25,那么梯度至少衰减到原来的 (0.25)^5 ≈ 0.001。这还没算权重矩阵的乘法呢。

为什么会这样?因为 Sigmoid 的导数在饱和区几乎为 0。饱和区就是 x 绝对值很大的区域。一旦神经元进入饱和区,梯度就断了。

我的经验: 如果你非要用 Sigmoid,我建议只在输出层用(比如二分类的最后一层)。隐藏层千万别碰。我曾经在隐藏层用过一次,结果就是前面几层的权重几乎没更新,白白浪费算力。

2.3 ReLU:解决了消失,带来了“死亡”

ReLU 的出现,可以说是革命性的。它的公式简单到令人发指:

ReLU(x) = max(0, x)

导数也简单:x > 0 时导数为 1,x ≤ 0 时导数为 0。

你看,正半轴导数恒为 1,梯度消失的问题一下子就解决了。这也是为什么 ReLU 能支撑起深层网络的训练。

但是,ReLU 带来了一个新问题——死亡 ReLU

死亡 ReLU 现象: 当某个神经元的输入一直为负时,它的输出恒为 0,导数也为 0。这个神经元就“死”了,再也无法被激活。更可怕的是,一旦死亡,它永远不会复活,因为梯度为 0,权重无法更新。

我在项目中遇到过这种情况。有一次训练一个图像分类模型,用了 20 层 ReLU。训练到一半,发现大约 30% 的神经元输出恒为 0。检查了一下,是因为学习率设得太大,导致权重更新过猛,很多神经元直接掉进了负半轴。后来我调小了学习率,又加了 Batch Normalization,情况才好转。

2.4 ReLU 的梯度流分析

咱们对比一下梯度流:

激活函数 正半轴梯度 负半轴梯度 梯度流问题
Sigmoid 最大 0.25,饱和区趋近 0 最大 0.25,饱和区趋近 0 梯度消失
ReLU 恒为 1 恒为 0 死亡 ReLU

你看,Sigmoid 是两边都堵死,ReLU 是只开半边门。说白了,ReLU 是用“砍掉一半梯度”的代价,换来了正半轴的畅通无阻。

但问题在于,如果网络初始化不好,或者学习率不合适,大量神经元会掉进负半轴。这时候梯度为 0,整个网络就废了一半。

2.5 核心知识图谱

下面这张图,是我自己总结的激活函数梯度流对比。你可以看到,从 Sigmoid 到 ReLU,再到后来的 Leaky ReLU、ELU、Swish,其实都是在解决同一个问题:如何让梯度在正负半轴都顺畅流动

激活函数梯度流问题演进 Sigmoid 输出范围 (0, 1) 导数最大 0.25 ❌ 梯度消失 深层网络梯度指数衰减 前面层几乎不学习 ReLU 输出 [0, +∞) 正半轴导数恒为 1 ❌ 死亡 ReLU 负半轴梯度恒为 0 神经元一旦死亡无法复活 改进方向 Leaky ReLU ELU Swish / SiLU 目标:正负半轴都有 合理的梯度流动 核心矛盾:梯度消失 vs 神经元死亡 → 需要更平滑的梯度流

2.6 小结与避坑指南

好了,咱们总结一下:

  • Sigmoid:梯度消失严重,深层网络基本不能用。我建议只在二分类输出层使用。
  • ReLU:解决了梯度消失,但引入了死亡 ReLU。使用时要注意学习率设置,最好配合 Batch Normalization。

避坑指南: 我曾经在一个 50 层的 ResNet 里用了 ReLU,结果训练到一半 loss 突然变成常数。排查了半天,发现是某层的所有神经元都死了。后来我把学习率从 0.1 降到 0.01,又加了梯度裁剪,问题才解决。所以,学习率是 ReLU 的命门

你可能会问:那有没有既没有梯度消失,又不会导致神经元死亡的激活函数?有,这就是我们接下来要讲的 Swish 和 SwiGLU。它们的设计思路,说白了就是让梯度在正负半轴都能平滑流动,同时保留 ReLU 的非线性能力。

嗯,数学基础就回顾到这里。下一节我们正式进入 Swish 的世界。


公众号:蓝海资料掘金营,微信deep3321