Wortsman, Farhadi & Rastegari (AI2 / UW / XNOR.AI), NeurIPS 2019

Discovering Neural Wirings

Stop hand-designing which channels connect to which. Treat the whole network as one giant graph, fix a budget of k edges, and let training itself decide the wiring — discovering a sparse sub-network in a single run, no retraining, no fine-tuning.

Prerequisites: Backpropagation + Convolutional networks + a little graph intuition
11
Chapters
6
Simulations

Chapter 0: The Problem

Look at any modern efficient network — MobileNet, ShuffleNet, EfficientNet. Someone, by hand, decided that this channel feeds into that 1×1 convolution, that depthwise convolutions go here, that a channel-shuffle goes there. The wiring — which feature map connects to which — was hand-crafted, the way feature engineering used to be hand-crafted before deep learning.

Neural Architecture Search (NAS) tried to automate this. But NAS searches over blocks — a small menu of pre-baked operations (3×3 conv, 5×5 conv, skip) and how to stack them. The connectivity inside and between those blocks is still constrained by the menu. It is automated furniture arrangement in a room someone else built.

The core question: What if we drop the menu entirely? Treat every single channel as a node in one enormous graph, allow any channel to connect to any later channel, and let gradient descent discover the wiring at the same time it learns the weights — in one ordinary training run?

Why this is brutally hard

The moment you let channels connect freely, you face a combinatorial explosion. With n nodes there are up to n(n−1)/2 possible directed edges in an acyclic graph. A subgraph is any subset of those edges. The number of subgraphs is exponential.

Nodes nPossible edgesPossible subgraphs
1045245 ≈ 3.5×1013
1004,95024950 (astronomical)
1000 (one real layer)~500,000far beyond atoms in the universe

You cannot enumerate this. You cannot run reinforcement learning over it (the action space is hopeless). DARTS-style relaxations keep a dense supernet in memory — but a dense graph over thousands of channels is enormous. So the real question becomes: how do you search an exponential space of wirings using almost the same cost as one normal training run?

The connection to compression nobody had drawn yet

Here is the reframing that makes the paper click. Finding a good fine-grained wiring is the same problem as finding a good sparse sub-network. A wiring with a budget of k edges is a sparse network — most possible connections are simply absent. So a method that discovers wirings is, simultaneously, a method that compresses networks: it trains a model that uses only a small percentage of its weights on the forward pass, while still benefiting from the full over-parameterized space during search.

Why can't we just enumerate or run RL over all possible channel-level wirings?

Chapter 1: The Key Insight

The whole paper hinges on one disarmingly simple idea. Give every possible edge a weight. Then play a game of musical chairs with a fixed number of chairs.

The insight in one sentence: Keep a weight on every candidate edge. On the forward pass, use only the k edges with the largest-magnitude weights (the "real" edges). On the backward pass, let the gradient flow to — but not through — the unused ("hallucinated") edges, so an unused edge can grow until it is strong enough to kick out a real one.

Two sets of edges, in constant tension

Real edges  E
The top-k by |weight|. These actually carry signal on the forward pass. Exactly k of them, always.
Hallucinated edges  Ehal
Everything else. Invisible on the forward pass — but still receiving gradient signal. A waiting list.

Because the total budget is fixed at k, the two sets are coupled: the instant a hallucinated edge's magnitude climbs above the weakest real edge, they swap. One leaves the forward pass; the other enters it. The wiring rewires itself, mid-training, without anyone redesigning anything.

Why "hallucinated"?

An edge in Ehal doesn't exist in the network you'd actually run — it carries no signal forward. But the algorithm imagines what would happen if it did, and updates its weight accordingly. It is a hallucination of a connection that might be useful. The clever part (Chapter 4) is computing that imagined gradient almost for free.

Think of it this way: a sports team has a fixed roster (the real edges) and a bench/scouting list (hallucinated edges). You still track the stats of bench players as if they were playing. When a bench player's projected value exceeds your weakest starter, you make the trade. DNW does this for connections, automatically, on every minibatch.
What is the defining trick of DNW's backward pass?

Chapter 2: The Neural Graph — formalizing the network as a DAG

Before the algorithm, we need the right object to operate on. DNW abandons the word "layer." Instead it models the network as a directed acyclic graph (DAG) G = (V, E). Each node v holds one channel; each edge (u,v) carries a scalar weight wuv.

The node update — every symbol defined

The state of node v (call it Zv, a 2-D feature map / channel) is computed in two steps. First, gather a weighted sum of all incoming channels — the node's input Iv:

