Yvinec, Dapogny, Cord & Bailly (Sorbonne / Datakalab), 2023

PowerQuant: Automorphism Search
for Non-Uniform Quantization

Compress a neural network to 4 bits without ever touching the training data — by replacing the usual evenly-spaced quantization grid with a single learned power function x→xa, the only non-uniform map that keeps integer multiplication intact.

Prerequisites: Uniform quantization + basic group theory intuition
11
Chapters
7
Simulations

Chapter 0: The Problem

You trained a beautiful ResNet-50. It hits 76% top-1 on ImageNet. Now your boss wants it on a phone, a security camera, a tiny edge chip — and it has to run fast and cool. The 32-bit floating-point weights are too big and too slow. The fix is quantization: store each weight in 8, or even 4, bits instead of 32. A 4-bit model is 8× smaller and runs integer arithmetic, which silicon loves.

But here is the twist that defines this paper. You are not allowed to look at the training data. Privacy regulations, medical records, proprietary datasets, security audits — in the real world the model often ships to a team that never had, and never will have, the data it was trained on. This is the data-free setting: you must compress the network using only the weights themselves.

The core question: Given only a trained network's weights — no training data, no fine-tuning, no labels — how do we squeeze them down to 4 bits while losing as little accuracy as possible?

Why this is genuinely hard

Quantization throws away information. At 8 bits you have 256 distinct values to represent every weight in a layer; at 4 bits you have just 16. The whole game is choosing which 16 values, and how to map every real weight onto the nearest one. A bad choice and your 76% network collapses to 54%. A good choice and it stays at 70%. The difference is entirely in the quantization grid.

The standard answer — uniform quantization — places those 16 values at evenly-spaced intervals. It is simple, hardware-friendly, and... ill-suited to how neural-network weights actually look. That mismatch is the seam PowerQuant pries open.

A worked sense of the stakes

SettingLevels/weightResNet-50 top-1What it buys
Full precision (FP32)~4 billion76.15%baseline, but big & slow
Uniform W8/A825676.15%4× smaller, lossless
Uniform W4/A41654.68%8× smaller, brutal accuracy hit
PowerQuant W4/A41670.29%same size, +15.6 points recovered

That last row is the entire paper in one line. Same 16 levels. Same data-free constraint. +15.6 accuracy points, just by choosing a smarter shape for the grid. By the end of this lesson you will know exactly where those 15 points come from and be able to derive the method on a whiteboard.

What makes the "data-free" quantization setting harder than ordinary quantization?

Chapter 1: The Key Insight

Two ideas were already on the table when this paper landed. Uniform quantization: evenly-spaced levels, maps multiply-to-multiply (hardware loves it), but a poor fit to bell-shaped weights. Logarithmic quantization: levels bunched near zero (great fit to bell-shaped weights!), but it secretly turns multiplications into bit-shifts — which need special hardware and break on most chips.

PowerQuant asks a sharper question. What is the full space of non-uniform grids that keep multiplication as multiplication? If we never leave that space, we get the accuracy benefit of non-uniformity AND the hardware compatibility of uniform — no bit-shifts, no lookup tables.

The insight: "A grid that preserves multiplication" is a precise algebraic statement. We want a map Q with an inverse such that Q(x)×Q(y) = Q(x×y). That is the definition of a group automorphism of the positive reals under multiplication. And a 150-year-old theorem says these automorphisms are exactly the power functions x→xa. So the entire search collapses to finding one number: the exponent a.

The three-word fix

Each piece of "search over automorphisms" solves a specific failure of the alternatives:

non-uniform
Bunch quantization levels where the weights actually live (near zero) instead of spreading them evenly — escape the uniform-grid mismatch.
automorphism
Restrict to maps that preserve multiplication, so integer multiply stays integer multiply — escape the bit-shift / LUT hardware trap of log-quant.
single exponent a
The whole family is x→xa, so calibration is a 1-D optimization — fast, data-free, provably has a unique optimum.

