跳至内容

GELU 激活函数:公式、直觉与在深度学习中的应用

GELU 是一种平滑、具有概率特性的激活函数,在深度学习架构中优于 ReLU 等更简单的替代方案,并已成为诸如 BERT 和 GPT 等 Transformer 模型的默认选择。
更新 2026年5月4日  · 8分钟

激活函数决定神经网络中哪些信号能够通过、哪些被阻断。若选择不当,模型要么学习过慢,要么无法泛化。多年来,ReLU 因其速度快且对大多数任务“足够好”而成为合理的默认选择。

GELU(Gaussian Error Linear Unit,高斯误差线性单元)改变了这一点。它如今是一些最强大模型背后的激活函数,包括 BERT 和 GPT。

本文将介绍 GELU 的直觉、其公式、与其他激活函数的比较,以及在实践中应如何使用。

如果您对机器学习中的激活函数还很陌生,请先阅读我们的ReLU(修正线性单元)新手指南博文。

什么是 GELU 激活函数?

GELU(高斯误差线性单元)是一种激活函数,它以平滑且具有概率性的方式,根据输入幅度对其加权。

大多数激活函数会做出“通过或阻断”的二元决定。例如,ReLU 会将所有负值置零,而对其他值不作改变。GELU 则不同。它没有硬阈值,而是根据输入的大小平滑缩放,这意味着即使是很小的负值也能对输出有所贡献。

与 ReLU 的不同在于,GELU 在各处都平滑且连续。在零点没有尖角,也不存在突变。这种平滑性在训练中会起作用,因为它为优化器提供了更干净的梯度信息。

GELU 的直觉

可以把 GELU 想象成一种不会一视同仁对待输入的滤波器。

ReLU 很“生硬”——任何负值都会被置零,次次如此。相反,GELU 会问“这个输入值有多可能是有用的?”明显较大且为正的值几乎原样通过;较小或为负的值被缩小,而不是完全切断。

结果就是一条平滑曲线,它抑制不那么相关的信号,但不将其彻底丢弃。

想象您在审阅一摞求职申请。严格的筛选会毫无例外地剔除没有学位的人。更聪明的筛选会考虑那些“差一点”的候选人——也许他们有能弥补的相关经验。GELU 就像更聪明的筛选。它不做死板的切割,而是根据输入的幅度来衡量,并决定放行多少。

这种渐进、带概率的缩放使 GELU 与众不同。没有突变、没有“死亡神经元”——而是对每个输入值做出平滑的“通过或抑制”决策。

GELU 公式

精确的 GELU 公式建立在高斯累积分布函数(CDF)之上,写作:

Gaussian cumulative distribution function

Gaussian cumulative distribution function

其中,x 是输入值,Φ(x) 表示从标准正态分布中抽取的随机变量小于等于 x 的概率。通俗地说,Φ(x) 告诉您输入值有多“正常”或多符合预期——而 GELU 就用这个概率来缩放输入。

输入越大,Φ(x) 越接近 1,意味着输入几乎原样通过;输入越小,Φ(x) 越接近 0,意味着输入会被抑制。

实践中的近似

精确公式的问题在于计算 Φ(x) 成本较高。它涉及误差函数,而误差函数没有简单的闭式形式,在大规模计算时较慢。

深度学习框架改用如下近似:

GELU approximation formula

GELU approximation formula

该近似使用 tanh,其计算快速,且在现代硬件上支持良好。对于实践中关心的输入范围,该近似与精确公式的结果几乎一致,这也是 PyTorch 和 TensorFlow 等框架默认采用它的原因。

当然,您不必背下任何一个公式。但了解这个近似的存在及其原因,有助于理解在代码中调用 GELU 时实际发生了什么。

GELU 与其他激活函数的比较

每种激活函数处理输入的方式不同,而这些差异会体现在模型训练效果上。

在文字阐述之前,先看一眼它们在视觉上的差异:

GELU versus other activation functions graph

GELU 与其他激活函数的对比图

Sigmoid

