Skip to main content

Latent space and inverse

The flow maps every input to a latent vector with one coordinate per input column. The first n_components coordinates are the layout. The rest are the residual, which holds what the layout does not.

Z = model.transform_latent(X) # (n, D), layout first, then the residual
X_back = model.inverse_latent(Z) # (n, d), the input again

Exact round trip​

inverse_latent undoes transform_latent up to float precision. roundtrip_ reports the largest absolute error of that round trip on the training data after fitting, typically between 1e-6 and 1e-4 in whitened units.

inverse_latent accepts any latent vector, not only those of real points. For inputs without padding, editing the residual of a point while keeping its layout coordinates gives another input that the model places at the same position.

Decoding a position​

X_rep = model.inverse_transform(Y) # Y has n_components columns

inverse_transform decodes positions of the layout, with the residual set to zero. The result is one representative input for each position. It is not the mean of the inputs placed there, and many different inputs map to the same position. conditional_spread measures how different they are.

Why the inverse is exact​

Every layer of the flow is an affine coupling. It changes some coordinates by a scale and a shift computed from the others, which pass through unchanged, so each layer can be undone exactly, and so can the whole flow. The PCA whitening in front of it is an invertible linear map.