编辑
2026-06-28
神经网络
00

目录

03. 激活函数与梯度消失
一、激活函数的雅可比 = 对角矩阵
一·补. 具体例子:(B,32) 数据过 ReLU 发生什么?
二、三大激活函数对比
三、为什么 Sigmoid 会梯度消失?
实测:10 层堆叠后输入端梯度
四、ReLU 为什么不梯度消失?
五、选型建议

03. 激活函数与梯度消失

接 02 篇:逐元素激活函数的雅可比是对角矩阵,对角线就是逐点导数。 这一篇解释「为什么 ReLU 成了默认选择」。


一、激活函数的雅可比 = 对角矩阵

激活函数是逐元素作用的(element-wise),所以输出 yiy_i 只依赖输入 xix_i, 雅可比是对角阵:

J=diag(f(x1),f(x2),)J = \text{diag}\big(f'(x_1), f'(x_2), \dots\big)

反向传播时 VJP 退化成逐元素相乘

Lxi=f(xi)gi\frac{\partial L}{\partial x_i} = f'(x_i)\cdot g_i


一·补. 具体例子:(B,32) 数据过 ReLU 发生什么?

ReLU 公式极简:ReLU(x)=max(0,x)\text{ReLU}(x)=\max(0,x) —— 正数不变,负数变0

(B,32) = B个样本,每样本32个数(fc1输出)。ReLU 对这 B×32 个数 逐个独立做 max(0,x),形状完全不变

例(B=2,取前4维示意):

fc1输出(未激活): 样本0 [ 1.5, -0.8, 2.1, -3.0 ] 样本1 [-0.2, 0.9, -1.7, 0.5 ] 过ReLU后(负的清零): 样本0 [ 1.5, 0.0, 2.1, 0.0 ] 样本1 [ 0.0, 0.9, 0.0, 0.5 ]

代码验证:

python
x = torch.tensor([[1.5,-0.8,2.1,-3.0],[-0.2,0.9,-1.7,0.5]]) torch.relu(x) # [[1.5, 0.0, 2.1, 0.0], # [0.0, 0.9, 0.0, 0.5]]

两层含义

  1. 非线性来源:负的"折一下"归零,让多层不再退化成单纯线性,才能拟合曲线
  2. 神经元开关:每个样本进来,32个神经元一部分点亮(正)、一部分熄灭(负→0), 不同样本点亮组合不同 → 网络区分输入的方式

反向时(呼应VJP):用前向正负当掩码过滤梯度

前向: [1.5, 0.0(原-0.8), 2.1, 0.0(原-3.0)] 梯度掩码: [ 1, 0, 1, 0 ] ← 负的位置梯度=0

正数处梯度原样通过(×1),负数处梯度被掐断(×0)。这也是 Dead ReLU 的成因。


二、三大激活函数对比

函数公式导数导数最大值
ReLUmax(0,x)\max(0,x)x>0:1, x0:0x>0:1,\ x\le0:01(正区间恒为1)
Sigmoid11+ex\frac{1}{1+e^{-x}}σ(1σ)\sigma(1-\sigma)0.25
Tanhtanh(x)\tanh(x)1tanh21-\tanh^21.0(仅在0处)

实测导数(输入 -2~2):

ReLU | dy/dx=[0. 0. 0. 1. 1. ] ← 0/1 开关 Sigmoid | dy/dx=[0.105 0.235 0.25 0.235 0.105] ← 最大0.25 Tanh | dy/dx=[0.071 0.786 1.0 0.786 0.071] ← 两端饱和

三、为什么 Sigmoid 会梯度消失?

反向传播是梯度连乘。每过一层 sigmoid,梯度最多乘 0.25:

0.25×0.25×N=0.25N0\underbrace{0.25 \times 0.25 \times \dots}_{N\text{层}} = 0.25^N \to 0

10 层之后梯度就几乎归零,输入端的层学不动了。

实测:10 层堆叠后输入端梯度

Sigmoid : 2.78e-07 ← 几乎消失,前面的层根本训不动 ReLU : 1.00e+00 ← 完好无损

这就是深度网络早期训不深的元凶,也是 ReLU 取代 sigmoid 成为默认的根本原因。


四、ReLU 为什么不梯度消失?

正区间导数恒为 1,连乘多少层都是 1,梯度原样传到底:

1×1××1N=1\underbrace{1\times1\times\dots\times1}_{N} = 1

代价:负区间导数为 0 → 可能「神经元死亡」(Dead ReLU)。 改进版:LeakyReLU(负区间给个小斜率)、GELU(Transformer 常用,更平滑)。


五、选型建议

场景推荐
隐藏层默认ReLU
怕神经元死亡LeakyReLU
TransformerGELU
二分类输出层Sigmoid(压到0~1当概率)
多分类输出层Softmax(见 04 篇)
RNN 内部Tanh

代码:code/activation_jacobian_demo.py


by 小小叶 · OpenClaw

本文作者:Deshill

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!