Concept units

Activation functions: bending straight lines

Intermediate

Read these first if they are new to you

The idea in one paragraph

An activation function is a fixed, simple function that a network applies to each output of a linear layer, one number at a time. The most common one, ReLU, replaces negative numbers by zero and keeps positive numbers. Without activation functions, any stack of linear layers works out to a single linear layer, which can only describe straight-line relationships. With them, the stack can bend, and enough bends can follow almost any curve.

Two linear layers in a row are still one straight line

A linear layer computes weighted sums. Take the simplest case: one input x and one output. Let a first layer compute 2x − 1. Let a second layer take that result, multiply by 3 and add 1:

3(2x − 1) + 1 = 6x − 2

The result is again a straight line. This always happens: a weighted sum of weighted sums is a weighted sum. Ten linear layers in a row can do no more than one.

ReLU puts a corner into the line

Now apply a function between the two layers. The ReLU (rectified linear unit) is the simplest:

ReLU(z) = max(0, z)

It keeps a positive number and turns a negative number into 0. So 3 × ReLU(2x − 1) + 1 is flat at 1 until x = 0.5, then rises with slope 6. The line has a corner. The second layer cannot undo that corner, because it only scales and shifts.

A function used this way is called an activation function. It acts on each number of a layer's output separately, and it has no weights of its own to learn.

Worked example: two corners make a tent

Take two hidden numbers, h1 = ReLU(x) and h2 = ReLU(x − 1). Combine them with a second linear layer: y = h1 − 2h2.

x−100.5123
h1 = ReLU(x)000.5123
h2 = ReLU(x − 1)000012
y = h1 − 2h2000.510−1

The output is flat, then rises to a peak of 1 at x = 1, then falls. No straight line does that.

Your turn. What is y at x = 1.5?

Answer

h1 = 1.5 and h2 = 0.5, so y = 1.5 − 1 = 0.5. It is on the way down.

Several activation functions are in common use

All of them bend. They differ in shape: sharp corner or smooth curve, and whether the output is limited to a range.

NameFormulaShape
ReLUmax(0, z)zero for negatives, a corner at 0
GELUz × Φ(z)a smooth version of ReLU that dips slightly below 0
SiLUz × sigmoid(z)close to GELU
sigmoid1 / (1 + e−z)an S between 0 and 1
tanh(ez − e−z) / (ez + e−z)an S between −1 and 1

Φ(z) is the chance that a draw from the standard bell curve is below z. The sigmoid has its own unit. ReLU, GELU and SiLU are the usual choices inside networks today. Sigmoid and tanh appear mostly where an output must stay in a range.

Try it. The figure below runs one small network with each activation function in turn. Predict first: which choice gives a straight output line? Then find the choice whose output has sharp corners, and say where they are.

The same small network, with the activation function swapped

The activation function f(z)

The network's output y(x)

Only the activation function changes. The network has one input, three hidden numbers hk = f(2(x − ck)) with c = −1.5, 0 and 1.5, and the output y = h1 − 2h2 + 1.5h3. The weights stay fixed. The vertical scale adjusts to each choice.
Answer

"None" gives a straight line, y = x − 1.5. ReLU gives corners at x = −1.5, 0 and 1.5, where each hidden number switches on. GELU, sigmoid and tanh give smooth bends near the same places.

What this page leaves out

Which activation function trains best is mostly found by experiment, not derived. The figure computes GELU with the common tanh approximation, which differs from the exact formula by less than 0.001. ReLU has no slope at exactly 0; software simply uses 0 there.

In code, an activation is one function call

activations.py

import torch

z = torch.tensor([-2.0, -0.5, 0.0, 0.5, 2.0])
print("relu   ", torch.relu(z))
print("sigmoid", torch.sigmoid(z))
print("tanh   ", torch.tanh(z))
print("gelu   ", torch.nn.functional.gelu(z))
relu    tensor([0.0000, 0.0000, 0.0000, 0.5000, 2.0000])
sigmoid tensor([0.1192, 0.3775, 0.5000, 0.6225, 0.8808])
tanh    tensor([-0.9640, -0.4621,  0.0000,  0.4621,  0.9640])
gelu    tensor([-0.0455, -0.1543,  0.0000,  0.3457,  1.9545])

The tent from the worked example, with NumPy, next to the same layers without ReLU:

bend.py

import numpy as np

def relu(z):
    return np.maximum(0.0, z)   # np.maximum keeps the larger of 0 and each number

x = np.array([-1.0, 0.0, 0.5, 1.0, 2.0, 3.0])

# Two linear steps with nothing between: still a straight line.
print(3 * (2 * x - 1) + 1)          # same as 6x - 2

# Two hidden units with ReLU, then a weighted sum: a bend.
h1, h2 = relu(x), relu(x - 1)
print(h1 - 2 * h2)
[-8. -2.  1.  4. 10. 16.]
[ 0.   0.   0.5  1.   0.  -1. ]

Check yourself

  1. What is ReLU applied to the list (−3, 0.2, 5)?

    Answer

    (0, 0.2, 5). The negative number becomes 0; the others stay.

  2. A network has five linear layers and no activation functions. Can it fit a set of points that lie on a parabola?

    Answer

    No. The five layers work out to one linear layer, so the output is a straight line (a flat plane, with more inputs). It cannot follow the curve.

  3. Using the tent network y = ReLU(x) − 2 × ReLU(x − 1), find y at x = 4 and at x = −5.

    Answer

    At 4: 4 − 2 × 3 = −2. At −5: both hidden numbers are 0, so y = 0.

  4. A model's output must be a probability between 0 and 1. Which activation from the table would you put on that output, and why not ReLU?

    Answer

    The sigmoid, because its output always lies between 0 and 1. ReLU can give any number of 0 or above, including numbers above 1.

Go further

Optional background, for readers who want more than this page.

Where this shows up

Units that build on this one