Sigmoid 将所有输入压缩到 0 到 1 之间。它是平滑的,但存在众所周知的问题:梯度消失。对于非常大或非常小的输入,梯度接近于零,导致更深层停止学习。GELU 没有这个问题,因为它在更宽的输入范围内保持有意义的梯度。

Tanh

Tanh 与 Sigmoid 类似,但以零为中心,输出范围为 -1 到 1。它比 Sigmoid 更好地处理负输入,但在极端值处仍会出现梯度消失。GELU 产生更平滑的输出曲线,有助于深层网络中的梯度流动。

ReLU

ReLU 简单且快速:正值原样通过,负值被置零。零点处的硬性切断会导致“死亡神经元”问题——长期接收负输入的神经元将完全停止更新。GELU 通过缩放负输入而非切断来避免这一点。

Leaky ReLU

Leaky ReLU 通过允许一小部分负输入通过来修复“死亡神经元”问题。它比 ReLU 更进一步,但零点处的过渡仍然是突变的。GELU 整体产生更平滑的曲线,在更深的架构中往往效果更好,因为梯度质量尤为重要。

总而言之,以下是这五种激活函数之间的差异:

GELU versus other activation functions table

GELU 与其他激活函数的对比表

为何在 Transformer 中使用 GELU

Transformer 也是深度神经网络。而网络越深,梯度质量就越重要。

像 BERT 和 GPT 这样的模型将数十层堆叠在一起。在这样的深度下,梯度流的小问题会被放大。如果激活函数在某些区域产生不稳定或近零的梯度,网络的早期层在训练中几乎不会更新,也就学不到什么。

GELU 通过在更宽的输入范围内保持梯度平滑且非零来避免这一点。它不像 ReLU 那样有零边界的切断,因此优化器在每一层都能获得更干净的信号,而不仅是靠近输出的层。

另外还有一个原因使 GELU 非常契合 Transformer 架构。

Transformer 通过注意力机制处理输入,会产生范围广泛的激活值——既有正值也有负值。与存在突变的函数相比,平滑的激活函数能更好地处理这种范围。

在最初的 BERT 论文中,作者选择了 GELU 而非 ReLU,并在基准测试中报告了更好的结果。GPT 也沿用了同样的选择。自那以后,GELU 成为大多数基于 Transformer 的架构中的默认激活函数,并非因为它新,而是因为它在这些模型所处的规模下表现更佳。

GELU 的实践

在模型中使用 GELU 与使用其他激活函数一样简单。PyTorch 和 TensorFlow 都内置支持。

PyTorch

在 PyTorch 中,您可以将 GELU 作为独立模块使用,或内联到模型定义中。以下是一个使用 GELU 的简单前馈模块:

import torch
import torch.nn as nn

class FeedForwardBlock(nn.Module):
    def __init__(self, input_dim, hidden_dim):
        super().__init__()
        self.fc1 = nn.Linear(input_dim, hidden_dim)
        self.act = nn.GELU()
        self.fc2 = nn.Linear(hidden_dim, input_dim)

    def forward(self, x):
        return self.fc2(self.act(self.fc1(x)))

block = FeedForwardBlock(input_dim=512, hidden_dim=2048)
x = torch.randn(8, 512)
output = block(x)

nn.GELU() 位于两个线性层之间,这正是您在 Transformer 的前馈子层中会看到的位置。激活在第一次投影之后、第二次投影之前运行。

TensorFlow

在 TensorFlow 中,可通过 Keras API 使用 GELU:

import tensorflow as tf
from tensorflow import keras

model = keras.Sequential([
    keras.layers.Dense(2048, input_shape=(512,)),
    keras.layers.Activation("gelu"),
    keras.layers.Dense(512)
])

x = tf.random.normal((8, 512))
output = model(x)

您也可以将其作为字符串参数直接传给 Dense 层:

keras.layers.Dense(2048, activation="gelu")

两种方式的结果相同。

GELU 在网络中的位置

GELU 的位置与其他激活函数相同——紧跟在线性变换之后、下一层之前。在 Transformer 架构中,这意味着位于前馈子层内、两次全连接投影之间。在其他深层网络中,将其置于线性或卷积层之后,让它在向前传递前对输出进行缩放。

