Cho, Alizadeh-Vahid, Adya, Rastegari (Apple), ICLR 2022

DKM: Differentiable
k-Means Clustering for Compression

Squeeze ResNet50 to 3.3 MB and MobileNet-v1 to 1 bit-per-weight — by reinterpreting hard k-means assignment as a soft attention problem, so the codebook is trained end-to-end against the task loss instead of fitted by a blind distance metric.

Prerequisites: k-means + softmax / attention + backprop
10
Chapters
6
Simulations

Chapter 0: The Problem

You trained a great image classifier. ResNet50 hits 76% top-1 on ImageNet. Then your boss says: "Ship it on the phone. It must keep running with no network, and it has to fit." You check the file size. 97.5 MB. That is 25 million weights, each a 32-bit float. The phone has a power budget, a tiny cache, and a memory-bandwidth ceiling. Every megabyte you load from DRAM costs battery.

So you need to compress the model — make the file smaller — while losing as little accuracy as possible. There are three big families of tricks: prune weights to zero, quantize floats to low precision, or share weights. This paper attacks the third.

The core question: If we force 25 million distinct weights to reuse just a handful of shared values — say only 4 distinct numbers per layer (2 bits each) — how do we choose those shared values so the network stays accurate? The naive answer (k-means) throws away the one thing we care about: the task loss.

Why weight-sharing is so attractive

Suppose a layer has N weights and we allow only k distinct values (the centroids, or codebook). Instead of storing 25M floats, we store:

That is a 16× shrink on the index storage alone (32 bits → 2 bits), and the codebook is negligible. This is exactly how DeepCompression (Han et al., 2016) got famous. The catch is which 4 numbers, and which weight maps to which index.

A worked sense of scale

QuantityValueWhy it matters
ResNet50 weights~25.5 millionEach is 32 bits uncompressed
Uncompressed size97.5 MBToo big for many on-device budgets
Bits/weight at k=4 clusters2 bitsStore an index, not a float
DKM result (ResNet50)3.32 MB @ 74.5%29.4× smaller, ~1.6% accuracy drop
DKM on MobileNet-v10.72 MB @ 63.9%A model with almost no redundancy!

That last row is the headline. MobileNet was designed to be small — prior compressors broke on it because it has little fat to trim. DKM still squeezed it to under a megabyte. The whole lesson is about why DKM succeeds where blind k-means fails.

In weight-sharing compression with k=4 clusters, what is actually stored per weight instead of a 32-bit float?

Chapter 1: The Key Insight

Classic weight-clustering (DeepCompression) runs k-means once or periodically: it groups weights by nearest centroid, replaces each weight with its centroid, then fine-tunes. The assignment step — "weight w_i belongs to cluster c_j" — is a hard, discrete decision based purely on Euclidean distance. Discrete means non-differentiable. Non-differentiable means the network's task loss cannot reach back and say "actually, that boundary weight should have gone to the other cluster."

The insight: A row of a k-means assignment is just a one-hot vector picking the nearest centroid. Replace that hard argmin with a softmax over negative distances — and suddenly the assignment is a differentiable attention distribution. The weight "attends" to all centroids, weighted by closeness. Now gradients from the task loss flow straight through the assignment, jointly optimizing both the weights and the codebook.

The one-line reframe

Treat each weight as a query, each centroid as a key and a value. The "attention score" is how close the weight is to the centroid. The clustered weight is the attention-weighted average of centroids — exactly the standard attention readout. That is the entire paper in one sentence.

query
a weight wi — the thing we want to compress
keys / values
the k centroids cj — the shared values it may snap to
score
dij = −‖wi − cj‖ → softmax → soft assignment aij
readout
i = Σj aij cj — the clustered weight used in the forward pass
Why this is more than a trick: Because the assignment is now part of the differentiable forward pass, DKM needs no extra learnable parameters, no modified loss, no regularizers, no Hessian, no SVD, and no distillation. It drops into an existing training loop. Every competing method needed at least one of those crutches.
What does DKM replace to make k-means assignment differentiable?

Chapter 2: Background — k-means, Precisely

Before we soften it, let's be crisp about hard k-means, because DKM is k-means with exactly one operation swapped. We have N scalar weights W = \{w_1, ..., w_N\} and want k centroids C = \{c_1, ..., c_k\}. Lloyd's algorithm alternates two steps until convergence:

Assign:   j*(i) = argminj ‖wi − cj2
Update:   cj = mean of all wi with j*(i)=j

Every symbol, in plain words:

The data flow we're about to compress

Concretely, for one convolution layer we flatten the kernel tensor into a long vector of weights and feed it to a DKM "layer" that returns clustered weights of the same shape:

StageTensor / shapeMeaning
Layer weights (e.g. conv)W ∈ RNflatten kernels; N can be millions
Centroids (codebook)C ∈ Rkk = 2b for b-bit storage
Distance matrixD ∈ RN×kdij = −‖wi−cj
Attention matrixA ∈ RN×krow-softmax of D — soft assignment
Clustered weightsW̃ = A·C ∈ RNfed into the forward pass
The hidden cost (a buried footnote): D and A are each N\times k, and the loop runs r iterations — and every intermediate A and D must be kept for backprop through the loop. Memory is O(r\,N\,2^b). For a giant layer with many bits this is the practical ceiling (we see "out of memory" in the paper's 8/8 ResNet50 result). Compression at train time is not free.
Hard k-means on a Layer's Weights — Watch Lloyd's Algorithm Step

Marbles = weights, colored by their hard nearest centroid. Triangles = centroids. Step to assign-then-update. Notice marbles near a boundary flip color in a single discrete jump — there is no in-between. Hold that thought for Chapter 3.

In hard k-means, why is the assignment step non-differentiable?

Chapter 3: The Boundary Bug

Here is the failure that motivates the whole paper, drawn straight from Figure 1. Consider two boundary weights, call them i and j, sitting almost exactly between two centroids. Hard k-means assigns each to its marginally nearer magnet — i\to c_2, j\to c_1 — purely on distance.

But "nearest in Euclidean distance" is not the same as "best for the task." Maybe sending i\to c_0 would barely change the rounding error but would let the network keep a decision boundary it needs. Distance can't know that. Only the task loss knows that — and in hard k-means the loss has no way to express its preference, because the argmin wall blocks the gradient.

Why this hurts most at low bits: With fewer clusters (low bit-width), each centroid covers a wider swath of weights, so each hard misassignment is a bigger rounding error. At 1-bit (k=2) a single wrong flip can swing a weight by a lot. The "lost opportunity cost" of a bad boundary decision grows exactly as compression gets aggressive — which is precisely the regime we care about.

The second, sneakier bug: the gradient hack

Classic methods have a second problem. In the backward pass, the weights are tied to a centroid, so what gradient does a weight get? DeepCompression simply re-purposes the centroid's gradient as the weight's gradient — an ad-hoc substitution with no principled justification. It's a straight-through-estimator-style fudge. DKM has no such fudge: the gradient of a weight is exactly the product of attention values and centroid gradients, because the forward pass is genuinely differentiable.

The Boundary Weight — Hard vs Soft Assignment

Two centroids, one weight you drag between them. The bars show the hard one-hot assignment (snaps abruptly at the midpoint) vs the soft DKM attention (a smooth blend). Hard assignment is a step function — flat then a cliff. Soft is a ramp the loss can climb.

Why does the hard-assignment boundary problem get WORSE as we use fewer bits (fewer clusters)?

Chapter 4: k-means as Attention — The Math

Now we derive the soft assignment from scratch. We need a differentiable stand-in for "pick the nearest centroid." The argmin over distances has a famous smooth cousin: the softmax over negative distances. As distances shrink (closer), the negative distance grows (larger score), so softmax puts more weight there — and in the limit it becomes a one-hot at the nearest. This is the standard "soft argmax."

Step 1 — distance as an attention score

For every weight–centroid pair, define a score that is large when close:

dij = −f(wi, cj) = −‖wi − cj2

The minus sign is the whole game: nearest centroid ⇒ smallest distance ⇒ largest (least-negative) score. f is any differentiable metric; the paper uses Euclidean.

Step 2 — softmax with temperature = soft assignment

aij = exp(dij / τ) ⁄ Σk exp(dik / τ)

Here a_{ij} is "how much weight i attends to centroid j," each row sums to 1, and \tau is the temperature — the softness knob we dissect in Chapter 6. Small \tau → spiky, near one-hot (almost hard k-means). Large \tau → flat, every centroid shares the weight.

Step 3 — the centroid update is also attention

Hard k-means updates a centroid to the mean of its members. The soft version is an attention-weighted mean, where weights that attend more pull harder:

j = (Σi aij wi) ⁄ (Σi aij)

The denominator \sum_i a_{ij} is the soft membership count of cluster j — the fractional number of weights leaning toward it. Compare to hard k-means where the count is an integer.

Worked numerical example (do it by hand)

One weight w=0.5, two centroids c_1=0.0, c_2=1.0, temperature \tau=0.5. Distances: d_1=-|0.5-0|=-0.5, d_2=-|0.5-1|=-0.5. Both equal ⇒ perfectly balanced:

a1 = e−0.5/0.5 ⁄ (e−1+e−1) = 0.5,   a2=0.5

Clustered weight: \tilde w = 0.5\cdot 0 + 0.5\cdot 1 = 0.5 — it reconstructs perfectly because it sits dead center. Now nudge w=0.6: d_1=-0.6, d_2=-0.4, scores e^{-1.2}=0.301, e^{-0.8}=0.449, so a_1=0.40, a_2=0.60 and \tilde w=0.60. The assignment continuously tilts toward c_2 — and that continuity is exactly what carries a gradient.

The payoff: Because every step is softmax, sum, and weighted average — all differentiable — the task loss L can compute \partial L/\partial w_i and \partial L/\partial c_j directly. A weight's gradient becomes a blend of the centroids' gradients, weighted by attention. Boundary weights now "shuttle" between clusters across batches, settling where the loss prefers — not where raw distance dictates.
In the centroid update c̃j = (Σi aij wi)/(Σi aij), what does the denominator represent?

Chapter 5: The DKM Loop — Showcase

This is Figure 2 made interactive. A DKM layer doesn't just do one assignment — it runs the soft assign/update loop inside the forward pass until the centroids stop moving (|C-\tilde C|\le\epsilon) or it hits the iteration limit (the paper uses \epsilon=10^{-4}, limit 5). Then it produces the clustered weights \tilde W = A\cdot C for the rest of the network — and crucially, backprop runs through every iteration of this loop.

One subtle, brilliant detail: centroids are not re-randomized each batch. The last C from the previous batch is the starting point for this batch (only iteration 0 uses k-means++ / random init). This warm-start makes the inner loop converge in a few steps and lets the codebook evolve smoothly with the weights — the magnets drift slowly as the marbles drift.

Play with the live DKM layer

Below is a real soft k-means loop on a layer of weights. Press Run loop to watch the attention reassign and the centroids glide to their attention-weighted means. Drop the temperature toward 0 and it behaves like hard k-means (centroids snap to cluster means); raise it and centroids collapse toward the global mean. Increase iterations to see convergence; change k to add codebook entries.

DKM Layer — Soft Assign + Update Loop (interactive Figure 2)

Each weight (dot, top row) draws faded lines to the centroids (triangles, bottom row); line opacity = attention aij. After each iteration the centroids slide to their attention-weighted mean. The status line reports total centroid movement ΔC — when it drops below ε, the loop has "converged" and W̃ = A·C is read out.

The whole loop in runnable PyTorch

This is the paper's core algorithm — a parameter-free, differentiable layer. Drop it on a flattened weight tensor; autograd handles the backward pass through the loop automatically.

dkm() — the parameter-free differentiable layer (PyTorch)
import torch, torch.nn.functional as F

def dkm(W, C, tau=1.0, iters=5, eps=1e-4):
    # W: [N] weights to compress.  C: [k] current codebook (warm-started).
    W = W.unsqueeze(1)                       # [N, 1]
    for _ in range(iters):
        D = -(W - C.unsqueeze(0)).abs()   # [N, k]  d_ij = -|w_i - c_j|
        A = F.softmax(D / tau, dim=1)       # [N, k]  row-softmax = attention
        C_new = (A * W).sum(0) / A.sum(0)  # [k]   attention-weighted means
        if (C_new - C).abs().max() < eps:   # converged?
            C = C_new; break
        C = C_new
    W_tilde = (A * C.unsqueeze(0)).sum(1)  # [N]  W̃ = A · C, used in forward pass
    return W_tilde, C                       # gradients flow through the whole loop

Note what's not here: no requires_grad on new parameters, no custom backward, no regularizer added to the loss. It's just differentiable ops, so the existing training loop and its gradients do all the work.

Why does DKM warm-start the codebook C from the previous batch instead of re-initializing it each batch?

Chapter 6: Temperature — The Hardness Knob

Soft assignment is wonderful for training, but at inference you must commit: each weight is stored as a single index into the codebook (that's where the 2-bit savings live). So the soft attention must harden into a one-hot. The temperature \tau is the dial between these two worlds.

The two limits, derived

Look again at a_{ij}=\text{softmax}(d_{ij}/\tau). The ratio between the top two scores is \exp((d_{\text{best}}-d_{\text{2nd}})/\tau):

Annealing intuition: Think of training as slowly cooling. Early on, warmer assignments let boundary weights explore — "shuttle among centroids," in the paper's words. As training proceeds the attention naturally sharpens (the weights and codebook co-adapt) so the soft assignment already closely matches the hard one it will collapse to. At inference, snapping each weight to its argmax centroid costs little because the model was annealed to that decision. The gap between "soft training behavior" and "hard inference behavior" is small by construction.

Worked example — the hardening gap

Boundary weight w=0.55, centroids 0.0 and 1.0. At \tau=0.3: scores e^{-0.55/0.3}=0.160 vs e^{-0.45/0.3}=0.223a=(0.42,0.58), soft \tilde w=0.58; hardened → 1.0, error 0.45. At \tau=0.05: a\approx(0.13,0.87), soft \tilde w=0.87; hardened → 1.0, error 0.13. Colder ⇒ the soft value already lives near the hard target ⇒ smaller surprise at inference time.

Temperature Sweep — Soft Attention Sharpening to One-Hot

Three centroids and one fixed weight. Bars = attention aij. Slide τ down: the distribution sharpens toward a one-hot on the nearest centroid (hard k-means). Slide up: it flattens toward uniform (the global mean). The dashed line marks the hardened value the inference engine will store.

As τ → 0, what does DKM's soft assignment become?

Chapter 7: Multi-Dimensional DKM

So far each weight was a scalar clustered on a line. But you can cluster groups of weights jointly. Split the N weights into N/d contiguous d-dimensional sub-vectors, and cluster those points in d-D space. Centroids become d-D vectors (C\in R^{k\times d}); the distance metric runs in R^d. This is product-quantization-style codebook compression, now made differentiable.

Why bother? The entropy argument (Figure 3)

The compression ratio for b-bit, d-dim clustering versus 32-bit floats is:

cr = 32N ⁄ (b · N/d) = d · 32 / b

Read that: compression depends only on the ratio d/b, not b or d alone. So 4/4 and 8/8 and 2/2 all give the same compression (1 effective bit-per-weight). But they are not equally good for accuracy. Assuming an even split, the per-weight entropy is:

ew = −Σi pi log2 pi = b,   with pi = 2−b

Entropy e_w=b increases with b at fixed d/b. Higher weight entropy ⇒ more learning capacity ⇒ (often) better accuracy. So at a target compression ratio, push b and d up together as far as memory allows.

The catch (the exponential wall): the codebook has 2^b entries and DKM's memory is O(r\,(N/d)\,2^b). So b can't grow forever — 2^b explodes. This is exactly why the paper reports out-of-memory for ResNet50 at 8/8. The sweet spot is "as many bits as your GPU survives," and that is empirical, not a clean formula.

Why this would WRECK ordinary k-means

In high d, a sub-vector can be near the boundary of many centroids at once (16 centroids at 4/4 vs only 2 at 1/1). The chance of a damaging hard misassignment grows combinatorially — prior methods often fail to converge at multi-dim configs. DKM survives because soft assignment + task-loss feedback can recover from an early bad choice over training. The 8/8 MobileNet-v1 result (64.3% at 1 effective bit-per-weight) is the proof.

2-D Sub-Vector Clustering — Soft DKM in the Plane

Each point is a 2-D weight sub-vector (d=2). Centroids (large rings) are 2-D codebook vectors. Soft attention colors each point as a blend of centroid colors. Run the loop and watch centroids migrate to attention-weighted 2-D means.

At a FIXED compression ratio, why might 8/8 (8 bits, 8 dims) beat 1/1 (1 bit, 1 dim) on accuracy?

Chapter 8: Experiments — Reading the Results

DKM is benchmarked on ImageNet1k (vision) and GLUE (NLP). The headline pattern: DKM is Pareto-superior — for any given model size, it gets higher accuracy than DeepCompression (DC), HAQ, and "And The Bit Goes Down" (ATB). The win is biggest exactly where prior methods struggle: very low bits and already-compact models.

The numbers that matter

ModelConfigTop-1Sizevs base
ResNet50 (base)32-bit76.1%97.5 MB
ResNet50 + DKMcv:4/4, fc:8/474.5%3.32 MB29.4×
MobileNet-v1 (base)32-bit70.9%16.1 MB
MobileNet-v1 + DKMcv:4/4, fc:4/263.9%0.72 MB22.4×
MobileNet-v1 + DKM8/8 (=1 bit/w)64.3%~1 bit/wmulti-dim

The MobileNet-v1 row is the famous one: 6.8% higher top-1 and 33% smaller than the prior state of the art on a model everyone considered "already maximally efficient." And the 8/8 multi-dim config beats the 1/1 config (64.3% vs ~50%) at the same effective bit-budget — direct evidence for Chapter 7's entropy argument.

What "not converging" tells us: In the head-to-head tables, competing methods (PROFIT, EWGS) show nc ("not converging") and oom entries at aggressive configs, while DKM trains through. The robustness — not just the peak number — is the contribution. DKM also compressed DistilBERT 11.8× on GLUE with only ~1.1% accuracy loss, so the method is not vision-specific.

Honest limitations the paper admits

Accuracy vs Compression — DKM's Pareto Frontier

Top-right is best (small model, high accuracy). DKM points (orange) sit above and to the right of prior methods (teal) — the definition of a Pareto-superior frontier. Toggle models to see the gap widen on the harder-to-compress MobileNet.

Where does DKM's advantage over prior compressors show up most strongly?

Chapter 9: Connections & Cheat Sheet

DKM lives at the intersection of three ideas you already know: k-means (the clustering it softens), attention (the mechanism it borrows), and quantization (the compression goal it serves). Its deepest lesson is a transferable pattern: any time a discrete argmax/argmin blocks a gradient, a temperatured softmax can turn it into a trainable soft choice — the same move behind Gumbel-softmax, soft attention, and differentiable rendering.

The transferable trick: "Differentiable hard decisions via softmax-with-temperature." Saw it in attention (soft alignment), in VQ-VAE alternatives (Gumbel codebooks), in NAS (soft architecture choices). DKM applies it to weight-sharing. Once you internalize it, you'll spot the same pattern everywhere a model has to choose.

Cheat sheet — every symbol, one place

SymbolMeaningPlain analogy
W ∈ RNlayer weights to compressmarbles on a line
C ∈ Rkcodebook / centroids (k=2b)magnets / shared values
dij = −‖wi−cjnegative distance = attention score"closeness vote"
aij = softmax(dij/τ)soft assignment (attention)how much wi leans on cj
τtemperature / hardness0 = hard k-means, ∞ = uniform
j = Σaijwi / Σaijcentroid updateattention-weighted mean
W̃ = A·Cclustered weights (forward pass)rounded weights
cr = 32d/bcompression ratiodepends only on d/b
ew = bweight entropy / capacitygrows with bits b

The five things to remember

1 · Reframe
Hard k-means assignment = argmin; soften it to softmax-over-(−distance) = attention.
2 · Differentiable
Now the task loss trains the codebook AND the weights jointly — no fudged gradients.
3 · Parameter-free
No new params, no modified loss, no regularizer/Hessian/SVD/distillation. Drops into training.
4 · Temperature
τ anneals soft→hard so the inference-time one-hot snap costs little accuracy.
5 · Multi-dim
Cluster d-dim sub-vectors: same cr=32d/b, higher entropy e_w=b → better accuracy (bounded by O(2^b) memory).

Where to go next

Mastery check: You should now be able to (1) write the DKM forward loop from memory, (2) explain why hard k-means hurts boundary weights and low-bit configs, (3) derive both τ limits, (4) explain why 8/8 beats 1/1 at equal compression, and (5) state the one design pattern — differentiable choice via temperatured softmax — that generalizes far beyond compression.
What is the single most transferable idea from DKM?