A small transformer that adds numbers kept failing on longer numbers for reasons that had nothing to do with addition. Every failure traced back to one property of softmax attention: it can prefer, but never exclude, and every preference is relative to everything else in the sequence. Patching it by hand moves the failure around. Letting the model learn its own coordinates gets surprisingly far, until it runs into the precision of counting.
The earlier log ended with a fix: 2D rotary positions, a fixed decay in column distance and a position-free attention sink took a one-digit-per-token adder from failing at about 40 digits to 100% at 200 on every seed. This log follows what happened next: the same fix on 3-digit tokens, a new failure, and what it says about attention itself. The tokenization side of the study is written up separately in How Tokenization Decides Whether a Transformer Can Add.
On 3-digit right-cut tokens, the fix gave two seeds near-perfect reach (.99 and 1.00 at 200 digits) and one seed far less (.49). Scoring every decision of 150 random 100-digit problems on its own, given the correct answer so far, seed 2 got 591 of 5250 decisions wrong; seeds 0 and 1 got 0 and 0. Its errors start abruptly around answer chunk 17, only where the first number has already ended, and attention to the target digit itself is unchanged.
What changed is where the remaining attention goes. The second number's chunks look for "the first number's chunk in my column", and once the first number has ended there is nothing to find. The decay pulls every far score toward zero, but a score of zero still gets weight e0 = 1 in the softmax, and the number of far keys grows with the column:
| model | heads | chunks 0–9 | 10–19 | 20–29 | 40+ | error: no cut → cut |
|---|---|---|---|---|---|---|
| seed 2 (fails) | L2H5 / L3H5 / L4H5 | 0.06 / 0.01 / 0.03 | 0.82 / 0.56 / 0.75 | 0.93 / 0.88 / 0.87 | 0.99 / 0.96 / 0.95 | .47 → 0 |
| seed 0 (perfect) | L2H0 / L4H5 / L4H2 | 0.10 / 0.01 / 0.07 | 0.58 / 0.64 / 0.46 | 0.79 / 0.78 / 0.65 | 0.90 / 0.93 / 0.82 | 0 → 0 |
| one digit per token, seed 0 (perfect) | L3H4 / L2H5 / L4H5 | 0.02 / 0.04 / 0.00 | 0.46 / 0.27 / 0.05 | 0.62 / 0.45 / 0.25 | 0.72 / 0.40 / 0.28 | 0 → 0 |
In every model, some heads end up giving most of their attention to the crowd of far keys. Only seed 2 decides "the first number is missing, treat it as 0" with those heads, so only seed 2 breaks, and removing far keys at evaluation removes all of its errors. Nothing here was aliasing: no single far key scores high. Many keys each score a little.
Softmax gives key j a share proportional to escorej, so only score gaps matter. A key that beats each of n others by a gap g keeps a share of 1 / (1 + n·e−g): to keep a majority it needs g > ln n.
Computed, not measured. A gap of 2 keeps a majority against at most about 7 other keys; holding against a thousand needs a gap of about 7.
Write the target's share as 1 / (1 + Σj e−gapj). Every failure in this project is a way for that leak sum to grow with length: aliasing is one far key with a gap near zero; drift is gaps at untrained distances that nothing constrains; dilution is many keys with modest gaps. Training on 10 digits only asks for the gaps 10 digits need, and the measured sink scores (about 0.7–2.5, against 50–100 for real lookups) show it learns exactly that much. For a head to behave the same at any length, the leak sum must stay bounded as the sequence grows, which requires a far key's gap to grow faster than log(distance). Rotary scores are periodic and bounded, so with rotation alone the sum always grows.
The same inequality is behind long-context methods in language models: Scalable-Softmax multiplies scores by a multiple of log(context length), and YaRN adds an attention temperature that grows with the log of the context-extension factor, both to keep attention from flattening as the context grows.
Three eval-time patches, each a no-op at training lengths: raise the sink's score by log(n / ntrain) or twice that, or drop all keys beyond the largest training distance (a window). Accuracy at 200 digits, seeds 0 / 1 / 2:
| model | none | sink + log n | sink + 2 log n | window |
|---|---|---|---|---|
| 3-digit right-cut, decay + sink | 1.00 / 1.00 / .47 | .93 / .99 / .69 | .01 / .93 / .53 | 1.00 / 1.00 / .99 |
| 3-digit left-cut, decay + sink | .27 / .01 / .14 | .32 / 0 / .21 | .20 / 0 / .24 | .01 / 0 / 0 |
| 1 digit, decay + sink | 1.00 / 1.00 / 1.00 | 1.00 / 1.00 / 1.00 | 1.00 / 1.00 / 1.00 | 1.00 / 1.00 / 1.00 |
| 1 digit, decay only (rotating sink) | .28 / .70 / .74 | .21 / .61 / .74 | .10 / .28 / .58 | .28 / .71 / .76 |
A stronger sink starves real lookups in models that did not need it; the window fixes the diluted seed and nothing else. Each patch encodes an assumption about how one particular model solved the task, and seeds solve it differently because 10-digit training cannot tell their mechanisms apart.
Sparsemax and entmax replace softmax with a rule that gives keys sufficiently below the leaders exactly zero weight, however many there are. Swapped in at evaluation, seed 2 improves only partly (200 digits: .51 → .67): its sink scores about 0.7, and beyond the trained range the best far keys score as high or higher, so they are leaders, not a crowd to exclude. Trained with entmax-1.5 from scratch, fewer sink heads collapse past the trained range (6 of 23 vs 12 of 23 with softmax), but a head that does collapse loses everything, and reach is worse overall (200 digits: .07 / .94 / .93 vs .99 / 1.00 / .49). The normalization changes how scores become weights; the failure is in the scores at distances training never saw.
Stepping back: a person adding on paper looks up digits by location ("same column, one row up"), an exact operation that means the same at any length. Attention only has content addressing (find the key most similar to the query) and fakes location by encoding positions as content, then reconstructing "one column ahead" as a similarity over distance from what training showed. Every failure above lives in that reconstruction. Earlier architectures had both kinds explicitly: the Neural Turing Machine shifted its read head by −1/0/+1, and the convolutional Neural GPU learned binary addition on short instances that generalized to much longer ones. Transformers traded explicit location for parallel training and generality.
Long training data does not close the gap either: in the tokenization log, adding 20–40 digit problems moved this model family's cliff from about 40 to about 160 digits, four times the longest training length both times.
So the last experiment keeps attention general and gives it a way to build exact locations: no rotary encoding, no place index, no positions at all. Each head keeps two counters, ct = (1 − resett)·ct−1 + gatet, with the gate and reset learned from the token's content (the same idea as contextual position encoding, CoPE). Position enters only through learned kernels of counter differences, free in shape within ±8 and forced to fall beyond, and each head has a position-free null key to attend to when nothing matches.
The limit is the counting itself. A gate is a sigmoid, so a column counter adds slightly less than one per digit, and differently in the operand and answer rows. Lookups compare counts, so the error in "same column" grows with the column, and somewhere past 50 columns the head reads the neighbouring digit. Rounding only the column counters' gates to exactly 0 or 1 at evaluation, with no retraining:
| model | counts per digit | drift at col. 99 (a / b) | made exact | 40 digits | 60 | 100 | 200 |
|---|---|---|---|---|---|---|---|
| seed 0 | 0.937 | 1.25 / 1.49 | 7 | .97 → .98 | .60 → .91 | .06 → .89 | 0 → .66 |
| seed 1 | 0.950 | 0.83 / 0.83 | 9 | .94 → .97 | .72 → .91 | .18 → .86 | 0 → .53 |
| seed 2 | 0.720 | 2.00 / 7.51 | 7 | .20 → .20 | .01 → .01 | 0 → 0 | 0 → 0 |
Seeds 0 and 1. Seed 2 does not route its lookups through its column counters and is unchanged.
Required precision grows with length (an error of ε per digit is half a column off after 1/(2ε) digits) while training at 10 digits only asks for about 5%. It is the leak sum again, in the counters: the model learns exactly the precision its training lengths need. Building exactness into training is not yet solved here. Switching a trained model's column counters to exact (straight-through) gates and continuing training knocked two of three seeds off their solution (reach 0); training from scratch with one exact and one soft counter per head, the model did its column counting with the soft counters (12 column counters, 0 of them exact) and extended worse (.39 at 40 digits).