What the whole method is, in one breath

PowerQuant is: pick exponent a by minimizing the per-layer reconstruction error (no data needed) → transform each weight by w→sign(w)·|w|a → quantize that with a uniform grid → at inference, raise activations to the power a, multiply in integers as usual, then undo the power. We will build every one of those pieces from scratch and watch the actual numbers flow.

Why does logarithmic quantization, despite fitting weight distributions well, struggle to deploy?

Chapter 2: Uniform Quantization, From Scratch

Before we can improve on uniform quantization we have to be able to do it by hand. Let's quantize a real weight tensor to b bits, symmetrically (signed, centered on zero — what the paper uses for weights).

The recipe has three numbers: a scale (how big one integer step is, in real units), the rounded integer code, and the reconstructed de-quantized value.

The symmetric uniform map, defined

Let W be the weight tensor and b the bit-width. A signed b-bit integer ranges over [−(2b−1−1), 2b−1−1]. For b=4 that is [−7, 7] — 15 usable levels.

s = max|W| / (2b−1 − 1)     Wint = round(W / s)     Ŵ = s · Wint

Where s is the scale — think of it as "real-world meters per integer tick." max|W| is the largest-magnitude weight (it defines the range we must cover). Wint is the stored integer code. ("W-hat") is what you get back when you de-quantize — almost certainly not equal to the original W, and that gap is the error we fight all lesson.

Worked example (do this on paper). Take a weight w = 0.012 in a layer whose largest weight is max|W| = 0.8, quantized to b=4 bits. Scale s = 0.8 / 7 = 0.1143. Code = round(0.012 / 0.1143) = round(0.105) = 0. De-quantized ŵ = 0.1143 × 0 = 0. Our small weight got crushed to exactly zero — an error of 0.012, which is the entire value. Hold that thought: it is the failure mode PowerQuant attacks.

See it: drag the scale, watch a weight snap to its grid

Below is a single layer's worth of weights (a Gaussian, like real networks). The horizontal ticks are the 15 uniform levels for 4-bit. Drag the highlighted weight — watch which level it snaps to and how the reconstruction error changes. Notice how lonely the levels are out in the tails and how starved they are at the peak.

Uniform Quantization Grid — Drag the Weight
drag the orange weight
In symmetric uniform quantization, what does the scale s represent?

Chapter 3: The Mismatch — Why Uniform Hurts

You just felt the problem in the last simulation. Neural-network weights are not spread uniformly. Layer after layer, they pile up into a sharp bell shape centered at zero: a huge mass of tiny weights, a thin tail of large ones. Uniform quantization spends its precious 16 levels evenly across the whole range — so the tails, where almost no weights live, get just as many levels as the dense peak.

That is exactly backwards. The peak is where most of the action is. Crushing a thousand small weights to a coarse grid does far more total damage than mis-rounding a handful of large outliers.

The big reveal. Quantization error is not democratic. If a layer has 90% of its weights in [−0.1, 0.1] but your grid covers [−0.8, 0.8] uniformly, then 90% of your weights share only ~12% of the available levels. You are pouring resolution into the empty tails. We want the opposite: fine resolution where the weights are dense.

Side-by-side: the same weights, two grids

Here is the comparison that motivates the entire method. Same Gaussian weights, same 4-bit budget. Left: a uniform grid. Right: a grid that bunches near zero (a power grid with a<1, previewing Chapter 5). Toggle the bit-width and watch the total reconstruction error. The power grid wins precisely because it puts its ticks where the histogram is tall.

Same Weights, Two Grids — Uniform vs Power
err: uniform — | power —
A counterintuitive finding the paper flags. Pruning lore says "small weights barely matter — zero them out." If that were true for quantization, you would want the coarse grid near zero (a>1). But empirically the best exponent is a≈0.55 < 1 — meaning the opposite: finely quantizing the small weights is what preserves accuracy. The authors argue the per-layer patterns live in the collective arrangement of many small weights, so you cannot treat them as disposable.
Why does a uniform grid waste resolution on bell-shaped weights?