GELU 的优势

如果您读到这里,已经了解了与其他激活函数相比,GELU 的主要卖点。这里简要回顾:

  • 平滑的激活:GELU 产生连续、可微的曲线,没有突变,为优化器在每一步提供更干净的信息。
  • 更好的梯度流:GELU 不会将负输入置零,因此梯度仍可通过接收负值的神经元传播,降低训练过程中神经元“死亡”的风险。
  • 更适合深度模型的性能:在诸如 Transformer 等深层架构中,更平滑的梯度带来的累积效应,往往能转化为较之简单激活函数更好的训练结果。

GELU 的局限

GELU 并非在任何场景下都是最佳选择。以下是您需要注意的几个局限:

  • 相比 ReLU 计算更昂贵:GELU 涉及误差函数或基于 tanh 的近似,两者成本都高于 ReLU 的简单阈值操作。在包含大量层的大模型中,这些开销会累积。

  • 不够直观:像 ReLU 这样函数的直觉很清晰——正值通过、负值不通过。GELU 的概率性缩放更难解释。

  • 并非总是必要:对于浅层网络或更简单的任务,GELU 往往没有实质优势。ReLU 或 Leaky ReLU 通常能以更低的计算成本取得相近表现。

总之,如果您在构建 Transformer 或其它深层架构,GELU 是一个稳妥的默认选择。对于其他情形,建议在采用前先做基准测试。

结语

GELU 不是普适升级,也不是可以替代 ReLU 的“一刀切”方案。它是一种在特定场景下值得采用的深思熟虑的设计选择——如深度网络与 Transformer 模型。

如果您在使用 BERT、GPT 或任何基于 Transformer 的模型,无论是否意识到,您已经在使用 GELU。现在您知道它为何存在了。

对于其他情况,激活函数的选择取决于权衡。没有任何一种函数总能获胜;了解各自的特点,能让您基于信心而非习惯做出选择。

如果您仍然觉得不同激活函数之间的差异令人困惑,欢迎报名我们的机器学习工程师学习路径,为机器学习与 MLOps 的职业发展做好准备。

FAQs

什么是 GELU 激活函数?

GELU(Gaussian Error Linear Unit,高斯误差线性单元)是神经网络中的一种激活函数。与 ReLU 不同,GELU 以概率性方式根据输入的幅度平滑地进行缩放。这使其更适合梯度质量更重要的深层架构。

GELU 与 ReLU 有何不同?

ReLU 以零为硬阈值将所有负输入置零,这可能导致神经元停止学习——即所谓“死亡神经元”问题。GELU 则通过逐步缩小负输入而非切断来避免这一点。这样能带来更平滑的梯度流,并在深层网络中表现更好。

何时应优先使用 GELU 而非其他激活函数?

GELU 最适用于深层架构,尤其是基于 Transformer 的模型,如 BERT 和 GPT。对于浅层网络或更简单的任务,计算开销很少能证明从 ReLU 切换过来的合理性。以 ReLU 作为基准开始,之后再进行测试对比。

精确的 GELU 公式与其近似有何区别?

精确的 GELU 公式使用高斯累积分布函数,需要计算误差函数——这一操作在大规模情况下较慢。近似形式则以 tanh 替代,它是一种更快且在现代硬件上支持良好的表达式。在实践中,两者的结果几乎一致,这也是大多数框架默认使用近似形式的原因。

GELU 能在 PyTorch 和 TensorFlow 中使用吗?

是的,这两个框架都支持 GELU。在 PyTorch 中,您可以在模型定义中使用 nn.GELU() 模块。在 TensorFlow 中,您可以将 "gelu" 作为字符串传入任一层的 activation 参数,或使用 keras.layers.Activation("gelu")

主题

与 DataCamp 一起学习

Courses

Dimensionality Reduction in Python

4小时
36.3K
Understand the concept of reducing dimensionality in your data, and master the techniques to do so in Python.
查看详情Right Arrow
开始课程
查看更多Right Arrow