Iv = ∑(u,v) ∈ E wuv · Zu

Then apply a per-node function (in the paper: BatchNorm → ReLU → 3×3 conv):

Zv = fθv(Iv)

Input data enters through input nodes V0 (no parents); the prediction Ŷ is read off the output nodes VE (no children).

Why this subsumes everything: a depthwise-separable convolution is just "a 3×3 conv at each node, then information flow on a complete bipartite graph between two sets of nodes." Channel shuffle, channel split, grouped convs — all of them are special cases of which edges exist. Picking the wiring picks the operation.

Interactive: the same graph, different wirings = different ops

Toggle which edges exist between two layers of channels. Watch how the operation's name changes purely as a function of the wiring — no new math, just a different edge set.

Complete bipartite — every input channel feeds every output channel. This is a pointwise (1×1) convolution. Edges = 4×4 = 16.
In a neural graph, how is "the operation" (depthwise vs pointwise vs grouped) determined?

Chapter 3: The k-Edge Rule — choosing the real edges

We have a weight on every candidate edge. How do we pick which k of them are "real" (used on the forward pass)? The simplest possible rule, and it turns out to be the right one:

E = { (u,v) : |wuv| ≥ τ }    where τ is chosen so that |E| = k

In words: sort all edges by the magnitude of their weight, keep the top k, threshold the rest away. τ is just the magnitude of the k-th largest edge — a threshold that floats up and down each step to keep the count at exactly k.

Why magnitude, not sign or value? Magnitude measures how strongly an edge couples two channels, regardless of direction. A large negative weight is just as important as a large positive one. Keeping the top-|w| edges is the discrete analogue of magnitude pruning — but applied continuously, during training, instead of once at the end.

Worked example — picking k = 3 from 6 edges

Say six candidate edges into a node have weights:

w = [ 0.8, −0.1, −0.6, 0.3, 0.05, −0.45 ]

Take absolute values: [0.8, 0.1, 0.6, 0.3, 0.05, 0.45]. Sort descending: 0.8 > 0.6 > 0.45 > 0.3 > 0.1 > 0.05. The top k=3 are {0.8, 0.6, 0.45}, so the threshold τ = 0.45. The real edges are #1 (0.8), #3 (−0.6), #6 (−0.45). The rest are hallucinated. Note: a negative weight (−0.6) survives because magnitude is what matters.

Interactive: drag the budget, watch the wiring snap

Move the slider to set k. The edges re-sort by magnitude and the top-k light up as "real." This is exactly what happens at line 5 of the algorithm, every minibatch.

k=3 → threshold τ = (3rd largest |w|). 3 real edges (teal), 5 hallucinated (dim).
An edge has weight −0.7; another has +0.4. With a tight budget, which is more likely to be a "real" edge?

Chapter 4: The Gradient Trick — flow to, not through

Here is the engineering heart of the paper. A hallucinated edge carries no signal forward, so by ordinary backprop it would receive zero gradient and never change. It would be frozen forever, and no rewiring could happen. DNW breaks this with one deliberate violation of the chain rule.

The update rule, derived

For every edge (u,v) — real or hallucinated — DNW updates its weight as if it had participated:

wuv ← wuv + ⟨ Zu, −α ∂L/∂Iv

Let's unpack this completely. The input to node v is Iv = ∑ wuvZu. The loss L depends on Iv through everything downstream. The gradient of wuv by the chain rule would be:

∂L/∂wuv = ⟨ ∂L/∂Iv , Zu

where the inner product ⟨·,·⟩ sums elementwise over the whole feature map (because Zu and ∂L/∂Iv are both [H×W] tensors). A standard SGD step is then w ← w − α ∂L/∂w — which is precisely the boxed update.

