machine learning · math

ReLU: the bent line that taught networks to go deep

Sep 19, 2017 · 9 min read

Most of the functions that matter in machine learning look like they were designed by a committee: the Gaussian with its \sqrt{2\pi}, the softmax with its exponentials, the sigmoid with its careful S. Then there's the rectified linear unit, which looks like a mistake. It's a straight line that someone folded in half at the origin:

\text{ReLU}(x) = \max(0, x).

Keep the positive part, flatten everything negative to zero. That's the whole definition. It is the single most-used activation function in deep learning, and if you'd shown it to a numerical analyst in 1990 they'd have wrinkled their nose — it's not smooth, it's not bounded, its derivative doesn't even exist at one point. And yet this bent line is a large part of why neural networks got deep in the first place. Let's earn it.

A hinge and its slope

Picture the graph: for x < 0 it lies flat along the axis, and at x = 0 it snaps upward to follow the diagonal y = x. One corner, two straight pieces — an elbow, a hinge. Its derivative is just as blunt:

\text{ReLU}'(x) = \begin{cases} 0 & x < 0, \\ 1 & x > 0. \end{cases}

On the active side the slope is exactly 1; on the dead side it's exactly 0. At x = 0 the derivative genuinely doesn't exist — the left slope is 0, the right slope is 1, and there's no single tangent to split the difference. In practice nobody loses sleep over it: you pick a subgradient, usually 0, and move on. The probability of landing precisely on the kink is zero anyway, and floating-point arithmetic will drift you off it soon enough.

That's the entire object. A function this plain has no business being important. The reason it is takes three ideas, and they build on each other.

Why you need a bend at all

Start with the question ReLU quietly answers: why does a network need a nonlinearity anywhere? Why not just stack linear layers and let depth do the work?

Because depth does no work if every layer is linear. Suppose layer one computes h = W_1 x + b_1 and layer two computes y = W_2 h + b_2. Substitute:

y = W_2(W_1 x + b_1) + b_2 = (W_2 W_1)\,x + (W_2 b_1 + b_2).

That's just y = W x + b with W = W_2 W_1 and b = W_2 b_1 + b_2. Two layers collapsed into one. Stack a hundred linear layers and they still collapse into one — a composition of linear maps is a linear map, full stop. You could add a thousand layers and never represent anything a single matrix couldn't. All that depth, all those parameters, and the function class never grows past "straight lines and flat planes."

The nonlinearity is what breaks the collapse. Slip a \max(0, \cdot) between the matrices and the substitution above simply doesn't go through — you can't pull the weights out past the kink. Suddenly each layer earns its keep, and depth starts buying you genuinely richer functions. That's the deal ReLU makes: one cheap bend per unit, in exchange for permission to be deep. Nonlinearity is the price of admission, and ReLU is the cheapest ticket at the door.

Why the bend beat the S-curve

For a couple of decades the bend of choice was smooth: the sigmoid \sigma(x) = 1/(1 + e^{-x}), or its cousin \tanh. They're gorgeous — bounded, differentiable everywhere, with a probabilistic reading. So why did a crude hinge shove them aside once networks got deep?

The answer is a single word that haunted early deep learning: vanishing gradients. Training happens by backpropagation, which is the chain rule run backwards through the layers — and the chain rule multiplies the local derivatives together. Look at the sigmoid's derivative: \sigma'(x) = \sigma(x)(1 - \sigma(x)), which peaks at a measly 0.25 when x = 0 and decays toward zero as soon as x wanders away from the origin. The moment a neuron saturates — pinned near 0 or 1 — its local gradient is a whisper.

Now chain ten of those together. Even in the best case you're multiplying numbers around 0.25: 0.25^{10} \approx 10^{-6}. The gradient that reaches the early layers is a millionth of what left the top, and in the saturated regions it's far worse. The first layers barely move; the network learns at a crawl or not at all. That's the vanishing-gradient wall that kept networks shallow for years.

ReLU walks straight through it. On the active side its derivative is exactly 1, not 0.25 — and 1^{10} = 1. Multiply as many ones as you like and nothing shrinks. Backprop's signal arrives at the bottom layers with its magnitude intact, so deep stacks actually train. The hinge won not because it's elegant but because it doesn't attenuate the gradient. Sometimes crude and flat beats smooth and saturating.

How a ReLU dies

Every deal has fine print, and ReLU's is grim: a unit can die. Look again at that derivative — it's 0 for all x < 0. A neuron whose weighted input is negative outputs zero and has zero gradient, which means backprop sends it no correction. It just sits there.

