Every construction in this course shares a requirement that has gone undiscussed: it passes through the origin. A subspace contains by definition, a linear map satisfies , and the column space of a matrix is the set of outputs reachable from a starting . This lesson lifts that restriction, which is what separates the framework built so far from an actual dense layer.
Translated subspaces
Let be a vector space, a subspace and a point. The set
is an affine space with direction space and support point . Its dimension is that of . An affine line corresponds to and an affine hyperplane to .
import numpy as np
x0 = np.array([1., 2.])
d = np.array([2., 1.])
L = x0 + np.outer(np.linspace(0, 1, 5), d)
Two observations delimit the object. The first is that is not a subspace except in one case: it contains if and only if , that is, if and only if , and then . An affine space not passing through the origin is closed under neither addition nor scalar multiplication, so none of the tools of the preceding lessons applies to it directly.
The second is that the support point is not determined by . If , then with , and
because . Any point of serves as support; the direction space, by contrast, is unique. The support is a choice of representation, not a property of the set.
The affine combination
The description above depends on a point chosen by hand. An intrinsic characterisation exists. Given and scalars , the expression is an affine combination when
The restriction is exactly what is required for the result not to depend on the origin. Translating every point by the same translates the combination by : it moves with the data instead of deforming. Without the restriction, translation introduces an arbitrary factor .
If in addition all weights are non-negative, the combination is called convex and the set of all of them is the convex hull of the points.
Two weights are free; the third is fixed by the sum. A vertex is reached at weight 1.
λ₃ = 1 − λ₁ − λ₂ = 0.30
λ₁ + λ₂ + λ₃ = 1.00
convex combination: inside the hull
Softmax weights are non-negative and sum to one: the attention output never leaves the hull.
The distinction is not a technicality. The attention mechanism computes with weights produced by a softmax, which are positive and sum to one by construction. The output of an attention head is therefore a convex combination of the value vectors, and is confined to their convex hull: it cannot produce anything outside the hull the available values form. The interpolation between examples used by the mixup augmentation technique is likewise a convex combination of two points, and moving to negative weights —permitted by the affine definition, forbidden by the convex one— is exactly what would take it off the segment joining the examples.
The solution set, once more
The lesson on the particular and general solution established that the solution set of is , and the lesson on the image and the kernel placed it inside the orthogonal decomposition of the domain. The object now has a name: it is an affine space with direction and dimension .
from scipy.linalg import null_space
A = np.array([[1., 1., 1.]])
b = np.array([6.])
x0, *_ = np.linalg.lstsq(A, b, rcond=None) # one concrete support
U = null_space(A) # the direction, 3 × 2
The support lstsq returns is the minimum-norm one, as seen in the lesson on the image and the kernel, but any other solution describes the same set. That the homogeneous system yields a subspace and the inhomogeneous one an affine space is the same distinction this lesson opens with: is what anchors the set to the origin.
The hyperplane and the margin
An affine hyperplane in admits a description by a single equation:
with . The vector is normal to the hyperplane —if and belong to , subtracting the two equations gives — and controls the displacement from the origin.
Drag the normal w or the point x; slide the offset b.
wᵀx + b = 4.00 · positive side
distance = |wᵀx + b| / ‖w‖ = 1.79
The quantity is not a distance, and the difference matters. For any , the component of along the unit normal is
where the last equality uses . The result does not depend on the chosen, and its absolute value is the distance from to . The sign gives the half-space.
The practical consequence runs as follows: replacing by leaves the hyperplane untouched —the equation defines the same set— but doubles every score. In a logistic regression, where the probability is , this means the confidence of the model can grow without the decision boundary moving at all. The magnitude of the logit conflates two different things: how far from the boundary the point lies, and how large has been allowed to become. Only the first is a property of the geometry of the problem, and it is the reason a penalty on the norm of the weights affects the calibration of the probabilities without necessarily altering the predictions.
The same scaling explains the formulation of the support vector machine. Fixing the normalisation on the closest examples, the separation between the two resulting hyperplanes is
so that maximising the margin is equivalent to minimising . The geometric problem and the optimisation problem are the same one written twice.
The affine map and the bias
An affine map between vector spaces is the composition of a linear one with a translation:
This is the exact definition of a dense layer. The term is the bias, and its geometric role is that of a support point: without it, and every decision boundary would be forced through the origin of feature space.
A = np.random.randn(3, 2)
a = np.random.randn(3)
def layer(x):
return A @ x + a # exactly nn.Linear(2, 3)
An affine map does not preserve arbitrary linear combinations, but it does preserve affine ones. The verification is immediate, and the restriction is precisely what makes it work:
As a corollary, a dense layer maps convex hulls to convex hulls: the image of the hull is the hull of the images.
One consequence remains, and it qualifies an earlier result. The composition of two affine maps is affine:
The lesson on linear maps showed that a network without activation functions collapses into a single matrix. The identity above closes the one loophole that remained: adding biases does not prevent it. A stack of dense layers without activations collapses into a single dense layer, with matrix and an accumulated bias. The bias supplies the displacement from the origin, which is indispensable, but it supplies no expressive power: the non-linearity has to come from somewhere else.
The route taken
The course began by solving and ends by describing precisely what a dense layer is. Between those two points the objects appeared out of necessity: elimination in order to solve, the factors in order not to repeat the work, rank in order to know how much information a matrix really holds, the basis in order to choose the representation, eigenvalues in order to find the best one, and the kernel in order to know what is lost along the way. The layer contains all of it except , and what sits inside the parentheses is no longer opaque.
Exercise. Generate two separable point clouds in and fit a logistic regression with scikit-learn. Extract coef_ and intercept_, draw the hyperplane and check that the signed distances carry the correct sign in each class. Repeat the fit with C ten times larger and verify that grows while the boundary barely moves.