Math for AI course · Lesson 38 of 180
Linear Algebra in a Tiny Neural Network
Trace every shape, bias, activation, and rank change through a two-layer network with a worked NumPy example and an interactive explorer.
A neural network can look like a string of matrix operations, yet each step changes what the numbers mean. Following one small network from input to output reveals the whole route: matrix shapes determine which maps can connect, biases translate those maps, rank limits independent directions, and an activation changes what the composition can express.
By the end, you will be able to trace each shape and calculate a two-layer network by hand or in NumPy, then explain where its bias, rank, and activation affect the result.
This lesson brings together three earlier tools: solving linear systems without explicitly inverting a matrix, using kernel and image to describe lost and reachable directions, and using bias to translate an affine map. Chapter 2 of Mathematics for Machine Learning supplies the linear algebra behind the synthesis. The network, numbers, code, visual, and assessments below are original.
Follow the dimensions through two affine layers
Here, “two-layer network” means two learned affine maps with a hidden activation between them. We will keep the output as two scores; no probability or class decision is applied. Let the input be a column vector . Each affine map combines a matrix with a bias vector:
The shared dimension between adjacent maps must match: has two columns for the two input features, and two rows for its hidden outputs. Then accepts those two hidden values and returns two output scores. The bias is added once to each hidden coordinate, and once to each output. A matrix with incompatible dimensions cannot perform the stated mapping; this is the same shape check that NumPy’s matrix product applies.
- Input · 2 features
- Affine map · 2 hidden values
- Hidden activation
- Affine map · 2 scores
- Output · 2 scores
z = W₁x + b₁
h = σ(z)
y = W₂h + b₂
- Preactivation z
- (, )
- Hidden output h
- (, )
- Scores y
- (, )
- Active hidden units
- Local Jacobian rank
A preactivation is exactly zero, where ReLU has a kink. The Jacobian is not defined at that point; inspect either neighboring region to see its local rank.
Initial input is 1, 1; hidden output is 0, 0.5; scores are 1.5, −0.5.
The starting values in the figure use these fixed, hand-chosen parameters:
The example is small enough to follow entry by entry. Its values are chosen to show one hidden unit turning off under ReLU; they are not trained parameters or a claim about a typical model.
Compute one prediction, keeping every intermediate
Take . The first matrix combines the two input coordinates in different ways. Adding the bias shifts each result:
NumPy’s @ operator performs matrix multiplication. The + b operations below
use NumPy’s elementwise broadcasting to add a length-two bias to a length-two
result. This small implementation prints the actual intermediate vectors:
import numpy as np
W1 = np.array([[1.0, -1.0], [1.0, 1.0]]) # (2, 2)
b1 = np.array([-0.5, -1.5]) # (2,)
W2 = np.array([[1.0, 2.0], [-1.0, 1.0]]) # (2, 2)
b2 = np.array([0.5, -1.0]) # (2,)
x = np.array([1.0, 1.0]) # (2,)
z = W1 @ x + b1 # (2,) = (2, 2) @ (2,) + (2,)
h = np.maximum(z, 0.0) # (2,), elementwise ReLU
y = W2 @ h + b2 # (2,) = (2, 2) @ (2,) + (2,)
print('z:', z) # [-0.5 0.5]
print('h:', h) # [0. 0.5]
print('y:', y) # [ 1.5 -0.5]
The same width logic applies to a batch. If examples are stored as rows,
their array has shape ; multiply on the right by to
produce hidden values, and then by to produce
scores. PyTorch’s Linear layer uses that row-oriented convention: its weight
shape is and it applies
. A Linear(2, 2) therefore stores a weight and a
length-two bias. PyTorch’s ReLU is applied elementwise and preserves the input
shape, matching the step used above (Linear docs,
ReLU docs,
NumPy matmul docs).
Without an activation, two layers are still one affine map
The bias in an affine layer is a translation. If the hidden step is the identity, the two layers compose by substitution:
So stacking more affine maps without a nonlinear activation cannot turn the overall input-output rule into a nonlinear one; the matrices multiply into a single matrix, and the biases combine into one offset. For our chosen values, and . The identity version therefore maps to .
The rank of a matrix counts its independent output directions. In this identity example both and have rank two, and their product also has rank two. In a network whose hidden width is , the linear part of an affine composition cannot have rank greater than , since it factors through only coordinates. If either matrix has lower rank, the composition’s rank can be lower still. These are upper bounds: a narrow layer is a possible bottleneck, but width alone does not guarantee a particular rank.
ReLU makes the map piecewise affine
ReLU changes a hidden coordinate to zero when its preactivation is negative. For any region where the signs of all preactivations stay fixed, the set of active units is fixed too. Let be a diagonal matrix with a for each active ReLU unit and a for each inactive one. Within that region, the local linear part of the two-layer network is
For the worked input, , so . Then
Near this input, both output scores change with the same input combination ; the difference direction has no effect while the first unit remains inactive. The matrix describes local changes inside this activation region, not one global matrix for the entire network. On a ReLU boundary where a preactivation equals zero, the function has a kink and no single region’s Jacobian describes both sides.
The hidden width and weights also constrain what the network can express. In this particular example, the two preactivation-zero lines partition the input plane into regions with different active-unit patterns; each region has an affine rule, and crossing a line can change that rule. More generally, adding a nonlinear activation makes nonlinear functions possible, but does not make every choice of weights expressive. A hidden unit may remain off for the inputs of interest, or the matrices may collapse directions. The matrix shapes, their ranks, the bias offsets, and the activation pattern all contribute to the behavior.
That is why the output values alone are a thin debugging signal. Trace shapes to catch incompatible connections, compare and to see which features were gated, and inspect the layer ranks or local Jacobian to identify lost directions. When a separate fitting step asks you to solve , Lesson 025 explains why a numerical solver avoids the hazards of forming . A network forward pass itself uses matrix products; it does not require inverting its learned weights.
Once the maps and their directions are clear, the next question is how large a vector is. Lesson 039 introduces norms to measure vector magnitude, compare embedding scales, and describe parameter penalties.
Check your understanding
Question 1
For the network in this lesson, state the shapes of x, W₁, b₁, z, h, W₂, b₂, and y. Why can W₂ accept h?
Show the step-by-step solution
has shape , is , is , and and are each . The second matrix is with bias of shape , producing of shape . The inner dimension of is two, which matches the two entries in ; the matrix therefore maps the hidden vector to two output scores.
Question 2
With x = (1, 1)ᵀ, calculate z, h, and y using the lesson’s matrices and ReLU. Show the bias and activation steps.
Show the step-by-step solution
First , so adding gives . Applying ReLU coordinate by coordinate gives . Next ; adding gives .
Question 3
Why does removing the hidden activation leave an affine map? Find its combined matrix and bias for this example.
Show the step-by-step solution
Substitute the first affine rule into the second: . Here multiplication gives . Also , so adding yields the combined bias . The result is one affine map because it still has the form .
Question 4
For x = (1, 1)ᵀ, what output does the identity-hidden-step version produce? How does it compare with the ReLU result?
Show the step-by-step solution
With the identity step, use the combined map from the previous solution: . With ReLU the output is because the first hidden preactivation is negative and becomes zero, while the second stays . The difference comes from that coordinatewise activation.
Question 5
A network maps 5 inputs through a hidden layer of width 3 to 4 outputs, with no activation. What is the largest possible rank of its linear part? What if the first weight matrix has rank 2 and the second has rank 3?
Show the step-by-step solution
The composed matrix factors through three hidden coordinates, so its rank is at most three. It cannot exceed the input dimension five or output dimension four either. If the first matrix has rank two and the second rank three, the product rank is at most the smallest of those bounds, which is two. These are upper limits; the actual product could have still lower rank if the directions are misaligned.
Question 6
At the worked input, the first ReLU unit is off and the second is on. Calculate the local Jacobian rank and explain its meaning.
Show the step-by-step solution
The activation mask is . Multiplying gives . Its second column is equal to its first, so it has one independent column and rank one. Within this activation region, small input changes along one direction do not change the output; both scores depend on the same input combination. This is a local statement because a ReLU switch changes the matrix .
Question 7
What changes when a ReLU preactivation is exactly zero? Can one use either neighboring region’s Jacobian as the single derivative there?
Show the step-by-step solution
ReLU has a corner at zero: its slope is zero just to the left and one just to the right. At an exactly zero preactivation, the function is not differentiable in that coordinate, so there is no single ordinary Jacobian that describes both sides. The network output is still defined; it is the one local linear approximation across the boundary that fails.
Question 8
A batch has 8 examples with 4 features each. What are the input and output shapes for PyTorch Linear(4, 3), and what is the weight shape?
Show the step-by-step solution
The batch input is , with eight rows and four input features. PyTorch stores the layer weight with shape so its weight is and its bias has shape . The layer returns , preserving the batch dimension and replacing the final feature dimension with three outputs.