Chapter 4: Automorphisms — The Algebra That Picks the Grid

So we want a non-uniform grid. But not any non-uniform grid — only ones that keep multiplication intact, because matrix multiply (integer multiply on real hardware) is the operation a network spends 99% of its time on. Let's make "keeps multiplication intact" precise, and watch it force our hand.

Manufacturing the requirement

Quantization is a map Q from real values to a discrete space, with a de-quantization inverse Q−1. For the quantized network to compute the same kind of arithmetic, we need: whatever the quantized values do under the quantized multiply, de-quantizing must recover the true product. Setting the quantized multiply to be ordinary multiplication ×, the requirement is:

Q(x) × Q(y) = Q(x × y)     for all x, y > 0

Read it slowly. "Quantize, then multiply" must equal "multiply, then quantize." A map that satisfies this — and is invertible (bijective, so Q−1 exists) — is by definition a group automorphism of (R*+, ×): the positive reals under multiplication. ("Automorphism" = a structure-preserving map from a set to itself. Here the structure being preserved is the multiplication.)

Lemma 1 (the whole space). The continuous automorphisms of (R*+, ×) are exactly the power functions Q : x → xa for a ∈ R. Nothing else qualifies. The infinite space of "multiplication-preserving grids" is a one-dimensional family parameterized by a single exponent.

Why power functions, derived in two lines

Here is the classic argument so it doesn't appear by magic. Take logs: let g(u) = ln Q(eu). The multiplicative law Q(xy)=Q(x)Q(y) becomes the additive law g(u+v) = g(u)+g(v) — Cauchy's functional equation. Its only continuous solutions are linear: g(u) = a·u. Undo the logs: ln Q(x) = a·ln x, so Q(x) = xa. The exponent a is the slope of the only line that fits — that is where our single free parameter comes from.

See it: turn the dial, watch the grid breathe

The map x→xa sends a uniform grid in the warped space back to a non-uniform grid in the original space. Drag the exponent a and watch where the levels land. a=1 is plain uniform; a<1 bunches levels near zero (fine for small weights); a>1 bunches them near the max.

Automorphism x→xa — Warp the Grid
a<1 → fine near zero
Why does requiring Q(x)×Q(y)=Q(x×y) collapse the search to power functions?

Chapter 5: PowerQuant — The Operator (SHOWCASE)

Now we assemble the full operator. The recipe is "warp, then quantize uniformly, then un-warp." Because the warp is |w|a, the only new ingredient over uniform quantization is raising magnitudes to a power.

The quantization operator, every symbol defined

Qa(W) = round [ (2b−1−1) · sign(W) · |W|a / max|W|a ]

Walk through it. |W|a — warp every magnitude by the power (this is the automorphism). max|W|a — the largest warped magnitude, used to normalize into [−1,1]. (2b−1−1) — scale up to fill the signed integer range (7 for 4-bit). sign(W) — store the sign separately so we can warp magnitudes safely (powers of negatives are trouble). round — snap to the nearest integer level.

And the de-quantization that recovers a real value (un-warp with the inverse power 1/a):

Qa−1(Wint) = sign(Wint) · ( |Wint| · max|W|a / (2b−1−1) )1/a
Worked example — rescue the crushed weight. Same layer as Chapter 2: w=0.012, max|W|=0.8, b=4, now with a=0.55. Warp: |w|a=0.0120.55=0.0826; max|W|a=0.80.55=0.884. Code = round(7 × 0.0826/0.884) = round(0.654) = 1. It is no longer crushed to 0 — it lands on level 1! De-quantize: ((1 × 0.884)/7)1/0.55 = (0.1263)1.818 = 0.0227. Error dropped from 0.012 (whole value lost) to 0.011 with the value preserved as nonzero — and crucially the relative ordering of small weights survives. Multiply that rescue across thousands of small weights and you get the +15 accuracy points.

