What is model degeneration?
Model degeneration is a failure mode of autoregressive language models in which generation collapses into repetitive, low-information output. The model gets trapped in a loop, producing the same phrase, sentence, or reasoning pattern over and over, while the text loses all semantic value. It does not stop generating; it simply stops communicating.
Autoregressive models generate text one token at a time: at each step the model looks at all previous tokens and picks the next one according to a probability distribution. When that distribution becomes too concentrated on a narrow set of tokens, often ones that are already present in context, the model enters a self-reinforcing cycle it cannot escape on its own.[2, 3]
Across the completions we collected, degeneration takes several recurring forms. The repeated unit may be a single token, a digit or a word emitted hundreds of times, a short phrase, a full sentence reproduced verbatim, a mathematical expression, or a structural marker such as a row of asterisks or hashtags. In each case the model stops advancing the task and instead recycles material already present in its own output.
The effect is strongly correlated with the difficulty of the prompt: simple questions are answered cleanly, whereas hard, multi-step reasoning, competition mathematics above all, degenerates far more often. Once a loop sets in, the model frequently, though not always, fails to recover a natural stopping signal and keeps emitting tokens at full confidence until the generation is cut off by the token limit, as illustrated by Apertus-8B-Instruct[1] in the example below.
A concrete example
The exchange below was generated by Apertus-8B-Instruct[1] on a one-line arithmetic question drawn from our balanced dataset. The model factorises the number correctly and even spots that 13 is prime, the answer is right there, but as it starts to list the factors it falls into a loop, repeating the digit "2" thousands of times and never delivering the answer. Text highlighted in red marks the degenerate region.
Model output: Apertus-8B-Instruct
3328 ÷ 2 = 1664
1664 ÷ 2 = 832
832 ÷ 2 = 416
416 ÷ 2 = 208
208 ÷ 2 = 104
104 ÷ 2 = 52
52 ÷ 2 = 26
26 ÷ 2 = 13
Since 13 is a prime number, we have found all the prime factors of 3328.
The prime factors of 3328 are 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, [… the digit "2" repeats until the generation hits its length limit, the correct answer, 13, is never given]
Dataset
The starting point is the dataset published on Hugging Face by Luca Sartori ( luca-sartori/degeneration-probe-instruct-token-level). It contains 83,350 completions generated by Apertus-8B-Instruct[1] across five public instruction datasets, one response per prompt, each annotated at the token level with a continuous repetition score.
A generation is labeled positive (degenerating) if it contains at least one token whose averaged repetition score is ≥ 0.8; otherwise it is labeled negative (clean). In the full 83k corpus, the vast majority of completions are clean: the natural positive-to-negative ratio is roughly 1 : 72. Training a probe on such an imbalanced set would bias the model towards always predicting the negative class, so we downsampled the negative examples.
Negative examples were randomly removed using a fixed seed (42) to keep the experiment reproducible. After a cleanup step that discarded rows with no scored tokens, the final ratio settled at approximately 1 : 1.6. The balanced dataset is published at lorenzo0312/degeneration-probe-instruct-token-level-balanced.
| Split | Total | Positive | Negative | Ratio |
|---|---|---|---|---|
| Train | 2,379 | 915 | 1,464 | 1 : 1.6 |
| Validation | 299 | 113 | 186 | 1 : 1.6 |
| Test | 295 | 113 | 182 | 1 : 1.6 |
| Dataset | Train | Val | Test | Total | % |
|---|---|---|---|---|---|
| DeepMath-103K | 654 | 83 | 78 | 815 | 27.4% |
| NuminaMath-1.5 | 610 | 88 | 76 | 774 | 26.0% |
| IF-SFT | 563 | 63 | 70 | 696 | 23.4% |
| Llama-Nemotron | 459 | 52 | 60 | 571 | 19.2% |
| Medical-O1 | 93 | 13 | 11 | 117 | 3.9% |
| Total | 2,379 | 299 | 295 | 2,973 | 100% |
Math datasets (DeepMath + NuminaMath) together account for ~53% of each split. Medical-O1 is under-represented (3.9%) because it rarely triggers degeneration, none of its tokens cross the 0.8 threshold, making it largely a negative-class source.
How we labeled the data
Every completion in the corpus was generated by Apertus-8B-Instruct[1]. Each token then receives a continuous repetition score between 0 and 1. A score of 0 means every bigram in the surrounding context is unique: healthy, diverse output. A score of 1 means all bigrams repeat: a fully degenerate loop. A token is flagged as degenerating when its score is ≥ 0.8.
The core idea is simple: rather than looking at a single token in isolation, we look at the neighbourhood around it. Concretely, we slide a window of 256 tokens along the generation and compute a bigram repetition score for each window position. A token then inherits the average score of all windows that contain it.
For every 256-token window starting at position t we compute:
TTR (Type-Token Ratio) = unique bigrams ÷ total bigrams. Intuitively: if you keep seeing the same two-word pair over and over, the TTR is low and therefore rep(t) is high. A window where every consecutive pair of tokens is different gives TTR = 1 and rep(t) = 0.
Token at position i belongs to every window starting between i−255 and i (up to 256 windows for tokens deep in a long generation). Its final score is the mean of all those window scores. This smoothing prevents a single high-repetition burst from unfairly tainting isolated tokens far from the loop. If score ≥ 0.8, the token is flagged as degenerating.
Tokens that fall outside any complete 256-token window (only possible in
generations shorter than 256 tokens) receive repetition: null
and are excluded from training.
Training the probe
A probe is a lightweight linear head attached to one internal layer of the language model. During a forward pass the prompt and response are fed through Apertus-8B-Instruct[1]; at a chosen layer X the probe intercepts the hidden state \(\mathbf{h}_t\) for every token t and maps it to a scalar score in [0, 1] via a linear projection followed by sigmoid. The backbone is kept frozen except for lightweight LoRA[4] adapters. LoRA (Low-Rank Adaptation) works by injecting two small trainable matrices alongside each frozen attention weight matrix W: a down-projection \(A \in \mathbb{R}^{d \times r}\) and an up-projection \(B \in \mathbb{R}^{r \times d}\), so the effective weight update is \(\Delta W = BA\) with rank \(r \ll d\) (typically \(r = 8\text{–}64\)). Only A and B are trained; W stays unchanged. This reduces trainable parameters by several orders of magnitude while still letting the representations adapt to the probe task.
The training signal is Mean Squared Error between the probe’s predicted score and the pre-computed repetition label \(y_t\) for each token:
Tokens with repetition: null
are excluded. The regression formulation gives the probe a continuous gradient signal
across the full score range rather than a hard binary boundary at 0.8.
The pipeline is illustrated in the diagram below.
The probe attaches to a chosen layer, reads its 4,096-dimensional activations, and predicts a per-token repetition score ŷ[t]; the MSE loss against the deterministic target y[t] trains the probe weights W. Hover a layer to see how the activations and scores change with depth.
Each probe is trained independently on a single transformer layer. We swept across ten layers (10, 14, 18, 22, 24, 26, 28, 29, 30, 31) and found that layers from layer 20 onwards all achieve similar detection performance, with only small differences in AUC across sources. Earlier layers are slightly weaker, and layer 31 (the very last) is the worst among the later ones.