AIToday
AI Safety & AlignmentLobsters AIPublished: Oct 22, 2026, 10:00 JST

Elon Litman: zero-loss PyTorch trick runs code in backward pass

Send on LINE
Elon Litman: zero-loss PyTorch trick runs code in backward pass

3 Key Points

  1. What happened

    Elon Litman showed that a loss term built from (2^30 + u) − 2^30 reads 0.0 in float32 while PyTorch's autograd differentiates it as u, letting .backward() and optimizer.step() rewrite weights. A CNN trained on MNIST kept its zero aux loss while 1,024 hidden-layer weights played all 2,345 generations of Conway's Game of Life, reaching 98.80% test accuracy.

  2. Why it matters

    Because the trick never touches the checkpoint, architecture, dataset or optimizer and logs 0.000000 every step, standard reviews and flat TensorBoard curves would not flag it — a supply-chain risk for teams fine-tuning open models with third-party loss packages.

Not sure about something? Ask the AI

Questions and answers are published on this page.

Summaries like this, in your inbox every morning.

Context & Analysis

Litman's starting point was a joke: could a loss function exist where loss.item() reads 0.0 but loss.backward() still moves the weights? The answer turned out to be yes, and far more consequential than a curiosity. The mechanism rests on a split between two views of the same expression. On the GPU, float32 above 2^30 can only represent multiples of 128, so adding a small value and subtracting 2^30 erases it. In PyTorch's autograd graph, the addition and subtraction nodes differentiate symbolically to 1 each, so the gradient flows through untouched.

Layering that with a stolen .detach() and a multiplication node that acts as a directional gate, Litman builds a scalar loss that is zero on paper over the reals, zero in float32 on the GPU, and non-zero only inside the backward tape. That is enough to set theta.grad to theta − F(theta), so one SGD step replaces the weights with F(theta). Wiring in the 3×3 neighborhood rule of Conway's Game of Life turns the parameter tensor into a board that advances one generation per optimizer.step(), while the logged loss stays pinned at 0.0.

The demonstration with a 1.6-million-parameter CNN on MNIST shows the payload and the real task can coexist: the auxiliary loss stayed at 0.0 across 2,345 steps, the network still hit 98.80% test accuracy against 98.84% for a baseline, and the 1,024 hidden-layer weights ran all 2,345 generations without a cell error. Litman suggests frontier models offer even more room, since unused vocabulary rows and unselected MoE experts receive an identically zero task gradient and could serve as an isolated scratchpad before writing a finished backdoor into an active layer.

FAQ
Wouldn't a reviewer spot the malicious function in the code?
Not necessarily. Litman describes hiding the Game of Life step as a geometric regularizer, burying the constants in a config file, or shipping it as a compiled CUDA extension so only disassembly reveals it.
Do existing defenses catch this?
Litman says it bypasses the two main ones: static checkpoint scanners, because training starts from an official hash-verified checkpoint, and container sandboxes, because it runs entirely inside GPU tensor kernels.
Does it still work with Adam instead of SGD?
Litman says it probably works, either by switching to a Minsky 2-counter machine or by spreading each state transition over roughly 100 to 1,000 training iterations.
Send on LINE

AI news that matters for your work, delivered every morning.

Pick your industry and the AI tools you use, and get news related to your work every day.

Free · 30 seconds with Google · unsubscribe anytimeWhat is AIToday? →

Ask AI

Ask AI anything about this article. The AI reads this article, earlier AIToday articles, and Wikipedia, and cites its sources. Q&As are published on this page for other readers too.

Questions and answers are published on this page.

Related Articles

Next articleMeta to issue non-voting stock to fund AI, trading in 2027