Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Structured linear layers: 1×1 conv & ActNorm

The LU-parameterised invertible 1×1 convolution and data-dependent ActNorm — cheap log-dets that make deep flows trainable

03 — Structured linear layers: 1×1 conv & ActNorm

Notebooks 00–02 covered orthogonal mixers: rotations, which are volume-preserving (log⁡∣det⁡∣=0\log|\det| = 0). But the “between-coordinate” toolkit has two more members, both introduced by Glow Kingma & Dhariwal (2018), that are general linear maps — not orthogonal, so they carry a real log-det — yet keep that log-det cheap (O(d)O(d) instead of O(d3)O(d^3)) by construction:

Together with coupling layers, these are the repeating unit of a Glow step (ActNorm → 1×11\times1 conv → coupling). Here we build the two linear pieces with gauss_flows.

What you will see

1. The invertible 1×11\times1 convolution

A 1×11\times1 convolution applies the same linear map WW to the channel vector at every spatial location: yij=Wxijy_{ij} = W x_{ij}, W∈RC×CW\in\mathbb{R}^{C\times C}. It is the learnable generalisation of the fixed channel permutation that RealNVP used to shuffle coordinates between coupling layers — instead of a hard permutation, a soft, trainable mixing. gf.Invertible1x1Conv operates on one channel vector (C,)(C,); we vmap it across the spatial grid.

log_det (analytic, = sum log|s|) = +0.5000
sum(log_diag_u)                  = +0.5000
log|det W| (dense, O(d^3))       = +0.5000
round-trip = 2.2e-16

on an 8x8 map: total log-det = 32.000 = 0.500 x 64 pixels
<Figure size 1200x360 with 6 Axes>

The analytic log-det matches the dense log⁡∣det⁡W∣\log|\det W| exactly, and round-trip is machine-precision. Across the 8×88\times8 map the per-pixel log-det simply multiplies by the number of positions (64). Unlike a rotation, WW is a general linear map, so its log-det is non-zero — but reading it off the triangular factor’s diagonal costs O(d)O(d), not the O(d3)O(d^3) of a dense determinant.

2. Why LU: invertible by construction, cheap log-det

Two problems with learning a raw weight WW: (i) computing log⁡∣det⁡W∣\log|\det W| at every step is O(d3)O(d^3), and (ii) nothing keeps WW invertible — gradient steps can drive it singular, and notebook 02 §2 showed an unconstrained matrix drifting off the manifold entirely. The LU parameterisation W=LUW = LU fixes both: LL is unit-lower-triangular, UU is upper-triangular with diag(U)=exp⁡(log_diag_u)>0\mathrm{diag}(U) = \exp(\text{log\_diag\_u}) > 0, so WW is always invertible and log⁡∣det⁡W∣=∑ilog_diag_ui\log|\det W| = \sum_i \text{log\_diag\_u}_i is read straight off. We confirm it survives training intact, on an arbitrary objective.

after 300 training steps:
  analytic log_det = -2.2268   dense log|det W| = -2.2268  (match)
  round-trip       = 2.2e-16  (still exactly invertible)
  det W            = +0.1079  (never crossed 0)

The analytic and dense log-dets stay equal, the round-trip stays at machine precision, and det⁡W\det W never approaches 0: the LU form keeps the layer a valid bijector for free, the structured counterpart to the orthogonal parameterisations of notebook 01. That is the whole reason flows store linear layers factored rather than dense.

3. ActNorm — data-dependent affine

ActNorm is the simplest structured layer: a per-channel affine y=(x−b) / sy = (x - b)\,/\,s with learnable location bb and positive scale s=softplus(log_scale)+10−5s = \mathrm{softplus}(\text{log\_scale}) + 10^{-5}. Its log-det is −∑clog⁡sc-\sum_c \log s_c (times the number of spatial positions for an image). The trick that gives it its name is the data-dependent initialisation: set bb and ss from the first batch’s per-channel mean and std, so the layer’s output starts standardised — zero mean, unit variance per channel. That conditioning is what lets very deep stacks train without the activations exploding or collapsing.

gauss_flows exposes the parameters but not a from_data factory (unlike FixedRotation.from_data), so we write the three-line init ourselves.

per-channel statistics of the output:
  default init : mean [ 7.05 -2.88  0.04  1.4 ]  std [4.3  0.71 2.89 1.46]
  data init    : mean [ 0.  0.  0. -0.]  std [1. 1. 1. 1.]
<Figure size 1100x400 with 2 Axes>

The default ActNorm (with log_scale = 0) just divides every channel by softplus(0)≈0.69\mathrm{softplus}(0)\approx0.69 — it ignores the data’s wildly different per-channel scales and offsets. The data-initialised ActNorm pins every channel to mean ≈0\approx 0, std ≈1\approx 1, so the next layer sees well-conditioned inputs. Stacked through a deep flow, this is the difference between a network that trains and one whose log-likelihood diverges in the first few steps.

4. How they fit together

A Glow “step” is exactly these pieces in sequence: ActNorm preconditions the activations, the 1×11\times1 conv mixes channels (replacing RealNVP’s fixed permutation), and a coupling layer (Part 5) does the expressive nonlinear work. All three have triangular or diagonal Jacobians, so their log-dets are O(d)O(d) and simply add (Part 0 composition). The orthogonal mixers of notebooks 00–02 slot into the same position as the 1×11\times1 conv — the choice is orthogonal (log-det 0, volume-preserving) versus general linear (log-det ∑log⁡∣s∣\sum\log|s|, can rescale).

Recap

layermaplog-detkept valid byAPI
rotation (nb 00–02)QxQx, orthogonal0orthogonal parameterisationgf.HouseholderRotation, …
1×11\times1 convWxWx, general linear$\sum\logs$
ActNorm(x−b)/s(x-b)/s, diagonal affine−∑log⁡s-\sum\log spositive scale, data initgf.ActNorm / ActNorm1D

Rotations re-frame without rescaling; the 1×11\times1 conv adds learnable rescaling with a cheap log-det; ActNorm adds the data-dependent conditioning that makes depth trainable. That completes the between-coordinate toolkit.

Next up — Part 3. With marginal transforms (Part 1) and orthogonal/linear mixers (Part 2) in hand, we can assemble the classic algorithm that alternates them to convergence: Rotation-Based Iterative Gaussianization (RBIG) — the non-parametric loop marginal → rotate → marginal → rotate … that drives a distribution to N(0,I)\mathcal{N}(0,I), with negentropy as its stopping signal.

References
  1. Kingma, D. P., & Dhariwal, P. (2018). Glow: Generative Flow with Invertible 1x1 Convolutions. Advances in Neural Information Processing Systems (NeurIPS).