Proposition 1I.12.P0140 of 100 in the corpus
An autoencoder is supervised learning whose target is its own input.
Reconstruction turns unlabelled data into a regression problem. The loss alone does not ask for a representation: without a constraint the best answer is to copy, and the constraint decides what is learned.
The label was there all along
Chapters I.2 to I.11 fitted a function to pairs of an input and a label. An autoencoder is fitted to the inputs alone. It composes two maps, an encoder and a decoder , and is trained so that the output reproduces the input:
A regression problem in which every example is its own target.
The vector is the code, is the reconstruction, and collects the parameters of both maps. Nothing in (I.12.1) is new machinery. It is the regression loss of I.4 with the target set equal to the input. Its gradient comes from the backward pass of I.6, and the optimisers of I.7 follow it.
What changes is where the interest lies. In regression the output is the product. Here the output is known before training starts, and the product is the intermediate vector .
The loss is still a likelihood. By I.4, squared error is the negative log-likelihood of a Gaussian of fixed variance centred on , up to constants. For inputs in a sigmoid output with binary cross-entropy is the Bernoulli counterpart. The choice states which errors the model may ignore. It does not change the argument below.
What stops it copying?
Suppose and both maps are unrestricted. Then and can each be the identity, the loss is exactly zero, and the code is the input. Zero is the best value the loss can take, and reaching it this way has taught the network nothing. I.12.X04 builds such a pair and shows it reconstructs points far from the data just as exactly.
So an autoencoder is defined by what prevents the copy. The oldest device is a bottleneck: choose . Every reconstruction is then for some , so it lies in the image of the decoder,
Call the reconstruction surface. Its points are indexed by numbers: a curve when , a surface when . This gives the picture to keep. The decoder draws a surface in input space. The encoder chooses, for each input, a point on it. The loss is the mean squared distance between the inputs and their chosen points.
When the decoder is linear, is a subspace of dimension at most . The end-to-end map then has rank at most (Rank, eigenvalues and the singular value decomposition 0.LA.04), and at least directions of the input are sent to zero. Two inputs that differ along one of them receive the same code. This is the discarded subspace of I.5.X04, now chosen on purpose.
The bottleneck does not say which surface. The loss does, and the next proposition finds the answer exactly for linear maps.
The width bounds the dimension of the surface. It does not bound how far the surface can bend. A decoder with enough freedom can thread a curve through every training point, and I.12.B04 does so with a single code number.
The data enter through one matrix
Take the linear case, where every step can be written out. Let and with and . Stack the examples as the rows of . The codes are , of shape , and the reconstructions are , of shape .
Write for the second-moment matrix, which is the covariance when the data are centred (Variance and covariance 0.PR.03). For one example the squared error is a trace,
and averaging over the examples replaces by :
The data enter only through S, and each half's gradient passes through the other half.
To derive the gradients, write for the end-to-end map. A change changes the loss by , because the two terms of the product rule are transposes of each other and is symmetric. So . The chain rule for a matrix product (The chain rule for matrix products 0.MC.07) gives and . The shapes are and , as they must be.
The first line of (I.12.2) says that a linear autoencoder sees its data only through . Two datasets with the same second-moment matrix give it the same loss surface.
One backward pass through both halves
The same gradients appear when (I.12.1) is differentiated one example at a time, as in I.6. The output error is . The decoder’s gradient is . The error passes back through the decoder as , and the encoder’s gradient is . Averaging over the data returns (I.12.2).
Two consequences follow from the order of the factors.
The encoder learns only through the decoder. Its gradient begins with , so a decoder that cannot yet express the residual passes nothing back. In I.12.X02 the encoder’s first gradient is exactly zero while the decoder’s is not. In the extreme case and both gradients vanish, and the loss stays at for ever.
A tied autoencoder sets . One matrix then plays two roles, and by the accumulation rule of I.6 its gradient is the sum of both:
The term with is the encoder’s role and the term with is the decoder’s, transposed into the shape of . Dropping either is the shared-weight error of I.9 and I.11 in a new place.
With a nonlinearity in the code, and , the backward pass gains one factor: the error entering the encoder is . Nothing else changes.
What the hourglass costs
A one-hidden-layer autoencoder with biases has parameters, or with tied weights. For and these are and . One forward pass costs multiply-accumulates. I.12.B05 counts a deeper dense stack and a convolutional one.
Two counts deserve suspicion.
The code is real numbers, which is a count of coordinates and not of information. One real number can index every example of a finite training set. The bottleneck constrains only together with the limited flexibility of and .
The reduction is part of the loss, as in I.4. Equation (I.12.1) sums over the coordinates and averages over the examples. A library default that averages over all numbers divides the loss and its gradient by . Alone that rescales the learning rate. Next to a penalty with its own coefficient it changes the balance by a factor of , which is for a image.
A pass small enough to inspect
The chapter uses one dataset throughout: the four points , , and . They are centred, and . This script runs a width-one autoencoder that keeps the first coordinate, one example at a time:
X = [(1, 2), (2.2, 0.4), (-1, -2), (-2.2, -0.4)]
E, D = [1.0, 0.0], [1.0, 0.0] # one encoder row, one decoder column
loss, gE, gD = 0.0, [0.0, 0.0], [0.0, 0.0]
for x in X:
z = E[0]*x[0] + E[1]*x[1] # code
xhat = [D[0]*z, D[1]*z] # reconstruction
delta = [2*(xhat[j] - x[j])/len(X) for j in range(2)]
loss += sum((xhat[j] - x[j])**2 for j in range(2))/len(X)
back = D[0]*delta[0] + D[1]*delta[1] # through the decoder
for j in range(2):
gD[j] += delta[j]*z
gE[j] += back*x[j]
print(round(loss, 6), [round(g, 6) for g in gD], [round(g, 6) for g in gE])
It prints 2.08 [0.0, -2.88] [0.0, 0.0]. The loss is the
variance of the coordinate that was dropped. The decoder is told to start
using its second weight. The encoder is told nothing yet.
I.12.B01 continues
from here, and its script checks (I.12.2) against central finite
differences for untied and tied weights.
Sources
Depends on
Used by
Problems using this
- I.12.B01 — Keep one coordinate, then repair each halfnumeric▲△△
- I.12.B04 — A width-one code that memorisescounterexample▲▲△
- I.12.B05 — Count the code before calling it a bottleneckshape▲▲△
- I.12.X02 — The encoder waits for the decodergradient▲△△
- I.12.X04 — As wide as the input, and nothing learnedcounterexample▲△△
- I.BOOK.B05 — A zero training loss that taught nothingcounterexample▲▲△
- I.BOOK.B06 — Shapes through a convolutional VAEshape▲▲△