SHOWCASE: the PowerQuant grid, fully interactive

This is the paper's Figure 2 made live. A layer of Gaussian weights (the histogram), the b-bit power grid drawn as vertical ticks, and a live reconstruction-error readout. Drag a to reshape the grid; toggle bits; change the weight distribution to a heavy-tailed one to see when a<1 stops helping. Find the a that minimizes the error — you are doing by hand what Nelder-Mead does in Chapter 6.

PowerQuant Grid (Figure 2, live) — Minimize the Error by Hand
reconstruction error: —
In Qa, why is the sign of each weight stored separately before warping?

Chapter 6: Finding a* — Data-Free Calibration

We have one knob, a. How do we set it without data? The paper's move: use the reconstruction error — how much the weights change when you quantize and de-quantize them — as a stand-in for accuracy loss. Weights are all we have, and weights are all this needs.

The objective, defined

ε(F, a) = ∑l=1..L ‖ Wl − Qa−1(Qa(Wl)) ‖p

Symbol by symbol: F is the network, L its number of layers, Wl the weights of layer l. The inner term is the original weights minus the round-tripped (quantized then de-quantized) weights — the per-weight damage. ‖·‖p is the Lp norm (the paper uses p=2, ordinary Euclidean length). Sum over all layers. We pick a* = argmina ε(F,a).

Why this works (the leap of faith, justified). There is no data, so we cannot measure accuracy. But the paper shows reconstruction error and true accuracy are strongly anti-correlated: minimize the weight damage and accuracy follows. Even better, they prove the objective is locally convex with a unique minimum — so a simple solver can't get stuck. That's why a 1950s optimizer (Nelder-Mead) is enough; no gradients needed (and the rounding makes gradients zero almost everywhere anyway).

Nelder-Mead: optimization without derivatives

Nelder-Mead is a derivative-free simplex search. In 1-D it just keeps a bracket of points, evaluates the error, and reflects/contracts toward the minimum — perfect here because round makes the gradient zero (or undefined) almost everywhere. It typically converges in a handful of evaluations.

See it: watch the solver hunt for a*

The blue curve is reconstruction error ε(a) over the real network's weights; the faint orange curve is the (hidden, data-needing) accuracy — note they bottom/peak at the same place. Press Step to advance the search one probe at a time, or Run to animate it converging. Change the bit-width and the optimum a* shifts — which is exactly why the paper re-optimizes a per network and per bit-width.

Nelder-Mead Search for a* — Watch It Converge
a* = — | err = —
Why can PowerQuant calibrate the exponent without any training data?

Chapter 7: Inference — Keeping Integer Multiply Intact

Here is the payoff of choosing automorphisms. At inference time, the quantized layer must still be ordinary integer matrix multiplication — that's the whole point. So where does the power go? Onto the activations, fused into the activation function, with essentially no overhead.

The data flow, traced with shapes

For a layer with input activations X and weights W, the simulated inference (Algorithm 2 in the paper) is:

1   warp activations
X ← Xa   (X assumed positive; for ReLU nets it always is). Tensor X: [B, Cin], element-wise power.
2   quantize to int
Xq ← round(X / sX)   integer codes. Weights W are already power-warped & quantized offline (no runtime cost).
3   integer matmul
O ← Fl(Xq)   ordinary int×int → int32 accumulate. THIS is unchanged from uniform quant — no bit-shifts, no LUTs.
4   un-warp + activate
X ← (sσ(O) / sW)1/a   apply activation σ, rescale, un-warp with inverse power 1/a, feeding the next layer.
Why the overhead is negligible. Weights are warped once at quantization time — zero runtime cost. The only runtime additions are the power on activations (steps 1 and 4). The paper notes this can be done in integer-only arithmetic via Newton's method, converging in just 2 iterations for low bit-widths (4 for int32). So the expensive matmul is untouched; you pay only a cheap elementwise power on the much smaller activation tensors.

