Neural network formulas: a cheat sheet · Activation functions

ReLU: the rectified linear unit

The simplest nonlinearity and the workhorse of deep learning. We take it apart bone by bone: why a single kink is enough to build any broken line, what the derivative at the kink is, how a ReLU network cuts space into linear pieces, why neurons “die”, and where the 2 in He initialization comes from.

Javharbek Abdulatipov · 35 min read
$$\operatorname{ReLU}(x)=\max(0,\,x)$$

Why we need it

Without a nonlinearity a neural network is useless: a composition of linear layers is again a linear function, however many layers you stack. We need a function that “breaks” linearity while being cheap to compute and gentle on the gradient. ReLU (rectified linear unit) does the minimum possible: it passes positive values unchanged and replaces negative ones with zero.

Where it appears:

  • convolutional networks — AlexNet, VGG, ResNet: ReLU is the main nonlinearity after the convolutions;
  • fully connected networks and tabular models — the default choice for hidden layers;
  • the original Transformer (2017) — the FFN block: $\max(0,\,xW_1+b_1)W_2+b_2$; modern LLMs moved to its smooth relatives GELU and SiLU (often inside the gated SwiGLU block);
  • mobile networks — ReLU6 $=\min(\max(0,x),\,6)$ in MobileNet suits low-precision arithmetic;
  • inside other formulas — $\max(0,\cdot)$ is also the SVM hinge loss, the triplet loss and the positive part of a number $x^+$.
The essentials in a minute

$\operatorname{ReLU}(x)=\max(0,x)$: zero on the left, the line $y=x$ on the right. The derivative is a step: 0 for $x<0$ and 1 for $x>0$; at zero there is no derivative, and libraries take 0. On the right the gradient passes without attenuation — that is why deep ReLU networks train fast. The price is “dead” neurons whose input is always negative.

Intuition: a rectifier

The name comes from electronics: a rectifier diode lets current flow one way and blocks it the other way. A ReLU neuron is a detector: while a feature is below the threshold it stays silent; once the threshold is crossed, it responds in proportion to how far.

Drag the point. To the right of zero the tangent coincides with the function itself (slope 1); to the left it lies on the axis (slope 0). At zero there is no single tangent: every line with a slope between 0 and 1 touches the graph from below — these are supporting lines.

Figure 1. ReLU, the tangent and the derivative (below). At $x=1.5$: $\operatorname{ReLU}=1.5$, $\operatorname{ReLU}'=1$. Move the point to zero: the derivative is undefined, and the set of slopes of the supporting lines is the interval $[0,\,1]$ (the subdifferential); PyTorch and TensorFlow take 0 from it.
What to notice

ReLU does not saturate on the right: at $x=100$ the derivative is the same 1 as at $x=0.1$. For the sigmoid and tanh the derivative is already below $0.01$ at $|x|=5$. On the left, however, ReLU is fully “saturated”: the derivative is exactly 0.

The formula, bone by bone

It pays to recognise the same function in different forms — each one highlights its own property:

$$\operatorname{ReLU}(x)=\max(0,x)=\begin{cases}x, & x>0\\0, & x\le0\end{cases}=\frac{x+|x|}{2}=x\cdot\mathbb 1[x>0]$$
$\max(0,x)$
a comparison with zero — one operation, no exponentials or divisions;
$\frac{x+|x|}{2}$
for $x>0$ the terms are equal and give $x$; for $x<0$ they cancel out;
$x\cdot\mathbb 1[x>0]$
a gate: the input is multiplied by 0 or 1 depending on its sign. For each example a ReLU network is a linear network with some neurons switched off.
$x$$\operatorname{ReLU}(x)$$\operatorname{ReLU}'(x)$
−300
−100
−0.500
00[0, 1]
0.50.51
111
2.52.51

Kinks make any broken line

A neuron $v\cdot\operatorname{ReLU}(x-c)$ is a “hinge”: zero up to the point $c$, then a line with slope $v$. Adding hinges with different $c$ gives a broken line: at each point $c_k$ the slope changes by exactly $v_k$. For example, $\operatorname{ReLU}(x+1)-2\operatorname{ReLU}(x)+\operatorname{ReLU}(x-1)$ is a “hat” of height 1.

Figure 2. A sum of three hinges with kinks at $-1$, $0$, $1$. With weights $(1,\,-2,\,1)$ we get a hat: the slopes of the pieces are $0,\ 1,\ -1,\ 0$ and the height is $f(0)=1$. Below is the derivative: a step function that jumps by exactly $v_k$ at the point $c_k$.

