ReLU (Rectified Linear Unit)
ReLU(修正线性单元)输出 max(0, x),保留正输入并将负输入置零。涵盖其梯度、ReLU 神经元死亡问题、变体和 PyTorch 代码。
线性整流单元(ReLU)是激活函数 f(x) = max(0, x):正输入原样通过,其他输入都输出零。通过一次简单比较,ReLU 就能以极低的计算成本为神经网络(NN)提供学习曲线模式所需的非线性。Vinod Nair 和 Geoffrey Hinton 于 2010 年采用 ReLU;2012 年,基于 ReLU 的卷积神经网络(CNN) AlexNet 赢得 ImageNet挑战赛,此后 ReLU 成为深度学习隐藏层的默认激活函数。如今,SiLU 和 GELU 等新型激活函数仍以 ReLU 为基准进行比较。
ReLU 的工作原理#
ReLU 对正输入的导数为 1,对负输入的导数为 0。在输入恰好为零时,导数未定义;PyTorch 等框架会将其设为 0。这两个值解释了 ReLU 的主要特性:
- 计算成本低:前向传播只需与零比较,反向传播只需应用掩码;不像 sigmoid 或 tanh 那样需要计算指数。
- 正输入不会饱和:梯度值恰好为 1,会原样通过每个激活单元,因此误差信号在经过许多层向后传播时不会缩小,这可以缓解饱和函数带来的梯度消失问题。
- 激活稀疏:每个负输入都会变成精确的零,因此任意时刻只有一部分层处于激活状态。对于随机初始化的权重,给定一个输入时,约有一半的层单元会输出零。
- 分段线性:由 ReLU 构成的网络会计算输入的分段线性函数,其中包含许多线性区域,这些区域在单元开启或关闭的位置相连。
下面的 PyTorch示例会应用 nn.ReLU,并使用 autograd 计算这些相同位置处的梯度:
import torch
from torch import nn
relu = nn.ReLU()
# Inputs on both sides of zero, tracked so PyTorch can compute gradients
x = torch.tensor([-2.0, -0.5, 0.0, 0.5, 2.0], requires_grad=True)
y = relu(x)
# Backpropagate a gradient of 1 from each output to its input
y.sum().backward()
print(f"Output: {y.tolist()}")
print(f"Gradient: {x.grad.tolist()}")代码会输出 [0.0, 0.0, 0.0, 0.5, 2.0] 和梯度 [0.0, 0.0, 0.0, 1.0, 1.0]。正输入会原样通过,梯度也保持不变;负输入和零输入都不会得到任何梯度,这既是 ReLU 激活稀疏的原因,也是它的主要缺陷。
ReLU 神经元死亡问题#
如果一个 ReLU 单元在所有训练数据中的输入都为负数,它就会输出零并且得不到梯度,因此其权重不再变化,该单元实际上就失效了。较大的权重更新往往会导致单元失效,而过高的学习率通常是其原因之一,因为它会将偏置推得很低。少数失效单元影响不大,但调参不当的一次训练可能导致某一层中大量单元失效。He 初始化会为 ReLU 层缩放初始权重;配合适中的学习率和批归一化,可以让大多数单元保持激活。带泄漏的变体则始终保留非零梯度,从而消除这一问题。
ReLU 的变体#
- Leaky ReLU:将负输入乘以一个较小的固定斜率(通常为 0.01),使未激活单元仍能获得梯度。
- PReLU:在训练期间学习负输入的斜率。Kaiming He 及其同事于 2015 年在提出 He 初始化的同一篇论文中介绍了这种方法。
- ReLU6:将输出限制在 6 以内,即 min(max(0, x), 6),使激活值保持在低精度算术能够良好表示的范围内。MobileNetV1 和 MobileNetV2 都使用了它。
- ELU:将负数区域替换为平滑的指数曲线,并在 −1 处饱和,从而使平均激活值更接近零。
- SiLU和GELU:平滑曲线,分别为 x · σ(x) 和 x · Φ(x)。对于较大的输入,它们的行为类似 ReLU;但它们会保留较小的负值,并且在零点处没有折角。它们每个元素的计算成本更高;GELU 论文报告称,在其测试的所有视觉、语言和语音任务中,GELU 的表现都优于 ReLU。
ReLU 与 Sigmoid 和 Tanh 的比较#
在 ReLU 出现之前,隐藏层使用 sigmoid 或 tanh。两者都会饱和:输入绝对值很大时,曲线会变平,导数也趋近于零;即使在最陡处,sigmoid 的导数也不会超过 0.25。在许多层中不断相乘会让早期层的梯度变得极小。在AlexNet 论文中,使用 ReLU 的四层 CNN 在 CIFAR-10上达到 25% 训练错误率的速度,比使用 tanh 单元的相同网络快六倍。当有限取值范围本身很有用时,sigmoid 和 tanh 仍然适用:sigmoid 用于输出层表示概率,也用于循环单元中的门控;tanh 则用于循环网络的隐藏状态。
现代模型中的 ReLU#
ResNet及其时代的大多数 CNN 都在整个网络中使用 ReLU,2017 年原始 Transformer也在前馈层中使用了 ReLU。许多较新的模型改用了更平滑的函数:BERT和视觉 Transformer使用 GELU,许多当前的大语言模型则使用 SwiGLU;而在速度和硬件支持最重要的场景中,ReLU 仍然很常见。YOLO26默认在 Conv 模块中使用 SiLU;在模型 YAML中添加一行 activation: nn.ReLU(),就能在训练前将所有 Conv 模块中的 SiLU 替换为 ReLU。这适用于 AMD Zynq UltraScale+ DPU 等原生支持 ReLU、但不支持 SiLU 的加速器。在 PyTorch 中,nn.ReLU(inplace=True) 会将结果写入输入张量,从而省去单独输出张量占用的内存。