Handling signed activations (SiLU, GeLU)

ReLU outputs are positive, so Xa is fine. But Transformers and EfficientNets use SiLU/GeLU, which go negative — and powers of negatives break the automorphism. The fix is asymmetric quantization: shift activations up by a constant so they're positive. SiLU is provably bounded below by CSiLU=0.27846, GeLU by CGeLU=0.16997. Shift by that constant (the zero-point), warp, and the extra C·W bias term is absorbed cheaply — standard asymmetric-quant bookkeeping.

At inference, where does the power transformation get applied so that the core matrix multiply stays plain integer multiplication?

Chapter 8: The Core Insight as Runnable Code

The entire method fits in a few dozen lines of NumPy. Here is the weight quantizer, the de-quantizer, the data-free objective, and the 1-D search — exactly the loop from Algorithm 1. Read it as the executable summary of everything above.

pythonimport numpy as np
from scipy.optimize import minimize_scalar

def powerquant(W, a, b=4):
    """Quantize weight tensor W with power exponent a to b bits."""
    qmax = 2**(b-1) - 1                 # e.g. 7 for 4-bit
    sgn  = np.sign(W)
    mag  = np.abs(W)
    warped = mag ** a                   # the automorphism: |w|^a
    s = warped.max() / qmax             # scale in WARPED space
    W_int = np.round(warped / s) * sgn  # integer codes (with sign)
    return W_int, s, sgn

def dequant(W_int, s, a):
    """Recover real weights: un-warp with inverse power 1/a."""
    warped = np.abs(W_int) * s          # back to warped magnitudes
    return np.sign(W_int) * (warped ** (1.0 / a))

def recon_error(W, a, b=4):
    """Data-free objective: how much do the weights change? (L2)"""
    W_int, s, _ = powerquant(W, a, b)
    W_hat = dequant(W_int, s, a)
    return np.linalg.norm((W - W_hat).ravel(), ord=2)

# ---- data-free calibration: find a* (Nelder-Mead style 1-D search) ----
W = np.random.randn(512, 512).astype(np.float32) * 0.1   # a layer's weights
res = minimize_scalar(lambda a: recon_error(W, a, b=4),
                      bounds=(0.2, 2.0), method='bounded')
a_star = res.x
print(f"optimal exponent a* = {a_star:.3f}")   # ~0.55 in practice

# compare to plain uniform (a = 1)
print("uniform  err:", recon_error(W, 1.0,    b=4))
print("power    err:", recon_error(W, a_star, b=4))   # lower!
The one line that is the whole paper. warped = mag ** a. Everything else — scale, round, the search — is identical to ordinary uniform quantization. PowerQuant is "uniform quantization, but raise the magnitudes to a learned power first." That's why it deploys with negligible overhead: it reuses the entire uniform-quant integer pipeline.

The inference-time activation power (integer-friendly)

pythondef quant_layer_forward(x, W_int, sW, a, qmax=7):
    # x is the (positive, ReLU) activation tensor [B, C_in]
    x_warped = x ** a                       # step 1: warp activations
    sx = x_warped.max() / qmax
    x_int = np.round(x_warped / sx)         # step 2: to integers
    o_int = x_int @ W_int.T                 # step 3: PLAIN integer matmul
    o = (o_int * sx * sW)                   # rescale accumulator
    return o ** (1.0 / a)                   # step 4: un-warp for next layer
    # the only extra ops vs uniform quant are ** a and ** (1/a) on activations
In the code, which single line distinguishes PowerQuant from plain uniform quantization?

Chapter 9: Experiments — How Much It Buys

