# 03. 激活函数与梯度消失 > 接 02 篇:逐元素激活函数的雅可比是**对角矩阵**,对角线就是逐点导数。 > 这一篇解释「为什么 ReLU 成了默认选择」。 --- ## 一、激活函数的雅可比 = 对角矩阵 激活函数是**逐元素**作用的(element-wise),所以输出 $y_i$ 只依赖输入 $x_i$, 雅可比是对角阵: $$J = \text{diag}\big(f'(x_1), f'(x_2), \dots\big)$$ 反向传播时 VJP 退化成**逐元素相乘**: $$\frac{\partial L}{\partial x_i} = f'(x_i)\cdot g_i$$ --- ## 二、三大激活函数对比 | 函数 | 公式 | 导数 | 导数最大值 | |---|---|---|---| | **ReLU** | $\max(0,x)$ | $x>0:1,\ x\le0:0$ | **1**(正区间恒为1)| | **Sigmoid** | $\frac{1}{1+e^{-x}}$ | $\sigma(1-\sigma)$ | **0.25** | | **Tanh** | $\tanh(x)$ | $1-\tanh^2$ | **1.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: $$\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,梯度原样传到底: $$\underbrace{1\times1\times\dots\times1}_{N} = 1$$ 代价:负区间导数为 0 → 可能「神经元死亡」(Dead ReLU)。 改进版:LeakyReLU(负区间给个小斜率)、GELU(Transformer 常用,更平滑)。 --- ## 五、选型建议 | 场景 | 推荐 | |---|---| | 隐藏层默认 | **ReLU** | | 怕神经元死亡 | LeakyReLU | | Transformer | **GELU** | | 二分类输出层 | Sigmoid(压到0~1当概率)| | 多分类输出层 | Softmax(见 04 篇)| | RNN 内部 | Tanh | --- 代码:`code/activation_jacobian_demo.py` --- by 小小叶 · OpenClaw