This is the main secret of ReLU networks: any continuous piecewise linear function on the line with $m$ kinks is $a+bx$ plus $m$ hinges, i.e. a network with one hidden layer of $m$ neurons (plus the output bias $a$ and the term $bx$, which two neurons can also express: $x=\operatorname{ReLU}(x)-\operatorname{ReLU}(-x)$). And broken lines approximate any continuous function on an interval as closely as we like.

Properties

  • Range: $[0,\,+\infty)$ — unbounded above, unlike the sigmoid and tanh.
  • Piecewise linearity: two linear pieces, one kink at zero.
  • Continuity and the Lipschitz property with constant 1: $|\operatorname{ReLU}(a)-\operatorname{ReLU}(b)|\le|a-b|$.
  • Convexity: the graph lies on or below every chord — the maximum of two linear functions is always convex.
  • Positive homogeneity: $\operatorname{ReLU}(\alpha x)=\alpha\operatorname{ReLU}(x)$ for $\alpha\ge0$. Scale can be moved between layers: multiplying a layer’s weights by $\alpha>0$ and the next layer’s by $1/\alpha$ gives the same network.
  • Idempotence: $\operatorname{ReLU}(\operatorname{ReLU}(x))=\operatorname{ReLU}(x)$.
  • Decomposing a number: $x=\operatorname{ReLU}(x)-\operatorname{ReLU}(-x)$ and $|x|=\operatorname{ReLU}(x)+\operatorname{ReLU}(-x)$.
  • Sparsity: if the neurons’ inputs are symmetric about zero, about half of the outputs are exact zeros.
Proofs: convexity and homogeneity

Convexity. For $t\in[0,1]$ and any $a,b$: $\max(0,\,ta+(1-t)b)\le\max\bigl(0,\,t\max(0,a)+(1-t)\max(0,b)\bigr)=t\max(0,a)+(1-t)\max(0,b)$, because $a\le\max(0,a)$, $b\le\max(0,b)$, and the right-hand side is non-negative.

Homogeneity. For $\alpha>0$ the sign of $\alpha x$ equals the sign of $x$, so $\max(0,\alpha x)=\alpha\max(0,x)$; for $\alpha=0$ both sides are 0. For $\alpha<0$ the equality fails: $\operatorname{ReLU}(-x)\ne-\operatorname{ReLU}(x)$ — the function is not odd.

The derivative, the subgradient and smooth relatives

$$\operatorname{ReLU}'(x)=\begin{cases}1, & x>0\\0, & x<0\end{cases},\qquad \partial\operatorname{ReLU}(0)=[0,\,1]$$
Why there is no derivative at zero

The derivative is the limit of the difference quotient. To the right and to the left of zero it differs:

$$\lim_{h\to0^+}\frac{\operatorname{ReLU}(h)-0}{h}=\lim_{h\to0^+}\frac{h}{h}=1,\qquad \lim_{h\to0^-}\frac{\operatorname{ReLU}(h)-0}{h}=\lim_{h\to0^-}\frac{0}{h}=0$$

The one-sided derivatives differ, so there is no ordinary derivative. Convex functions have a substitute — the subgradient: a number $g$ such that $f(y)\ge f(x)+g(y-x)$ for all $y$, i.e. the line with slope $g$ lies below the graph. At zero every $g\in[0,1]$ qualifies: this set is called the subdifferential $\partial\operatorname{ReLU}(0)$.