The headline is the W4/A4 column on ResNet-50. Uniform quantization there is a disaster (54.68%); PowerQuant recovers most of the loss (70.29%) — and it is still fully data-free, no fine-tuning. At W8/A8 PowerQuant is lossless (76.15%, equal to FP32), matching or beating every data-free competitor including methods that do generate synthetic data.

The numbers (ResNet-50, ImageNet)

MethodDataW8/A8W4/A4
FP32 baseline76.1576.15
Uniformno76.1554.68
Logarithmicno76.1257.07
DFQ (Nagel '19)no75.45
GDFQ (synthetic)GAN75.71~55.4
SQuant (Cong '22)no76.0468.36
PowerQuantno76.1570.29

Two facts to sit with. (1) PowerQuant beats SQuant — the prior best data-free operator — by +1.93 points at W4/A4, and beats the synthetic-data GDFQ by +14.88. (2) It can only ever beat uniform, never lose to it, because uniform (a=1) is inside its search space — at worst the optimizer returns a=1.

The empirical "a* ≈ 0.55" fact. Across networks the optimal exponent clusters around 0.55 — comfortably below 1, confirming the "finely quantize the small weights" story. But it does drift by network and bit-width (the paper reports per-config values), which is precisely why re-running the cheap 1-D search per layer/bit-width matters.

See it: PowerQuant vs the field, swept across bit-widths

This reconstructs the paper's Figure 1. Pick a bit-width regime and watch the accuracy bars. The gap between PowerQuant and uniform/log widens dramatically as bits drop — non-uniformity matters most when levels are scarce.

PowerQuant vs the Field (Figure 1, live)
DenseNet-121 / ImageNet top-1
What the paper doesn't dwell on (failure modes). The reconstruction-error proxy is a local guarantee — convex near the optimum, not globally; pathological multi-modal weight distributions could mislead it (the authors flag this in an appendix). And the activation power costs more on signed-activation Transformers (the SiLU/GeLU bias term) than on clean ReLU convnets. PowerQuant is strongest exactly where weights are bell-shaped and activations are positive.
Why can PowerQuant never do worse than uniform quantization?

Chapter 10: Connections & Cheat Sheet

PowerQuant sits at a clean intersection: it borrows the fit of non-uniform/log quantization and the hardware story of uniform quantization, by recognizing that "preserve multiplication" is an algebraic constraint with a one-parameter solution.

Where it fits in the landscape

Uniform quant
Even grid, hardware-friendly, poor fit. PowerQuant's a=1 special case.
Log quant
Great fit, but turns multiply into bit-shift. PowerQuant gets the fit without leaving multiplication.
PowerQuant
The whole multiplication-preserving family is x→xa; pick a* by data-free reconstruction-error minimization.

Cheat sheet — every equation

Symbol / formulaMeaning
Qa(W) = round[(2b−1−1)·sgn(W)·|W|a/max|W|a]Power-quantize: warp by |w|a, normalize, round to int
Qa−1(Wint) = sgn·(|Wint|·max|W|a/(2b−1−1))1/aDe-quantize: un-warp with inverse power 1/a
Q(x)×Q(y)=Q(xy) ⇒ Q(x)=xaAutomorphism constraint → power functions (Lemma 1)
ε(F,a) = ∑l ‖Wl − Qa−1(Qa(Wl))‖2Data-free objective: total weight reconstruction error
a* = argmina ε(F,a)Optimal exponent (Nelder-Mead, locally convex, unique min, ≈0.55)
a<1 / a=1 / a>1fine near 0 / uniform / fine near max

Related lessons on Engineermaxxing

The one-sentence takeaway. If you constrain non-uniform quantization to keep ordinary multiplication intact, the only maps left are power functions x→xa — so the best data-free non-uniform quantizer is found by tuning a single exponent against weight reconstruction error, recovering most of the accuracy that 4-bit uniform quantization throws away, with no data and almost no overhead.
In one line: what does PowerQuant fundamentally trade?