GELU 是深度学习、神经网络、激活函数、Transformer 和大语言模型中非常常见的一个术语。它用来描述一种比 ReLU 更平滑的非线性激活函数。换句话说,GELU 函数是在回答这样一个问题:神经元计算出一个线性得分后,应该怎样以更柔和的方式决定这个信号通过多少?
如果说 ReLU 函数像一个“硬开关”:正数通过、负数截断;那么 GELU 更像一个“软门控”:输入越大,越倾向于通过;输入越小,越倾向于抑制,但不是简单粗暴地一刀切。因此,GELU 常用于 Transformer、BERT、GPT 类模型、前馈神经网络模块和现代深度学习模型,是理解大模型中激活函数选择的重要概念。
一、基本概念:什么是 GELU 函数
GELU 是 Gaussian Error Linear Unit 的缩写,通常可译为高斯误差线性单元。它是一种激活函数,用于把神经元的线性输入转换成非线性输出。
一个神经元通常先计算:
z = w · x + b
然后通过激活函数得到输出:
a = GELU(z)
其中:
- x 表示输入向量
- w 表示权重向量
- b 表示偏置
- z 表示线性输入
- a 表示经过 GELU 激活后的输出
GELU 的常见定义为:
GELU(x) = x * Φ(x)
其中:
- x 表示输入
Φ(x) 表示标准正态分布的累积分布函数
xΦ(x) 表示把输入 x 乘以一个与 x 大小相关的平滑门控系数
从通俗角度看,GELU 可以理解为:输入越大,越应该保留;输入越小,越应该抑制;中间区域则平滑过渡。
这与 ReLU 的硬截断不同。ReLU 是:
ReLU(x) = max(0, x)
也就是:
x > 0 时,直接输出 x
x ≤ 0 时,直接输出 0
而 GELU 不是简单地把负数全部变成 0,而是根据输入大小进行柔和调整。
二、为什么需要 GELU 函数
GELU 之所以重要,是因为现代 深度学习 模型需要既有非线性表达能力,又有较平滑的训练性质。
ReLU 函数简单高效,但它有明显的硬折点:
ReLU(x) = max(0, x)
这意味着:
- 正数完全通过
- 非正数直接归零
- 在 0 附近存在明显折断
这种设计简单有效,但有时过于粗糙。
GELU 的思路更柔和:不是简单判断输入是否大于 0,而是根据输入大小决定信号通过的程度。
例如:
- 较大的正数大部分保留
- 接近 0 的数部分保留
- 较小的负数大多被抑制
- 轻微负数可能仍保留少量信息
从通俗角度看:
- ReLU:大于 0 就开,小于等于 0 就关
- GELU:根据输入大小,柔和决定开多少
这使 GELU 在许多 Transformer 模型中表现良好。
现代大语言模型中,前馈网络模块通常包含:
线性层 → 激活函数 → 线性层
其中激活函数常常使用 GELU 或其变体。
因此,GELU 是理解 Transformer 内部非线性变换的重要组成部分。
三、GELU 的核心公式
GELU 的理论定义为:
GELU(x) = x * Φ(x)
其中,Φ(x) 是标准正态分布的累积分布函数:
Φ(x) = P(X ≤ x),其中 X ~ 𝒩(0,1)
其中:
X 表示服从标准正态分布的随机变量
𝒩(0,1) 表示均值为 0、方差为 1 的正态分布
Φ(x) 表示随机变量 X 小于或等于 x 的概率
因此,GELU 可以理解为:
GELU(x) = x * P(X ≤ x)
从通俗角度看:GELU 用一个概率值 Φ(x) 作为门控系数,决定输入 x 应该保留多少。
当 x 很大时:
当 x 很小时:
当 x 接近 0 时:
Φ(x) 接近 0.5
GELU(x) 大约保留一半趋势
所以,GELU 不是简单地“负数归零、正数放行”,而是用概率方式对输入进行平滑调节。
这也是 GELU 名称中包含 Gaussian 的原因:它与高斯分布,也就是正态分布有关。
四、GELU 的近似公式
由于标准正态分布的累积分布函数 Φ(x) 计算起来相对复杂,实际工程中常使用近似公式。
常见近似形式为:
GELU(x) ≈ 0.5x (1 + tanh(√(2/π) (x + 0.044715x^3)))
其中:
tanh 表示双曲正切函数
π 表示圆周率
0.044715 是近似公式中的常数
这个公式虽然看起来复杂,但它的作用很简单:用一个更方便计算的平滑函数近似原始 GELU。
还有一种更简单的近似形式:
GELU(x) ≈ x * σ(1.702x)
其中:
σ 表示 Sigmoid 函数
σ(1.702x) 近似模拟 Φ(x)
从通俗角度看:
- 原始 GELU:
x × 正态分布累计概率
- 近似 GELU:用
tanh 或 Sigmoid 近似这个概率门控
在深度学习框架中,用户通常不需要手写这些公式。
例如,在 PyTorch 中可以直接使用:
torch.nn.GELU()
框架会在内部处理具体计算方式。
五、如何直观理解 GELU
GELU 最核心的直觉是:让输入根据自身大小,以平滑概率方式决定通过程度。
可以把 GELU 看成一种“软门控”函数:
- 输入很大 → 门几乎全开 → 基本保留
- 输入接近 0 → 门半开半关 → 部分保留
- 输入很小 → 门几乎关闭 → 基本抑制
这与 ReLU 的差别很明显。
ReLU 是硬门控:
GELU 是软门控:
例如,从直觉上看:
x = 2 时,GELU(x) 接近 2
x = 0 时,GELU(x) = 0
x = -2 时,GELU(x) 接近 0,但不是通过硬规则截断
此外,GELU 在轻微负数区域可能输出小的负值。
这说明它不像 ReLU 那样把所有负数都强制变成 0,而是允许部分负向信息以较弱形式存在。
从通俗角度看:GELU 比 ReLU 更柔和,也更连续地控制信息流。
这有助于模型在训练过程中获得更平滑的梯度变化。
六、GELU 与 ReLU 的区别
GELU 和 ReLU 都是隐藏层常用激活函数,但它们的行为不同。
1、ReLU 是硬截断
ReLU 定义为:
ReLU(x) = max(0, x)
它的特点是:
- 正数直接通过
- 负数全部变为 0
- 计算简单
- 可能出现死亡 ReLU 问题
从通俗角度看:ReLU 是一个简单明确的开关。
2、GELU 是平滑门控
GELU 定义为:
GELU(x) = x * Φ(x)
它的特点是:
- 正数大多通过
- 负数大多被抑制
- 过渡更加平滑
- 不像 ReLU 那样简单一刀切
从通俗角度看:GELU 是一个根据输入强弱逐渐开合的软开关。
3、训练表现上的差异
ReLU 的优势是简单、高效、广泛适用。
GELU 的优势是平滑、柔和,并且在 Transformer 等模型中常有较好表现。
可以简单理解为:
- ReLU:适合许多传统深度网络,尤其是 CNN 和普通 MLP
- GELU:常见于 Transformer、BERT、GPT 等现代架构
不过,GELU 并不总是绝对优于 ReLU。
在不同任务、模型规模、数据条件和训练设置下,二者表现可能不同。
从实践角度看:ReLU 是经典默认选择,GELU 是现代 Transformer 模型中的常见选择。
GELU 在 Transformer 中非常常见,尤其是在前馈网络模块中。
一个 Transformer 层通常包括:
注意力模块 → 前馈网络模块
其中前馈网络模块常见形式为:
FFN(x) = W₂ * f(W₁ * x + b₁) + b₂
其中:
x 表示输入表示
W₁、W₂ 表示权重矩阵
b₁、b₂ 表示偏置
f 表示激活函数
在许多 Transformer 模型中,这里的 f 就可以是 GELU。
从通俗角度看,Transformer 中的前馈网络模块会对每个 token 的表示进行非线性加工:
token 表示 → 线性变换 → GELU 激活 → 线性变换 → 更新后的表示
GELU 在这里的作用是:为 token 表示的变换过程引入平滑非线性。
在 BERT、GPT 等模型中,GELU 曾被广泛采用。
后来一些模型也会使用 SwiGLU、GeGLU、SiLU 等变体,但 GELU 仍然是理解 Transformer 激活函数的重要基础。
从通俗角度看:注意力机制负责让 token 之间交换信息,GELU 所在的前馈网络负责对每个 token 的内部表示进行非线性加工。
八、GELU 的优势、局限与使用注意事项
1、GELU 的主要优势
GELU 的主要优势是平滑。
它不像 ReLU 那样在 0 点硬折断,而是通过概率门控方式平滑调整输入。
其次,GELU 对轻微负值更宽容。
它不会简单地把所有负数都截断为 0,而是允许一部分负向信息以较小形式保留。
再次,GELU 在 Transformer 和大语言模型中非常常见。
对于理解现代模型结构,它是一个非常重要的激活函数。
从通俗角度看,GELU 的优势在于:它不是粗暴地关闭信号,而是根据输入强弱柔和地控制信号通过程度。
2、GELU 的主要局限
GELU 也有局限。
首先,它比 ReLU 计算更复杂。
ReLU 只需要一个 max 操作,而 GELU 涉及正态分布函数或近似函数。
其次,GELU 的解释不如 ReLU 直观。
ReLU 的规则非常清楚:负数归零、正数保留;GELU 则需要理解概率门控和平滑近似。
再次,GELU 并不保证在所有任务中都比 ReLU 好。
对于一些简单网络或小规模任务,ReLU 可能已经足够。
此外,在实际工程中,激活函数只是影响模型表现的因素之一。
模型结构、数据规模、学习率、归一化、初始化和优化器同样重要。
3、使用 GELU 时需要注意的问题
使用 GELU 时,可以注意以下几点:
- Transformer 和语言模型中常见 GELU
- 普通 MLP 中也可以尝试 GELU
- 如果追求极致计算效率,ReLU 可能更简单
- GELU 适合需要平滑非线性的模型
- 不要认为 GELU 一定优于所有激活函数
- 不同框架中 GELU 可能支持 exact 或 approximate 模式
从实践角度看,GELU 是现代深度学习中非常重要的激活函数,尤其适合与 Transformer 架构一起理解。
九、Python 示例
下面给出几个简单示例,用来帮助理解 GELU 的计算和使用。
示例 1:使用 PyTorch 计算 GELU
import torch # PyTorch 深度学习库
import torch.nn as nn # 神经网络模块
# 输入张量(5个实数)
x = torch.tensor([-3.0, -1.0, 0.0, 1.0, 3.0])
# GELU(Gaussian Error Linear Unit)激活函数,更平滑的ReLU变体
gelu = nn.GELU()
# 应用 GELU 激活函数
y = gelu(x)
print("输入:", x)
print("GELU 输出:", y) # 输出近似:负值被平滑映射到接近0,正值近似线性
这个例子可以观察:
- 较大正数基本保留
- 0 附近平滑过渡
- 负数大多被抑制,但不是像 ReLU 那样简单截断
示例 2:对比 ReLU 与 GELU
import torch # PyTorch 深度学习框架
import torch.nn as nn # 神经网络模块
# 测试用的输入张量(包含负数、零、正数)
x = torch.tensor([-3.0, -1.0, 0.0, 1.0, 3.0])
# ReLU 激活函数(负值置零,正值不变)
relu = nn.ReLU()
# GELU 激活函数(高斯误差线性单元,平滑的非线性)
gelu = nn.GELU()
print("输入:", x)
print("ReLU 输出:", relu(x)) # 输出:[0, 0, 0, 1, 3]
print("GELU 输出:", gelu(x)) # 负值有较小的非零输出,正值近似线性
这个例子中:
- ReLU 会把所有负数变成 0
- GELU 会对输入进行平滑调整
- GELU 的负数部分通常不是简单清零
从输出可以直观看到:
示例 3:在前馈神经网络中使用 GELU
import torch # PyTorch框架
import torch.nn as nn # 神经网络模块
# 定义简单前馈神经网络:输入4维 → GELU激活 → 输出3维(类别logits)
model = nn.Sequential(
nn.Linear(4, 16), # 全连接层:4→16
nn.GELU(), # GELU激活函数
nn.Linear(16, 3) # 输出层:16→3
)
# 生成一批随机输入:5个样本,每个样本4个特征
x = torch.randn(5, 4)
# 前向传播,得到未归一化的类别分数
logits = model(x)
print("输出 logits 形状:", logits.shape) # torch.Size([5, 3])
print(logits)
这个例子中:
nn.Linear(4, 16) 进行线性变换
nn.GELU() 引入平滑非线性
nn.Linear(16, 3) 输出 3 个类别的 logits
如果用于多分类任务,通常会配合 nn.CrossEntropyLoss()。
示例 4:手动实现 GELU 近似公式
import torch # PyTorch 张量计算
import math # 数学常量(sqrt(2/π))
# GELU 的近似实现(基于 tanh 展开,常用于高效计算)
def gelu_approx(x):
# 公式:0.5 * x * (1 + tanh(sqrt(2/π) * (x + 0.044715 * x^3)))
return 0.5 * x * (
1 + torch.tanh(
math.sqrt(2 / math.pi) * (x + 0.044715 * x ** 3)
)
)
# 测试输入:负数、零、正数
x = torch.tensor([-3.0, -1.0, 0.0, 1.0, 3.0])
# 计算近似 GELU
y = gelu_approx(x)
print("输入:", x)
print("近似 GELU 输出:", y)
这个例子对应近似公式:
GELU(x) ≈ 0.5x (1 + tanh(√(2/π) (x + 0.044715x^3)))
在实际使用中,一般不需要手动写这个函数,直接使用深度学习框架内置的 GELU 即可。
📘 小结
GELU 函数是一种常用于现代深度学习模型的激活函数,定义为 GELU(x)=xΦ(x),其中 Φ(x) 是标准正态分布的累积分布函数。它不像 ReLU 那样把负数简单截断,而是根据输入大小进行平滑门控:输入越大,越倾向于保留;输入越小,越倾向于抑制。GELU 常用于 Transformer、BERT、GPT 等模型中的前馈网络模块。对初学者而言,可以把 GELU 理解为:一种比 ReLU 更柔和的“软开关”激活函数。对于开发者来说,在 云栈社区 交流这些技术细节,往往能获得更多实践上的启发。