Why this hardly hurts training: for continuous data a neuron’s input is exactly zero with probability 0. In floating-point arithmetic exact zeros do occur, but so rarely that the choice of a value in $[0,1]$ hardly matters (in 16-bit arithmetic zeros are noticeably more frequent, and the choice of $\operatorname{ReLU}'(0)$ can sometimes affect training). By convention libraries take 0.

The second derivative is zero everywhere except at zero (in the sense of distributions, $\operatorname{ReLU}''=\delta(x)$). Hence inside each linear region a ReLU network is an affine function of its input, and its gradient with respect to the input is piecewise constant.

Softplus: a smoothed ReLU

If the kink gets in the way (for example, when second-order optimization or a physical model needs a smooth function), it can be rounded off:

$$\operatorname{softplus}_\beta(x)=\frac1\beta\ln\bigl(1+e^{\beta x}\bigr),\qquad \operatorname{softplus}_\beta'(x)=\sigma(\beta x)$$

The difference $\operatorname{softplus}_\beta(x)-\operatorname{ReLU}(x)=\frac1\beta\ln\bigl(1+e^{-\beta|x|}\bigr)$ is largest at zero, where it equals $\frac{\ln2}{\beta}$; as $\beta\to\infty$ softplus tends to ReLU, and its derivative, the sigmoid, tends to the step. At zero it always equals $\sigma(0)=0.5$ — the middle of the subdifferential $[0,1]$.

Figure 3. Top: ReLU and $\operatorname{softplus}_\beta$; bottom: their derivatives. At $\beta=1$ the largest gap is $\ln2\approx0.693$, at $\beta=4$ it is $0.173$, at $\beta=32$ — $0.022$. The derivative of softplus at zero is always $0.5$.

A ReLU network in space: linear regions

A first-layer neuron with two inputs is off on one side of the line $w^\top x+b=0$ and linear on the other. Each such line is a fold line. $H$ neurons cut the plane into regions, and within each region the set of active neurons (the activation pattern) is constant, so the network is an ordinary affine function there. The output surface is a polyhedron glued together from flat facets.

Figure 4. Left: the network output $f(x_1,x_2)=\sum_k v_k\operatorname{ReLU}(w_k^\top x+b_k)$ in 3D — flat facets and fold edges. Right: the view from above; colour is the index of the linear region, dashed lines are the neurons’ lines, thin lines are levels of $f$ (they bend at the boundaries). With 4 neurons the window shows 10 regions out of a possible 11 ($1+H+\tfrac{H(H-1)}{2}$); with 8 neurons, 25 out of 37. Two layers of 4 neurons already give 30 regions: the second layer’s boundaries bend at the first layer’s.

$H$ lines in general position divide the plane into at most $1+H+\binom H2$ parts — the number of regions of one layer grows polynomially. Depth works differently: each next layer “folds” the already cut space, and the number of regions can grow exponentially with the number of layers (Montúfar et al., 2014). This is one explanation of why deep networks are more expressive than wide ones with the same number of neurons.

Universal approximation

A network with one hidden ReLU layer and enough neurons approximates any continuous function on a closed bounded set to any accuracy (Leshno et al., 1993: any continuous activation that is not a polynomial will do). For ReLU this is visible literally: broken lines are made of hinges, polyhedral surfaces of folds.

ReLU in training: the network draws a broken line

Let us train one hidden layer $\hat y(x)=\sum_{k=1}^{H}v_k\operatorname{ReLU}(w_kx+b_k)+c$ on points of a sine wave. Each neuron is a hinge with its kink at $x=-b_k/w_k$; gradient descent moves the kinks to where the curve bends and tunes the slopes.

$$\frac{\partial\hat y}{\partial b_k}=v_k\,\mathbb 1[w_kx+b_k>0],\qquad \frac{\partial\hat y}{\partial w_k}=v_k\,x\,\mathbb 1[w_kx+b_k>0]$$

The gradient with respect to a neuron’s parameters comes only from the points where the neuron is on. If there are no such points at all, the neuron stops learning — that is what “dying” means.

Figure 5. 40 points of $y=\sin(1.6x)$ with noise ($\sigma=0.08$), full-batch gradients and Adam with step $0.02$. Teal lines are the hinges, the dots at the bottom are their kinks, red dashes are dead neurons. With 6 neurons the MSE drops from $3.102$ to $0.267$ by step 100, $0.012$ by step 300 and $0.0090$ by step 1500; on the way one neuron dies. With 3 neurons one is dead from the very start, and a broken line made of two live hinges is too coarse — $0.265$; with 12 the result is $0.0101$, but 4 of the 12 are dead (three of them already at initialization).
What the figure shows

A ReLU network cannot draw anything smooth — only broken lines. Of the 6 neurons, 5 are alive by step 1500, and their kinks sit at about $-2.5$, $-1.2$, $-0.4$, $0.3$ and $1.0$: near the peaks of the sine (around $\pm1$ and at the left edge) and at the ends of its nearly straight stretch around zero. Extra neurons do not necessarily help: with 12 neurons some die and some duplicate their neighbours (kinks at $-1.2$ and $-1.0$, at $-0.25$ and $-0.09$).

The dying ReLU

A neuron is “dead” if $w^\top x+b\le0$ on all training examples. Then its output is always 0, the gradients with respect to $w$ and $b$ are always 0 (see the formula above), and a gradient step by itself will not revive it. For a first-layer neuron, whose inputs are the fixed data, this is permanent (with plain SGD). In deeper layers a neuron’s input changes as the earlier layers learn, and the momentum of SGD with momentum or Adam keeps moving the parameters for a while, so neurons occasionally come back — but you cannot count on it.

How it happens: one large gradient step sharply decreases the bias $b$ or turns $w$ so that the neuron’s hyperplane moves outside the cloud of data. The larger the learning rate, the more often this happens.

Figure 6. A network of 64 ReLU neurons on 128 points $y=\sin(3x_1)+x_2$, $x\in[-1,1]^2$, mini-batches of 16, plain SGD, 600 steps, the same He initialization ($\operatorname{Var}w=2/2=1$ for two inputs, zero biases). Right: the neurons — blue ones are alive (brightness is the share of points where the neuron is on), red ones are dead. With $\eta=0.3$, $91\%$ of the neurons die within the first 5 steps and $97\%$ by the end; the MSE gets stuck at $0.137$. With $\eta=0.2$ a quarter is dead ($27\%$), MSE $0.004$; with $\eta=0.1$ and $0.03$ none die (MSE $0.005$ and $0.041$ — the small step is simply slower).

How to treat it:

  • a moderate learning rate, warm-up and gradient clipping;
  • normalization and adaptive optimizers: BatchNorm before the activation centres each neuron’s input over the batch, and Adam limits each parameter’s step to roughly $\eta$, so a single huge gradient cannot throw the bias far (this lowers the risk but does not remove it);
  • activations with a non-zero slope on the left — Leaky ReLU, PReLU, ELU, GELU, SiLU: the gradient on the left is not zero, so the neuron can come back;
  • careful initialization: zero biases (sometimes slightly positive), He weights. Strongly negative biases kill neurons before training even starts.

He initialization: where the 2 comes from

Let $z=\sum_{j=1}^{n}w_jh_j$ with independent weights, $\mathbb Ew_j=0$, $\operatorname{Var}w_j=c/n$. Then $\operatorname{Var}z=c\cdot q$, where $q=\mathbb E[h^2]$ is the mean square of the inputs. If $z$ is symmetric about zero, ReLU zeroes out exactly half of its distribution, and

$$q_{l}=\mathbb E\bigl[\operatorname{ReLU}(z)^2\bigr]=\frac12\operatorname{Var}z=\frac c2\,q_{l-1}\qquad\Longrightarrow\qquad q_L=q_0\Bigl(\frac c2\Bigr)^{L}$$

With $c=1$ (as for tanh) the signal halves at every layer; with $c=3$ it grows by half. Only $c=2$ preserves the scale: this is He initialization (He et al., 2015), $\operatorname{Var}w=2/n_\text{in}$. The backward pass works the same way (with $n_\text{out}$ instead of $n_\text{in}$, which is the same thing for layers of equal width), so the gradients neither vanish nor explode either.

Figure 7. The mean square of the activations $q_l$ at each of the 30 layers of a random network of width 100 (log scale); the orange dashed line is the theory $q_0(c/2)^l$. With $c=2$ the ratio $q_{30}/q_0=2.66$; with $c=1$ it is $2.47\cdot10^{-9}$ (theory $9.3\cdot10^{-10}$); with $c=3$, $5.1\cdot10^5$ (theory $1.9\cdot10^5$). The factor $\approx2.66$ is the same in all three cases: the weights are the same and ReLU is positively homogeneous, so $c$ merely multiplies the whole signal by $(c/2)^{L/2}$; the deviation from theory is a random finite-width fluctuation. The share of active neurons in the last layer is $51\%$, almost exactly half.
A bit of history

The rectifier idea is old: Fukushima used it as early as 1969. ReLU entered deep learning in 2010–2011 (Nair and Hinton; Glorot, Bordes and Bengio), and in the AlexNet paper (2012) a four-layer convolutional network with ReLU reached 25% training error on CIFAR-10 six times faster than the same network with tanh. In 2015 He et al. derived the $2/n$ initialization and showed that with it even a 30-layer ReLU network trains from scratch, while with Xavier initialization it does not learn.

In code

ReLU never overflows and never loses precision: a comparison with zero is exact in any arithmetic. Attention belongs elsewhere: the convention at zero, dead neurons and initialization.

pythonimport numpy as np

def relu(x):
    return np.maximum(0.0, x)

def relu_grad(x):
    # subgradient: take 0 at the point 0, like PyTorch and TensorFlow
    return (x > 0).astype(float)

x = np.array([-3.0, 0.0, 2.5])
print(relu(x), relu_grad(x))     # [0.  0.  2.5] [0. 0. 1.]

# “Dead” neurons: not a single positive input on the whole dataset
rng = np.random.default_rng(0)
X = rng.normal(size=(1000, 20))
W = rng.normal(size=(20, 64)) * np.sqrt(2 / 20)   # He initialization
for b0 in (0.0, -5.0):
    Z = X @ W + b0
    dead = np.mean((Z > 0).sum(axis=0) == 0)
    print(b0, f"{dead:.0%}")     # 0.0 0%  and  -5.0 66%
pythonimport torch
import torch.nn as nn

x = torch.tensor([-1.0, 0.0, 2.0], requires_grad=True)
torch.relu(x).sum().backward()
print(x.grad)                    # tensor([0., 0., 1.]) — 0 at zero

# He initialization: Var w = 2 / fan_in
layer = nn.Linear(512, 512)
nn.init.kaiming_normal_(layer.weight, mode="fan_in", nonlinearity="relu")
nn.init.zeros_(layer.bias)

# The FFN block of the original Transformer: Linear → ReLU → Linear
ffn = nn.Sequential(nn.Linear(512, 2048), nn.ReLU(), nn.Linear(2048, 512))
# nn.ReLU(inplace=True) saves memory but overwrites the input if it is still needed
The rule

ReLU plus He initialization (kaiming_normal_ with nonlinearity='relu'), zero biases and a reasonable learning rate. Check from time to time the share of neurons that never fired on a batch: if it grows, lower the learning rate or switch to Leaky ReLU / GELU.

Common mistakes

  1. ReLU at the output of a regression whose target can be negative. The network physically cannot output $y<0$. A regression output needs a linear layer; ReLU at the output fits only quantities that are non-negative by nature (and even then softplus is often better: a ReLU output has zero gradient for negative inputs).
  2. Initialization meant for tanh. With $\operatorname{Var}w=1/n$ the signal in a deep ReLU network decays as $2^{-L}$: after 30 layers by a factor of $2^{30}\approx10^9$ (Figure 7). Use He initialization.
  3. Too large a learning rate. It kills neurons en masse, and they cannot be restored (Figure 6). The symptom: the loss is frozen and the share of zero activations is close to 100%.
  4. “The derivative of ReLU at zero is 1/2” or “it is undefined, so it is a bug”. Mathematically, at zero there is the subdifferential $[0,1]$, and any value from it is admissible; libraries take 0. In practice it hardly affects training.
  5. inplace=True where the input is needed later. The operation overwrites its input; if that input is used in a residual connection or by another operation’s backward pass, PyTorch raises an error or the result is wrong.
  • Leaky ReLU: $\max(\alpha x,x)$ — a non-zero slope $\alpha$ on the left cures dying.
  • GELU and SiLU: $x\Phi(x)$ and $x\sigma(x)$ — smooth “gates” instead of the hard $x\cdot\mathbb 1[x>0]$; far from zero they behave like ReLU.
  • Sigmoid: the derivative of softplus is $\sigma(\beta x)$; ReLU displaced the sigmoid from hidden layers because of saturation.
  • tanh: saturates on both sides; tanh gets Xavier initialization, ReLU gets He.
  • Huber and Triplet loss: the cut-off $\max(0,\cdot)$ appears in loss functions too.
  • Adam and SGD: the optimizer and the learning rate decide how many neurons die.

Summary

1) $\operatorname{ReLU}(x)=\max(0,x)=\frac{x+|x|}2$ is a gate: the input is multiplied by $\mathbb 1[x>0]$. 2) The derivative is a 0/1 step; at zero the subdifferential is $[0,1]$, in practice 0; no saturation on the right. 3) A sum of hinges $v_k\operatorname{ReLU}(x-c_k)$ is any broken line; on the plane a ReLU network is a polyhedron of linear regions, and depth multiplies their number. 4) Softplus is a smooth ReLU whose derivative is the sigmoid. 5) A large learning rate kills neurons for good. 6) He initialization $\operatorname{Var}w=2/n_\text{in}$ compensates for ReLU zeroing half of the signal.

Check yourself

1. What is $\operatorname{ReLU}(x)-\operatorname{ReLU}(-x)$?
2. What does PyTorch return as the gradient of ReLU at $x=0$?
3. A network with one hidden layer of 5 ReLU neurons and one input $x$. What can its graph be?
4. Why can a ReLU neuron “die” for good?
5. What weight variance does He initialization suggest for a layer with $n_\text{in}$ inputs?