![[activations] pytorch-1.11+ Tanh Gelu Approximation](https://www.chat-gpts.plus/wp-content/uploads/2026/07/15397-f170e494.jpg)
[activations] pytorch-1.11+ Tanh Gelu Approximation
快速结论:该问题涉及在 HuggingFace Transformers 中,当 PyTorch 版本 ≥ 1.11 时,是否可以用 PyTorch 内置的 F.gelu(x, approximate="tanh") 替代 Transformers 自定义的 gelu_new 函数。当前尚未给出最终解决方案,但已有实验结果表明两种实现在数值上不完全一致(CPU 上约 99.1% 的随机张量通过 atol/rtol=1e-6 检查),提示直接替换可能影响模型数值输出。
问题场景
用户在 HuggingFace Transformers 库中使用 gelu_new(即 ACT2FN["gelu_new"])激活函数时,发现 PyTorch 1.11+ 已内置了 Tanh GELU 近似实现。用户希望在 Transformers 中检测到 PyTorch ≥ 1.11 时,自动替换为 PyTorch 的 F.gelu(x, approximate="tanh") 以获得性能提升。
报错原文
该 Issue 并非报告报错,而是功能请求。但相关代码位置如下:
# Transformers 中的 gelu_new 实现(src/transformers/activations.py)
def gelu_new(x):
"""Implementation of the GELU activation function currently in Google BERT repo (identical to OpenAI GPT)."""
return 0.5 * x * (1.0 + torch.tanh(math.sqrt(2.0 / math.pi) * (x + 0.044715 * torch.pow(x, 3.0))))
原因分析
可能原因:PyTorch 1.11+ 中通过 F.gelu(x, approximate="tanh") 提供了与 Transformers 的 gelu_new 类似的数学表达式(都是 Tanh-GELU 近似),但两者在数值计算路径、精度、硬件加速(SIMD / CUDA kernel)上可能不一致。贡献者 @jaketae 的实验表明,CPU 上两个函数的输出在 1000 次随机测试中,仅有 99.1% 通过了 torch.allclose(rtol=1e-6) 检查,GPU 上为 99.7%;而精确相等的比例在 CPU 上仅为 21.3%。因此直接替换可能破坏 Transformers 对数值向后兼容性的严格要求。
环境排查
- PyTorch 版本:需 ≥ 1.11 才能使用
F.gelu(..., approximate="tanh")。当前 Issue 讨论时,PyTorch 1.11 刚发布但未包含该功能,需使用 nightly 版本。 - Transformers 版本:任意版本,但
gelu_new函数位于src/transformers/activations.py。 - 硬件:CPU 和 GPU 均可测试;实验表明 GPU 上数值一致性略好于 CPU。
解决步骤
注意:该 Issue 在关闭时仍为 WIP 状态,以下步骤基于讨论中提出的可行性验证,并非最终合入方案。可优先尝试:
- 确认 PyTorch 版本:运行
import torch; print(torch.__version__)确保 ≥ 1.12(或 nightly build)。 - 数值一致性验证:在自己的模型或随机张量上,对比
gelu_new(x)与F.gelu(x, approximate="tanh")的输出差异。建议使用不同 dtype、设备、张量形状进行测试。 - 如果需要替换:可尝试修改 Transformers 源码,在
activations.py中根据 PyTorch 版本条件引入F.gelu(x, approximate="tanh")。但需注意 Issue 中社区强调的“数值向后兼容性”原则——任何输出变化都需显式启用(如添加新函数,而非覆盖原函数)。 - 关注上游进展:该 Issue 最终未被合并,后续可通过
huggingface/transformers的 PR 或 issue 跟踪是否有正式实现。
验证方法
执行数值一致性测试脚本:
import torch
import torch.nn.functional as F
x = torch.randn(1000, 768) # 模拟常见 hidden_size
out_torch = F.gelu(x, approximate="tanh")
out_hf = gelu_new(x) # 此处 gelu_new 需从 transformers 导入
print(torch.allclose(out_torch, out_hf, rtol=1e-6))
如果输出来自 Transformers 官方后续合入版本,则也应确保模型推理最终输出(logits / loss)在前后版本间不产生不可接受的差异。
参考来源
huggingface/transformers #15397: [activations] pytorch-1.11+ Tanh Gelu Approximation



