Standing
Commonly usedEstablished and frequently the right choice, but competing with live alternatives rather than having settled the question.
In BERT, GPT-2, GPT-3 and every ViT. New models use SiLU inside a gate instead, and the difference between them is not measurable.
judged as of 2026-09 · what the labels mean
Theory
ReLU makes a hard decision: keep the input or discard it. GELU makes a soft one — scale the input by how likely it is to be worth keeping, where “likely” is read off a standard normal.
The motivation in the original paper is a stochastic regulariser: dropout multiplies by a Bernoulli mask, and if you make the keep-probability depend on the input’s magnitude and then take the expectation, is what falls out. Whether that story is load-bearing is doubtful. What is not doubtful is that the function has a small negative lobe and a continuous derivative, and both help.
The family
Three functions are in circulation and they are near-identical over the range activations actually occupy.
| Name | Form | Where |
|---|---|---|
| GELU | BERT, GPT-2/3, ViT | |
| SiLU / Swish | Llama, Mistral (inside a gate) | |
| GELU-tanh | the fast approximation |
SiLU replaces the Gaussian CDF with a logistic one, which is the same S-curve with slightly heavier tails. Ramachandran et al. found it by automated search, which is a pleasing result about how much of activation design is taste: a search over thousands of candidates rediscovered the function someone had already derived from a dropout argument.
That constant is a curve fit, not a derivation. The approximation exists because
erf was slow on the hardware of 2018; it is no longer slow, and the
approximation persists because checkpoints were trained against it.
Implementation
import math
import torch
from torch import Tensor
def gelu_exact(x: Tensor) -> Tensor:
return x * 0.5 * (1.0 + torch.erf(x / math.sqrt(2.0)))
def gelu_tanh(x: Tensor) -> Tensor:
"""GPT-2's form. Use this iff the checkpoint was trained with it."""
inner = math.sqrt(2.0 / math.pi) * (x + 0.044715 * x.pow(3))
return x * 0.5 * (1.0 + torch.tanh(inner))
# torch spells the choice as a flag, which is the right way to carry it:
# nn.GELU() -> exact
# nn.GELU(approximate="tanh") -> GPT-2Does the choice matter
Barely, and it is worth saying so plainly. Shazeer’s GLU-variants paper trained the whole matrix — ReLU, GELU, Swish, each with and without a gate — and the gated versions beat the ungated ones by a clear margin while the activations within each group were separated by noise.
The conclusion the field drew, correctly, is that gating is the design decision and the activation inside it is a detail. Llama uses SiLU because SwiGLU is what Shazeer named; had he named GEGLU, the models would use GELU and nothing else would differ.