Skip to content

Analytic or empirical

anyinit.initialize(model, "analytic", (32, 3, 224, 224))  # no data, no forward pass
anyinit.initialize(model, "empirical", batch)  # no assumptions

analytic (the default) propagates moments through the graph without running the model; input_spec contributes shapes and nothing else. It is deterministic, data-free, and takes milliseconds.

empirical pushes real batches through, measures what arrives, and corrects layer by layer in topological order, so each layer is exact given everything upstream.

Both share the graph, the layer adapters and the target, so switching changes the method, not the goal. Start with analytic; reach for empirical when the report warns about the analytic assumptions.

When the analytic mode is less accurate

Narrow layers with high-order activations. The analytic mode assumes pre-activations are Gaussian, which holds well at large width. E[relu(z)⁶] measures 2.6× the Gaussian prediction at width 256, but only 1.06× at width 4096. AnyInit detects heavy tails and corrects for them, and the validation reports what remains.

Rule of thumb: analytic is reliable for χ ≲ 1.2 at width ≥ 256.

One draw against the ensemble. The analytic mode predicts the average over random draws, and a model holds a single draw. For a 20-layer ReLU MLP, the final second moment (target 1) lands, across 16 seeds:

width analytic analytic, center=True empirical
128 0.11 – 2.25 0.78 – 1.22 1.00
512 0.58 – 1.51 0.98 – 1.03 1.00

center=True removes most of the spread; empirical removes all of it. Reproduce with python docs/experiments/draw_drift.py.

Residual blocks. Merges assume the branches are independent, which a branch and its skip connection are not quite. The error is modest, and empirical does not rely on it.

distribution="sinusoidal". Its rows are correlated, which the analytic recursion only approximates. The report flags it; use empirical.