Skip to content

激活函数

没有激活函数,多层神经网络等价于单层线性变换。激活函数提供非线性,让网络能拟合任意复杂函数。

无激活: W2(W1x)=Weqx——还是线性的!\text{无激活: } W_2(W_1x) = W_{\text{eq}}x \quad \text{——还是线性的!}

Sigmoid 曾经是标准选择,但有两个致命问题:

  1. 梯度消失:当 ∣x∣>3|x| > 3 时,梯度 σ′(x)<0.01\sigma'(x) < 0.01,深层网络几乎无法学习
  2. 非零中心:输出恒为正,导致梯度更新锯齿形震荡
import torch
import torch.nn.functional as F
x = torch.tensor([5.0], requires_grad=True)
y = torch.sigmoid(x)
y.backward()
print(f"Sigmoid'(5.0) = {x.grad.item():.6f}") # ≈ 0.0066
x2 = torch.tensor([5.0], requires_grad=True)
y2 = F.relu(x2)
y2.backward()
print(f"ReLU'(5.0) = {x2.grad.item()}") # 1.0

ReLU 在 x<0x < 0 时输出和梯度都为 0。如果学习率太大,可能导致神经元永久”死亡”:

# 模拟死亡神经元
x = torch.randn(1000, 10)
w = torch.randn(10, 10) * -10 # 负权重导致输出恒为负
out = F.relu(x @ w)
dead_ratio = (out.sum(dim=0) == 0).float().mean()
print(f"死亡神经元比例: {dead_ratio:.1%}")

GELU 是 Transformer 的标准选择。它给负值一个非零输出,解决了 ReLU 的死亡问题:

GELU(x)=x⋅Φ(x)=x⋅12[1+erf(x2)]\text{GELU}(x) = x \cdot \Phi(x) = x \cdot \frac{1}{2}\left[1 + \text{erf}\left(\frac{x}{\sqrt{2}}\right)\right]

近似公式(GPT-2 使用):

GELU(x)≈0.5x(1+tanh⁡[2π(x+0.044715x3)])\text{GELU}(x) \approx 0.5x\left(1 + \tanh\left[\sqrt{\frac{2}{\pi}}(x + 0.044715x^3)\right]\right)

SwiGLU 是 Llama 使用的激活函数,在 GELU 基础上进一步改进:

SwiGLU(x)=(xW1⊙SiLU(xW2))W3\text{SwiGLU}(x) = (xW_1 \odot \text{SiLU}(xW_2))W_3

其中 SiLU(x)=x⋅σ(x)\text{SiLU}(x) = x \cdot \sigma(x),也称为 Swish。

场景推荐原因
CNN 隐藏层ReLU简单高效
TransformerGELU平滑、性能好
大模型 (Llama等)SwiGLU最新最优
二分类输出Sigmoid输出概率
多分类输出Softmax概率分布