Layers and activations
How do networks gain power by stacking layers?
Lesson complete
If you like:
One hidden layer was enough to solve XOR. Today we stack more layers and see how much power that gains, and why stacking, by itself, is not enough.
No voice: the lesson advances on its own with subtitles.
The voice for this lesson is being recorded: for now it advances on its own with subtitles.
Review modeComment on this stepI finished the lesson
What you will achieve
- Explain why stacking linear layers is equivalent to a single layer, and what changes when a nonlinear activation is added.
- Compute by hand the forward pass of a tiny network, with and without ReLU.
- Recognize what the universal approximation theorem says, and what it does not, and why layers are stacked in practice.
Key ideas
- A layer is a group of neurons that look at the same inputs; the forward pass computes layer by layer, from input to output.
- Without activation, two layers equal one: the product of two linear transformations is another linear transformation. Stacking adds nothing.
- Nonlinearity (ReLU, tanh, sigmoid) folds space: what a straight line could not separate becomes separable after the fold.
- With enough neurons, a single hidden layer can approximate any continuous function on a closed, bounded set (universal approximation), but the theorem does not say how many neurons are needed nor that training will find them.
- Stacking layers multiplies the folds: for certain functions, a deep network needs far fewer neurons than a single layer.
What many people believe
Common belief The more layers a network has, the more powerful it is, always.
What is true Without a nonlinear activation between them, any number of layers equals a single one. With it, more layers allow more shapes, but they also cost more to train and to run, and they do not guarantee a better result.
Check yourself
Four questions. No grade, no account: they just show whether the idea stuck.
Under the hoodFor those who want the math and the code. You do not need it to follow the course.
A layer, in one formula
A layer with neurons and inputs stores a weight matrix (one row per neuron) and a bias vector . Given the input , it computes
where is the activation, applied component by component. A forward pass chains this formula layer by layer. A dense network with sizes has parameters: for example, the 2-8-8-8-1 network of the playground has .
The linear collapse
If is the identity, two layers give
which is a single layer with weights and bias . With the numbers of the lesson:
By induction, linear layers equal one. With and input , the hidden layer gives , ReLU turns it into , and the output is , not : the equivalence breaks.
The activations
Their derivatives matter for training (lesson 8): , , and (at it does not exist; by convention it is taken as 0). ReLU, the “rectified linear unit”, has smooth variants such as GELU (Hendrycks and Gimpel, 2016), which BERT uses instead of ReLU (Devlin et al., 2019).
Universal approximation
What it says (Cybenko, 1989, theorem 2). A function is sigmoidal if as and as . If is continuous and sigmoidal, then for every continuous function on the unit cube (rescaling, on any cube) and every there exist , , and such that
Who else, and under which conditions. The same year, Hornik, Stinchcombe, and White proved it for “squashing functions” (non-decreasing, with limits 0 and 1, not necessarily continuous), and for measurable functions in a weaker sense (approximation in probability); in a closing note they acknowledge Funahashi’s work (1989), which had reached a close result independently. The hypotheses do not coincide: Cybenko does not require to be monotone, and Hornik et al. do not require it to be continuous. Hornik (1991) showed that a bounded, nonconstant activation is enough ( approximation; if it is also continuous, uniform approximation on compact sets). Leshno, Lin, Pinkus, and Schocken (1993) settled the question: for a locally bounded, piecewise continuous activation, a network with one hidden layer approximates every continuous function, uniformly on every compact set, if and only if the activation is not a polynomial. ReLU meets that condition. The theorem also needs the bias (the threshold): without it, it fails.
What it does not say. It approximates a known function on a bounded set; it says nothing outside it, nor about learning from examples. It does not bound or say how to find the weights. Cybenko admits this in his closing discussion: his paper is limited to existence, and he suspects that the vast majority of approximation problems will need an astronomical number of terms, because of the curse of dimensionality. Hornik et al. add that a failure in practice may be due to inadequate learning, too few neurons, or a random relation between input and output.
The construction in the lesson. It is not Cybenko’s proof, which uses the Hahn–Banach theorem and builds nothing. For a function of one variable, with equally spaced knots and slopes , ,
is a one-hidden-layer network with ReLU neurons that equals at the knots (piecewise linear interpolation). If , the maximum error is at most : doubling the neurons divides the bound by four. For the scene’s curve, ; with the bound is 0.026 and the measured error is 0.025. The ratio of measured errors is not always four: 2.5 from 3 to 6 neurons, 3.0 from 6 to 12, 4.1 from 12 to 24, and 3.8 from 24 to 48. Nor does it drop at every step (from 1 to 2, 4 to 5, and 7 to 8 neurons it rises a little, because equally spaced knots fall in other places). The turn’s goal, 0.05, is reached with 17 neurons (0.047; with 16, 0.057). Here the weights are computed, not trained.
Depth: the sawtooth
The tent function on uses two neurons: it rises from 0 to 1 on and falls from 1 to 0 on . The composition ( layers, neurons) has straight pieces (checked numerically up to ). A network with one hidden layer of ReLU neurons has at most pieces in one dimension (each neuron adds one corner), so to match it, it needs at least neurons. Telgarsky (2016) uses this same function and proves something stronger, for approximating and not just matching: for every there is a ReLU network with layers and neurons such that every ReLU network with at most layers and at most neurons stays at distance at least on . It is a result about specific functions, not a law: it does not say that every real task benefits equally from depth.
In code: the forward pass and the collapse
import numpy as np
W1 = np.array([[1, 2],
[3, -1]]) # hidden layer: one row per neuron
W2 = np.array([[2, 1]]) # output
def net(x, activation):
h = activation(W1 @ x) # forward pass: hidden layer...
return (W2 @ h)[0] # ...and output
linear = lambda z: z
relu = lambda z: np.maximum(0, z)
print("W2 @ W1 =", W2 @ W1) # the equivalent single neuron
for x in ([2, 1], [1, 0], [0, 1]):
x = np.array(x)
print(x, "no activation:", net(x, linear), "| one neuron:", (W2 @ W1 @ x)[0], "| with ReLU:", net(x, relu))
Expected output:
W2 @ W1 = [[5 3]]
[2 1] no activation: 13 | one neuron: 13 | with ReLU: 13
[1 0] no activation: 5 | one neuron: 5 | with ReLU: 5
[0 1] no activation: 3 | one neuron: 3 | with ReLU: 4
In code: a network that learns the circles
It is the same idea as the playground (a 2-6-1 network, ReLU and a sigmoid output), with plain gradient descent. The lines with dZ are backpropagation, explained in lesson 8.
import numpy as np
rng = np.random.default_rng(0)
# Data: a central group (class 0) surrounded by a ring (class 1)
n = 90
a0, r0 = rng.uniform(0, 2 * np.pi, n), np.sqrt(rng.uniform(0, 1, n)) * 1.15
a1, r1 = rng.uniform(0, 2 * np.pi, n), rng.uniform(1.95, 2.8, n)
X = np.vstack([np.c_[r0 * np.cos(a0), r0 * np.sin(a0)], np.c_[r1 * np.cos(a1), r1 * np.sin(a1)]])
X = (X + 0.12 * rng.normal(size=X.shape)) / 3 # coordinates in [-1, 1]
y = np.r_[np.zeros(n), np.ones(n)]
# Network 2 → 6 (ReLU) → 1 (sigmoid)
W1 = rng.normal(0, np.sqrt(2 / 2), (2, 6)); b1 = rng.uniform(-0.5, 0.5, 6)
W2 = rng.normal(0, np.sqrt(1 / 6), (6, 1)); b2 = np.zeros(1)
sig = lambda z: 1 / (1 + np.exp(-z))
for step in range(1500):
Z1 = X @ W1 + b1; H = np.maximum(0, Z1); p = sig(H @ W2 + b2).ravel() # forward pass
dZ2 = (p - y)[:, None] / len(y) # error at the output
dW2, db2 = H.T @ dZ2, dZ2.sum(0)
dZ1 = (dZ2 @ W2.T) * (Z1 > 0) # the blame flows back to the hidden layer
dW1, db1 = X.T @ dZ1, dZ1.sum(0)
for P, G in ((W1, dW1), (b1, db1), (W2, dW2), (b2, db2)):
P -= 0.5 * G # gradient descent
print("accuracy:", ((p > 0.5) == y).mean())
Expected output: accuracy: 1.0. With 6 neurons it gave 1.0 on all ten seeds tried (0 to 9); with 3 neurons, between 0.81 and 1.0; with 2, between 0.82 and 0.89 (NumPy’s random numbers may change between versions). These are hits on the same points used for training: being right on new data is a different question (lesson 10). The lesson’s playground uses the Adam optimizer instead of plain descent (lesson 9).
What comes next
Computing the gradient of every weight in a network like this is backpropagation (lesson 8). How to train well —batches, optimizers— is lesson 9, and lesson 10 shows that being right on the training points, as here, does not guarantee being right on new data.
Decision lens
What this idea means if your job is to decide, not to code.
- “More layers” is not a quality measure: each layer adds cost to train and to run. The playground’s accuracy is measured on the same points used for training; ask for a comparison with a simple model on data that neither saw, before accepting that depth is justified.
- The universal approximation theorem guarantees that a network exists, not that it works in your case: it does not say how much data, compute, or how many neurons are needed. If someone invokes it to sell a solution, ask for evidence on your problem.
- Training is sensitive to the starting point: the same recipe with another seed can give different results (try it in the playground with “Reset” and few neurons). Ask for the training to be repeated and the variability reported, not just the best run.
- Size is cost: GPT-3 has ninety-six layers and one hundred seventy-five billion parameters. When they talk about a “deep network,” ask for the parameter count and the cost per task (lessons 24 and 26).
Terms in this lesson
- Layer A group of neurons that receive the same inputs and compute at the same time. A network is a chain of layers: input, one or more hidden ones, and output.
- Forward pass Computing a network’s output: the numbers move on layer by layer, from input to output.
- ReLU Rectified linear unit: an activation function that returns zero if the sum is negative and the sum itself if it is positive, max(0, z). A hinge with a single corner.
- Nonlinearity The property of a function that is not a straight line. It stops stacked layers from collapsing into one and lets a network fold space.
- Universal approximation Theorem: a network with one hidden layer and enough neurons can approximate any continuous function on a closed, bounded set, to any desired precision. It does not say how many neurons are needed nor that training will find them.
- Deep network A network with several hidden layers. Each layer builds on what the previous one already transformed; for certain functions, this reaches complex shapes with far fewer neurons than a single wide layer.
- Artificial neuron A unit of computation that multiplies each input by a weight, adds the results, adds a bias, and applies an activation function: y = f(w·x + b).
- Activation function A function applied to the weighted sum plus the bias to produce the neuron’s output. Examples: the step and the sigmoid.
- Sigmoid The function σ(z) = 1/(1 + e⁻ᶻ): it turns any number into a value between 0 and 1, and equals 0.5 when z = 0.
- Hidden layer A layer of neurons between input and output. It creates intermediate signals that the output combines; its values are not observed directly.
- Decision boundary The set of points where the neuron changes its answer. With two inputs it is a straight line: w₁x₁ + w₂x₂ + b = 0.
- Weight (w) In a linear model, the number that multiplies the input: the slope of the line. It tells how much the prediction rises for each unit the input grows.
- Bias (b) The term added at the end of the model: the prediction when the input is zero, that is, the height at which the line crosses the vertical axis. It is not the bias of data or of an unfair model, which is a different concept.
- Parameter Each of the numbers a model adjusts while training and in which it stores what it learned.
- Loss function A single number that summarizes how wrong a model is on its data. Training is the search for the parameters that make it as small as possible.
Full transcript
Sources
- Cybenko, G. (1989). Approximation by superpositions of a sigmoidal function
- Hornik, K., Stinchcombe, M., White, H. (1989). Multilayer feedforward networks are universal approximators
- Funahashi, K. (1989). On the approximate realization of continuous mappings by neural networks
- Hornik, K. (1991). Approximation capabilities of multilayer feedforward networks
- Leshno, M., Lin, V. Y., Pinkus, A., Schocken, S. (1993). Multilayer feedforward networks with a nonpolynomial activation function can approximate any function
- Telgarsky, M. (2016). Benefits of depth in neural networks
- Brown, T. B., et al. (2020). Language Models are Few-Shot Learners (GPT-3: 96 capas, 175 mil millones de parámetros; tabla 2.1)
- Hendrycks, D., Gimpel, K. (2016). Gaussian Error Linear Units (GELUs)
- Devlin, J., Chang, M.-W., Lee, K., Toutanova, K. (2019). BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (usa la GELU en lugar de la ReLU)
- Kingma, D. P., Ba, J. (2015). Adam: A Method for Stochastic Optimization
CommentsThis lesson’s public conversation: questions, facts to check, ideas.
Comments live in GitHub Discussions, in the course’s public repository; writing one requires a GitHub account. They load from giscus.app when you open this section. The course reviewers read them, and if a change is accepted, it is applied in both languages. Open the thread on GitHub