Usually that's fine; next batch it flips positive and wakes up. But suppose a large gradient update shoves a neuron's weights and bias so far that its input is negative for every example in the data. Now it outputs zero on everything, its gradient is zero on everything, and there is no force anywhere that can nudge it back. It's frozen — a dead ReLU, a permanent zero. In a badly tuned network, especially one with too aggressive a learning rate, a distressing fraction of units can flatline this way, and a dead unit is worse than a useless one: it's a parameter you're carrying that will never contribute again. This is exactly the kind of failure a careful gradient descent setup — a sane learning rate, good initialization — is trying to avoid.

The diagnosis points straight at the cure. The problem is that flat left half with its zero gradient. So: what if the negative side weren't quite flat?

A family of gentler bends

That single idea — give the negative side a little life — spawns most of the ReLU variants.

Leaky ReLU is the bluntest fix: instead of zero, let negatives through at a small slope \alpha (say 0.01):

\text{LeakyReLU}(x) = \max(\alpha x, x) = \begin{cases} x & x \ge 0, \\ \alpha x & x < 0. \end{cases}

Now the left half has slope \alpha instead of 0, so its gradient is never exactly zero and a unit can always claw its way back from the dead. PReLU (parametric ReLU) takes the obvious next step and makes \alpha a learned parameter, so the network decides for itself how leaky each unit should be rather than you guessing.

ELU (exponential linear unit) smooths the elbow and lets the negative side saturate gently toward -1 instead of running off linearly:

\text{ELU}(x) = \begin{cases} x & x \ge 0, \\ \alpha(e^{x} - 1) & x < 0. \end{cases}

It's differentiable at the origin and pushes the mean activation closer to zero, which can help training — at the cost of an exponential to evaluate.

GELU (Gaussian error linear unit) is the one that ended up in the transformers running today. Instead of a hard gate that keeps x or kills it, it weights the input by the probability that a standard normal falls below it:

\text{GELU}(x) = x \cdot \Phi(x),

where \Phi is the standard normal CDF. The result is a smooth curve that hugs ReLU for large |x| but dips slightly below zero near the origin, giving a soft, probabilistic version of the gate.

f(x) x 0 ReLU leaky ReLU GELU ELU
ReLU is the hard hinge in steel. Leaky ReLU (gold) tilts the dead half up a touch; ELU (grey) and GELU (deep gold) round off the corner and let the negative side breathe. The differences all live near the origin — far out, everyone agrees with ReLU.

Line them up and a pattern emerges: every variant is fussing over the same small neighborhood around zero, trying to keep a little gradient alive on the negative side without giving up ReLU's clean, un-vanishing slope of 1 on the positive side. They differ in the details near the elbow and agree completely in the tails.

Bent lines, summed into anything

Here's the payoff that makes all of this feel inevitable. A single ReLU is a boring, piecewise-linear elbow. But watch what happens when you take a weighted sum of several, each with its own breakpoint:

g(x) = \sum_{k} w_k \,\text{ReLU}(x - b_k).

Each term \text{ReLU}(x - b_k) is flat until x reaches its breakpoint b_k, then kicks in with slope w_k. So at every breakpoint the total slope changes by w_k, and between breakpoints the sum is just a straight line. Add more terms and you get a curve made of straight segments that changes direction wherever you like, by however much you like — a piecewise-linear function with knots exactly at the breakpoints.

And piecewise-linear functions can approximate any continuous function as closely as you want: chop the domain into fine enough pieces and connect the dots with line segments, and the jagged approximation hugs the smooth target. This is the intuition behind the universal approximation theorem — a network with a single hidden layer of enough ReLUs can get arbitrarily close to any continuous function on a bounded domain. Depth makes this dramatically more efficient (some functions need exponentially fewer units when you stack layers), but even the flat, one-layer version already has the whole real line of continuous functions within reach. All from copies of one bent line, slid to different spots and scaled.

The fastest way to feel this is to build it yourself. The ReLU playground lets you drag the leaky slope to watch the variants morph near the origin, and — in the second panel — stack a handful of ReLU bumps with adjustable breakpoints and weights, summing them into a piecewise-linear curve that you tune, by hand, toward a target. Get the knots in the right places and the error readout drops toward zero, and you'll see the universal approximation theorem stop being a theorem and start being a thing you can do with a few sliders. A hinge, copied and stacked, bends into anything — that's the whole secret of the plainest function in deep learning.


Thoughts? Find me on LinkedIn.