The sleight of hand: For a real edge this is just normal backprop. For a hallucinated edge, ∂L/∂Iv still exists (node v is on the forward pass; only the specific edge isn't), and Zu still exists (node u is computed for its own real edges). So we can evaluate the same formula — for an edge that was never used. The gradient flows to the edge weight, but not through the edge into Zu.

Reading the update as an alignment detector

Strip away the notation. The update adds ⟨ Zu, g ⟩ to wuv, where g = −α∂L/∂Iv is "the direction we wish Iv would move to reduce loss." So:

So the hallucinated edges that grow are exactly the ones whose source channel is consistently useful for reducing the loss at the target. That is a learned, data-driven scout report.

Interactive: alignment → weight growth

Rotate the source channel vector Zu relative to the desired-descent direction g. The bar shows the resulting weight update Δw = ⟨Zu, g⟩. Find the angles that strengthen vs. weaken the edge.

At 45°: positive alignment → Δw > 0, the edge strengthens.
Footnote that matters: the appendix shows this update is equivalent to a straight-through estimator [Bengio 2013] — the forward pass applies a hard top-k mask, the backward pass pretends the mask was the identity. That's the same idea that makes binarized/quantized networks trainable. DNW is a straight-through estimator over connectivity instead of over bit-width.
Why doesn't a hallucinated edge stay frozen at its initial weight?

Chapter 5: The Swap Proof — why replacing an edge lowers the loss

We have a heuristic that feels right: strengthen edges whose source aligns with descent. But the paper proves something concrete — that under mild conditions, the moment a hallucinated edge overtakes a real one, making the swap actually decreases the loss. Let's reconstruct the argument; the paper compresses it, so we fill every gap.

The setup

Consider one target node k (using the paper's index). A hallucinated edge (i,k) is about to replace a real edge (j,k). Before the step: |wik| < |wjk| (so j is in, i is out). After the update rule (write for the updated weight): |w˜ik| > |w˜jk| — the swap condition has triggered.

Let g = −α∂L/∂Ik be the steepest-descent direction for the node's input. Define two possible post-update node inputs:

A = w˜ikZi + (rest)     (we DID swap in i)
B = w˜jkZj + (rest)     (we did NOT swap, kept j)

where (rest) is the contribution of all the other unchanged real edges — identical in both. We want to show that A moves Ik more in the descent direction than B does.

The condition to prove

"More aligned with descent" means a larger inner product with g:

⟨ A − Ik, g ⟩ ≥ ⟨ B − Ik, g ⟩

Subtract the common (rest) terms; both A−Ik and B−Ik reduce to a single edge's change. It simplifies to:

ik ⟨Zi, g⟩ ≥ w˜jk ⟨Zj, g⟩

Now recall the update rule: w˜ = w + ⟨Z, g⟩, so ⟨Z, g⟩ = w˜ − w. Substitute:

ik(w˜ik − wik) ≥ w˜jk(w˜jk − wjk)

This is now pure algebra in four scalars — no tensors left. Assuming α is small enough that the weight signs don't flip (sign(w˜)=sign(w)), the paper shows there is a learning-rate range α ∈ (0, α*) for which this inequality holds whenever the swap condition |wik|<|wjk| but |w˜ik|>|w˜jk| is met.

What the proof really says: a swap only fires when the incoming edge's source channel is more aligned with the loss-descent direction than the outgoing edge's. By a small-step argument (Lemma 1: moving the node input toward the more-aligned target reduces a Lipschitz loss), that swap can only help. The musical-chairs game is not random churn — every trade is, locally, an improvement.

The boundary case worth noticing

The paper's footnote: if wik increases in magnitude while wjk decreases, the inequality holds trivially. The only delicate case is when both grow — handled by tuning α. This is why weight decay helps in practice: it actively shrinks under-performing edges, making clean "j shrinks, i grows" swaps the common case and eliminating dead-end edges.

A swap (hallucinated i replaces real j) is provably beneficial when…

Chapter 6: Training Simulation — watch the wiring discover itself

This is the showcase. Everything from Chapters 3–5 happens here, live, on a tiny neural graph. Press Train and watch a budget of k real edges (solid teal) and a pool of hallucinated edges (dashed, dim) compete. Each step: pick top-k by magnitude → forward only on those → update all weights by alignment → re-threshold. When a hallucinated edge overtakes a real one, you'll see the swap flash.

What to look for: early on, the wiring churns — lots of swaps as the network explores. As training settles, swaps become rare: the graph has discovered a stable sub-network. Lower k = sparser network, harder competition. This is the whole paper in motion.
step 0 · loss —— · swaps 0 · real edges 4 / 12. Press Train.

The core algorithm as runnable Python

Strip DNW to its essence — a custom autograd function that masks forward, identity-backward. This is the entire trick:

python
import torch

class ChooseTopK(torch.autograd.Function):
    """Forward: keep top-k |weights|. Backward: gradient flows to ALL weights (straight-through)."""
    @staticmethod
    def forward(ctx, w, k):
        flat = w.abs().flatten()
        tau  = flat.kthvalue(flat.numel() - k + 1).values   # k-th largest |w|
        mask = (w.abs() >= tau).float()                  # real edges = 1, hallucinated = 0
        return w * mask                                  # only real edges carry signal forward
    @staticmethod
    def backward(ctx, grad_out):
        return grad_out, None                          # grad flows to EVERY weight, mask ignored

def dnw_linear(x, W, k):
    # x: [B, in]  W: [out, in] learnable, dense  k: edge budget
    W_eff = ChooseTopK.apply(W, k)              # [out, in], mostly zero on forward
    return x @ W_eff.t()                          # [B, out]

# Training is ordinary SGD. The dense W keeps updating everywhere;
# the forward pass only ever uses k entries. A zeroed weight that
# grows large will re-enter the top-k automatically next step.

Note the tensor flow: W is stored dense at full bit-width (say fp32, shape [out, in]), but Weff is mostly zeros — only k nonzeros reach the matmul. The dense backward pass is what lets dead weights recover.

In the Python above, why must the backward return the full gradient even for zeroed (hallucinated) weights?

Chapter 7: Dynamic Neural Graphs — adding time

So far the graph was a DAG: signal flows once, input to output. The paper then asks: what if a node's state can change over time? This unlocks recurrent and even continuous-time models from the same machinery.

Discrete time — and why it subsumes feed-forward nets

Give each node a state that evolves over ℓ = 0, 1, ..., L time steps:

Zv(ℓ+1) = fθv( ∑(u,v)∈E wuv Zu(ℓ) , ℓ )

Written with the weighted adjacency matrix AG of the graph, this is beautifully compact:

ZV(ℓ+1) = fθ( AG ZV(ℓ) , ℓ )
The unification: a 3-layer MLP is just a dynamic graph run for 3 time steps (Figure 1 of the paper). A cyclic graph with input injected over time is an LSTM. The same top-k edge-discovery algorithm now searches the wiring of recurrent networks — you just backprop through time.

Continuous time — the Neural ODE connection

Take the time step to zero and the recurrence becomes a differential equation:

d/dt ZV(t) = fθ( AG ZV(t) , t )

This is a Neural ODE. If only some nodes receive input (V0 ⊂ V), it's an Augmented Neural ODE. DNW discovers the wiring AG of the ODE's vector field, optimized via the adjoint method. One algorithm, three regimes: static, recurrent, continuous.

Interactive: roll the time dimension

Drag the time slider to unroll a small dynamic graph. Watch a 3-node recurrent graph "unfold" into an equivalent feed-forward stack — the same nodes, copied across time, with edges becoming layer-to-layer connections.

L=3: the recurrent graph unrolls into 3 layers — equivalent to a 3-layer feed-forward net.
What does multiplying the node states by the adjacency matrix A_G accomplish?

Chapter 8: Training Sparse Networks — DNW as one-shot compression

Now the compression payoff. Forget exotic graphs — take an existing architecture (ResNet-50) and treat each convolution as its own little graph where every weight is an edge. Apply the top-k% rule per layer. You get a sparse network trained in a single run, sparsity held throughout — no train-dense-then-prune, no retrain, no fine-tune.

Why this is different from the Lottery Ticket Hypothesis

The Lottery Ticket Hypothesis (LTH) says dense networks contain sparse "winning tickets" that train well if you find them. But LTH's recipe is expensive: train the full dense net, prune by magnitude, reset to the original init, and retrain. That's at least two full training runs.

DNW's claim: you don't need to train the dense net first. You play the same "initialization lottery" — with a combinatorial number of possible sub-networks — but during a single training run. At every step only k% of weights are active on the forward pass, yet the dense backward pass keeps every weight in contention. You get a winning ticket without ever paying for the dense net.

The forward/backward asymmetry, made concrete

PassWhat's usedTensorWhy
Forwardtop-k% of weights by |w|W ⊙ mask, mostly 0Sparse compute; this is the model you'd deploy
Backwardall weights (dense)full ∂L/∂WZeroed weights still get gradient so they can recover
Biases & BatchNormalways densefullTiny parameter count; sparsifying them hurts with no savings
First convkept dense ("First Layer Dense")fullOnly 0.04% of params, but huge accuracy impact

That last row is a quiet but striking finding: leaving the very first convolution dense (a rounding-error fraction of the parameters) noticeably raised accuracy at every sparsity level. Failure mode revealed: sparsifying the input stem starves the network of low-level features it can't reconstruct later.

The results that matter

Method (ResNet-50, ImageNet)WeightsTop-1
Sparse Networks from Scratch [Dettmers '19]10%72.9%
DNW — All Layers Sparse10%74.0%
DNW — First Layer Dense10%75.0%
Dense baseline100%77.5%

At 10% of the weights, DNW reaches 75.0% top-1 — within 2.5 points of the full dense network, and beating the prior sparse-from-scratch method by >2 points. The whole sub-network was discovered in a single ordinary training run.

What is DNW's key advantage over the Lottery Ticket Hypothesis approach for finding sparse networks?

Chapter 9: Experiments — does discovered beat random?

The paper's primary baseline is a randomly wired graph (RG): assign random weights to all edges, keep the top-k by magnitude, then freeze the wiring and train only the node parameters. Prior work (Xie et al., "randomly wired networks") showed RG already beats hand-designed nets. DNW's question: does learning the wiring beat freezing a random one?

Small-scale: same graph, three time regimes (CIFAR-10, 41k params)

A tiny classifier, run as static / discrete-time / continuous-time. In every regime, learning the wiring (DNW) beats the frozen random wiring (RG) by ~4–5 points:

SettingRandom wiring (RG)DNW (learned)
Static76.1%80.9%
Discrete time77.3%82.3%
Continuous time78.5%83.1%

Large-scale: MobileNetV1-DNW on ImageNet

Take MobileNetV1's structure, let DNW discover the channel wiring at matched FLOPs. The headline: at ~41M FLOPs, DNW boosts MobileNetV1 by 10 points of top-1 accuracy (50.6% → 60.9%), and even beats MnasNet — an RL-based NAS method that cost orders of magnitude more compute.

Interactive: accuracy vs. compute, learned vs. random vs. hand-designed

Each point is a model on the ImageNet accuracy/FLOPs trade-off. Toggle the families. DNW (warm) sits above the random-wiring and hand-designed frontiers at every budget.

DNW's frontier dominates: more accuracy at equal FLOPs, because dead neurons let it skip depthwise convs the random graph must compute.

The ablations that prove it's the update rule

Table 2 isolates why DNW works by removing pieces:

The "No Update Rule" ablation scores far below full DNW. What does that prove?

Chapter 10: Connections & Cheat Sheet

DNW sits at the crossroads of three research lines and quietly unified them: neural architecture search, network pruning/compression, and the lottery ticket hypothesis. Its real legacy was the realization that a network's connectivity can be learned by the same gradient that learns its weights — and that this is compression.

2018
Lottery Ticket Hypothesis — sparse winning tickets exist (but need train-prune-reset-retrain)
2019
Randomly Wired Networks (Xie et al.) — fixed random wiring beats hand design
2019
DNW — learn the wiring during training; sparse sub-network in one run, no retrain
2020
Edge-Popup / "What's Hidden in a Randomly Weighted Net?" — same authors: find a sub-network in a FROZEN random net, no weight training at all
2021+
Supermasks, RigL, dynamic sparse training — the live-sparsity-during-training paradigm DNW helped seed

The cheat sheet — every key idea

IdeaEquation / RuleWhat each symbol means
Node inputIv = ∑(u,v)∈E wuvZuZu=upstream channel, wuv=edge weight
Real-edge selectionE = { (u,v): |wuv|≥τ }, |E|=ktop-k by magnitude; τ=k-th largest |w|
Update rule (all edges)wuv ← wuv + ⟨Zu, −α∂L/∂Ivflow TO, not THROUGH; a straight-through estimator
Swap condition|wik|<|wjk| → |w˜ik|>|w˜jk|hallucinated i overtakes real j
Dynamic graphZV(ℓ+1)=fθ(AGZV(ℓ),ℓ)AG=adjacency; one matmul = full message pass
Continuous limitdZV/dt = fθ(AGZV(t),t)a (augmented) Neural ODE over the wiring

Why DNW still matters

The whiteboard summary

DNW treats a network as a graph with a weight on every possible edge. On the forward pass it uses only the top-k edges by magnitude (the model you'd deploy — sparse, compressed). On the backward pass it updates every edge weight via ⟨Zu, −α∂L/∂Iv — a straight-through estimator that lets an unused "hallucinated" edge grow whenever its source channel aligns with the loss-descent direction. When a hallucinated edge overtakes the weakest real one, they swap, and the paper proves (under a small-learning-rate condition) the swap lowers the loss. The result: the wiring discovers itself during one ordinary training run, beating both hand-designed and randomly-wired networks, and yielding sparse networks at 10% of the weights within 2.5% of the dense baseline.

"As NAS becomes more fine grained, finding a good architecture is akin to finding a sparse subnetwork of the complete graph."
— Wortsman, Farhadi & Rastegari, DNW (2019)