# Messprotokoll MATH-500 — warum eine Zahl allein nichts sagt Diese Seite protokolliert, wie die Mathematik-Werte in der Modellkarte zustande kommen, welche Fehler dabei aufgetreten sind und was noch fehlt. Sie existiert, weil derselbe Messlauf je nach Auswertung **76 oder 99 Prozent** ergibt — und beide Zahlen belegbar sind. Wer Benchmark-Werte veröffentlicht, ohne das offenzulegen, veröffentlicht eine Meinung. ## Der aktuelle Stand **Qwen3.8-27B Q8_0, `reasoning_effort: xhigh`, Budget 24.000 Token, 150 Aufgaben: 147 richtig = 98,0 %** — in einem Durchlauf, ohne Nachmessung. Die drei Fehlschläge: | Art des Fehlschlags | Anzahl | |---|---| | Notation, vom Vergleicher als falsch gewertet | 2 | | keine Antwort geliefert (Budget gerissen) | 1 | | falsches Ergebnis geliefert | **0** | **Über 150 Aufgaben kein einziges falsches Ergebnis.** Entweder stimmt die Antwort, oder es kommt gar keine. Der Weg dahin ist die eigentliche Geschichte dieses Protokolls. Dieselben 150 Aufgaben lagen mit 8.000 Token Budget bei 138 richtig = 92,0 %, mit zehn Aufgaben ohne jede Antwort. Die sechs Prozentpunkte Unterschied hat kein Modell und keine Einstellung gebracht, sondern allein der Platz zum Rechnen — siehe Fehler 1. Und der ursprünglich gemessene „Reasoning-Vorteil" von 16 Punkten löste sich auf, sobald beide Läufe dasselbe Budget bekamen (Fehler 5). Die Einzelfälle des 8.000er-Laufs stehen mit Aufgabentext und Musterlösung in [FEHLERANALYSE.md](FEHLERANALYSE.md). ## Fehler 1: das Token-Budget — behoben Der erste Durchgang lief mit **1.600 Token** Budget je Aufgabe. Das war die denkbar schlechteste Wahl: knapp über dem 90. Perzentil des tatsächlichen Bedarfs. Ein Viertel aller Antworten wurde mitten im Rechenweg gekappt, bei Stufe 5 fast die Hälfte. **Behebung:** zweistufige Messung (`run_omega.sh`). Stufe 1 misst den tatsächlichen Bedarf an einer kleinen Stichprobe, Stufe 2 fährt den Hauptlauf mit dem gemessenen Budget statt einem geratenen. **Was dabei schiefging und wichtig ist:** Stufe 1 ergab an zwölf Aufgaben ein Maximum von 4.274 Token — im Hauptlauf lagen **20 von 150** darüber. Der Token-Bedarf hat einen schweren Schwanz: | | Token je Aufgabe | |---|---| | Median | 610 | | 75. Perzentil | 1.563 | | 90. Perzentil | 5.384 | | darüber | direkt ans Limit | Aus einer kleinen Vorabstichprobe lässt sich das nötige Budget **nicht** ableiten. Wer so vorgeht, muss den Schwanz großzügig aufschlagen. ## Fehler 2: zu strenger Antwortvergleich — behoben, in zwei Runden Bei Mathematik-Benchmarks steckt der Fehler fast nie im Modell, sondern im Vergleich: dieselbe Antwort kommt als `0.75`, `\frac{3}{4}`, `3/4` oder `\dfrac{3}{4}`. **Erste Runde.** Von acht abgeschlossenen, aber als falsch gewerteten Antworten war **genau eine wirklich falsch**: | gegeben | erwartet | tatsächlich | |---|---|---| | `\frac{4}{3}` | `\frac43` | identisch, Kurzform ohne Klammern | | `\frac{3}{4}` | `\frac 34` | identisch, Leerzeichen statt Klammern | | `0,35625` | `.35625` | identisch, Dezimalkomma und führende Null | | `5` | `x=5` | richtig gerechnet, ohne Zuweisungspräfix | | `[-2, 7]` | `x \in [-2,7]` | richtig, ohne Mengenzeichen | | `B` | `\text{(B)}` | richtig, Multiple-Choice-Buchstabe | | `-0.09` | `\frac{9}{100}` | **echter Fehler** (Vorzeichen) | **Zweite Runde**, gefunden im Omega-Lauf selbst: | gegeben | erwartet | tatsächlich | |---|---|---| | `\frac{270}{7}` | `\frac{270}7\text{ degrees}` | identisch, Einheit nur auf einer Seite | | `12\text{ cm}` | `12` | identisch, Einheit auf der anderen Seite | | `1-\sqrt{19}, 1+\sqrt{19}` | `1 \pm \sqrt{19}` | dieselbe Lösungsmenge, ausgeschrieben | | `\begin{pmatrix}\frac{16}{49}\\[2mm]…` | `\begin{pmatrix}16/49\\…` | derselbe Vektor, andere Bruchform | Wirkung ohne jede erneute Modellrechnung — die Antworten lagen bereits vor: | Modell | vorher | nachher | |---|---|---| | Qwen3.8-27B BF16 | 72,7 % | **77,3 %** | | Qwen3.8-27B Q6_K | 72,7 % | **76,7 %** | | Qwen3.6-27B Q6_K | 70,7 % | **76,7 %** | | Qwen3.8-27B Q8_0 | 72,0 % | **76,0 %** | | Qwen3.8-27B Q8_0, mit Reasoning | 90,0 % | **92,0 %** | **Vier bis sechs Prozentpunkte, die reine LaTeX-Konvention waren.** Die Rangfolge hat sich dabei nicht geändert — der Fehler traf alle Varianten gleich. Die Gegenrichtung ist genauso wichtig und wird mitgeprüft: `\frac{270}{7}` gegen `\frac{271}7\text{ degrees}` bleibt **ungleich**, `1 \pm \sqrt{19}` gegen `1 \pm \sqrt{17}` bleibt **ungleich**, und `(3,2)` gegen `(2,3)` bleibt **ungleich** — eine Regel, die Einheiten wegwirft oder Kommas umsortiert, darf nicht anfangen, Werte gleichzumachen. `selftest_mathe.py` prüft inzwischen 47 Fälle in beide Richtungen plus alle 240 Musterlösungen gegen sich selbst. ### Eine Nebenwirkung, die fast durchgerutscht wäre Die gelieferte Antwort wurde im Bericht auf 60 Zeichen gekürzt. Verglichen wurde zur Laufzeit die volle Antwort — aber damit ließ sich ein langer Matrix-Ausdruck **nachträglich nicht mehr neu bewerten**. Die Grenze liegt jetzt bei 400 Zeichen. Wer Läufe nachträglich umbewerten will, muss speichern, was er vergleicht. ## Fehler 3: Trainingskontamination — nicht geprüft MATH-500 liegt seit Jahren öffentlich auf HuggingFace. Ob die getesteten Modelle die Aufgaben im Training gesehen haben, ist **nicht untersucht**. Für den Vergleich der Varianten untereinander ist das unerheblich — Kontamination trifft alle gleichermaßen. Für jeden Vergleich mit fremden Modellen macht es die absoluten Zahlen wertlos. **Geplante Prüfung:** Fortsetzungstest — dem Modell die ersten Wörter einer Aufgabe vorlegen und sehen, ob es den Originaltext wörtlich vervollständigt. ## Fehler 4: der Generierungskollaps — die eigentliche Schwäche Die zehn Aufgaben ohne Antwort wurden mit **32.000 Token** nachgemessen, also dem Vierfachen. Ergebnis: **neun lösen sich, keine einzige lief erneut ins Limit.** Damit steht die Bilanz bei 147 von 150 = 98,0 % — allerdings über zwei verschiedene Budgets hinweg, also keine Leaderboard-Quote. Die Erwartung war „schwere Aufgaben brauchen mehr Platz". Das stimmt nur zum Teil. Was tatsächlich passiert, ist dreierlei: **Erstens: echter Mehrbedarf.** Fünf der zehn brauchten mehr als 8.000 Token, die aufwendigste 14.816. Hier war das Budget schlicht zu klein. **Zweitens: Streuung.** Zwei Aufgaben, die im Hauptlauf 8.000 Token rissen, lösten sich in der Nachmessung mit **1.527** beziehungsweise **1.830** Token — ein Fünftel des vorherigen Verbrauchs. Gleiche Aufgabe, gleiches Modell, gleiche Temperatur. Hier braucht nicht die Aufgabe viel Platz, sondern der einzelne Durchlauf verläuft sich. Zwei weitere lagen mit 7.515 und 7.976 knapp **unter** der alten Grenze, waren also reine Grenzfälle. **Drittens: ein echter Wiederholungskollaps.** Genau ein Fall. Der Denktext endete so: ``` ? x= ? x= ? x= ? x= ? x= ? x= ? x= ? x= ? x= ? x= ? x= ? x= … ``` Hunderte Male. Danach setzte das Modell das Ende-Zeichen und lieferte einen **leeren** Antworttext. Verbraucht waren 16.044 von 32.000 Token — das Budget war also **halb leer**, der Abbruchgrund lautete `stop`, nicht `length`. **Daraus folgt eine praktische Empfehlung:** gegen diesen Fehler hilft kein größeres Budget, sondern ein zweiter Versuch. Wir fahren mit Temperatur 0,2 und `top_p 0.9` ohne Wiederholungsstrafe; Zyklen dieser Art sind bei niedriger Temperatur ein bekanntes Muster. Wer das Modell produktiv einsetzt, sollte im Client eine Wiederholung vorsehen, wenn die Antwort leer bleibt. ## Fehler 5: der Reasoning-Vergleich war verzerrt — behoben, mit umgekehrtem Ergebnis Eine frühere Auswertung stellte „mit Reasoning 92,0 %" gegen „ohne Reasoning 76,0 %" und schloss auf **+16 Punkte durch Denken**. Der gepaarte Test sah eindrucksvoll aus: 23-mal war nur der Reasoning-Lauf richtig, kein einziges Mal nur der andere. **Der Vergleich war nicht sauber.** Der Lauf ohne Reasoning hatte ein Budget von **1.600** Token, der mit Reasoning **8.000**. Ein Teil des Abstands war Budget, nicht Denken — im 1.600er-Lauf liefen 34 von 150 Aufgaben ins Limit. **Behebung:** beide Läufe erneut, dieselben 150 Aufgaben, beide mit **24.000** Token, alles andere identisch. | Lauf | richtig | Token je Aufgabe | am Limit | |---|---|---|---| | Reasoning `xhigh` | 147 / 150 = 98,0 % | 1.890 | 1 | | ohne Reasoning | 146 / 150 = 97,3 % | 1.431 | 0 | ``` exakter McNemar: 4 : 3 p = 1,0000 ``` **Von den +16 Punkten bleibt nichts übrig.** Bei gleichem Budget ist auf MATH-500 kein Reasoning-Effekt nachweisbar. Der gesamte ursprünglich gemessene Abstand war ein Budget-Effekt. Das ist der lehrreichste Fehler dieser Messreihe, weil er in beide Richtungen täuschte: Er behauptete einen Effekt, den es nicht gibt, und er verdeckte den, den es gibt — nämlich den Einfluss des Token-Budgets (92,0 % → 98,0 % bei sonst identischen Bedingungen). Lehre für jeden Paarvergleich: **zuerst `max_tokens` beider Läufe vergleichen.** Gleiche Aufgaben und gleiches Modell heißen noch nicht gleiche Bedingungen. Und ein eindrucksvoll aussehender p-Wert prüft nicht, ob überhaupt das Richtige verglichen wurde. ## Was die Zahlen deshalb bedeuten **Belastbar:** * Die getesteten Varianten unterscheiden sich nicht. Gepaart geprüft mit dem exakten McNemar-Test: bei HumanEval+ **0 von 21** Paarungen signifikant (kleinster p-Wert 0,219), bei MATH-500 **0 von 6**. Weder die neuere Generation noch die höhere Quantisierung bringt einen messbaren Vorteil. * Von den beantworteten Mathematikaufgaben sind 139 von 140 richtig. * Die Fehlschläge sind überwiegend Generierungskollapse, keine Rechenfehler. * Bei gleichem Budget bringt Reasoning auf MATH-500 keinen messbaren Vorteil (147 gegen 146 von 150, p = 1,0000). Der Denkmodus kostet dort 32 Prozent mehr Token, ohne die Trefferquote zu heben. * Das Token-Budget ist der eigentliche Hebel: 8.000 → 24.000 Token heben dieselben 150 Aufgaben von 92,0 % auf 98,0 %. **Nicht belastbar:** * Jeder Vergleich mit publizierten MATH-500-Zahlen. Andere Grader, anderer Umfang, unbekannte Budgets — siehe die Einordnung in der Modellkarte. * Die Fehlerquote bei Budgets zwischen 8.000 und 24.000 Token. Gemessen sind nur die beiden Endpunkte; wo dazwischen der Ertrag abflacht, ist offen. ### Warum gepaart und nicht über Konfidenzintervalle Eine frühere Fassung argumentierte mit überlappenden 95-Prozent-Intervallen. Das ist zwar nicht falsch, aber unnötig schwach: alle Varianten bearbeiten **dieselben** Aufgaben. Damit tragen nur die Aufgaben Information, bei denen genau eine von zwei Varianten besteht — und der exakte McNemar-Test wertet genau diese aus. Er ist deutlich empfindlicher als der Vergleich zweier unabhängiger Intervalle und findet trotzdem nichts. Das ist ein stärkeres Ergebnis als „die Intervalle überlappen". Zur Einordnung der Empfindlichkeit: bei etwa zehn abweichenden Aufgaben bräuchte es ein Verhältnis von 9:1, um Signifikanz zu erreichen. Beobachtet wurden Unterschiede von 1 bis 4 Aufgaben. Wer hier einen Unterschied behaupten will, braucht einen größeren Aufgabensatz, nicht eine andere Rechnung. ## Was noch aussteht 1. **Reasoning-Läufe der übrigen Varianten** (Q6_K, Qwen3.6, BF16) — bisher liegt nur für Q8_0 ein Lauf mit vollem Reasoning vor 2. **Kontaminationsprüfung** per Fortsetzungstest 3. **Größerer Aufgabensatz** (MBPP+ zusätzlich zu HumanEval+), um überhaupt die Empfindlichkeit für Variantenunterschiede zu bekommen 4. **Die eine Aufgabe, die auch mit 24.000 Token nicht fällt** (`intermediate_algebra/1350`) — bisher der einzige verbliebene Fehlschlag des Reasoning-Laufs ## Mitgelieferte Werkzeuge | Datei | Zweck | |---|---| | `bench_mathe.py` | Messlauf gegen MATH-500 / GSM8K | | `selftest_mathe.py` | 47 Prüfungen des Vergleichs — **vor** jedem Lauf ausführen | | `nachmessen_omega.py` | misst abgeschnittene Aufgaben nach, mit Schleifenerkennung | | `neubewerten.py` | wertet gespeicherte Läufe mit korrigiertem Vergleich neu | | `mcnemar.py` | gepaarter Signifikanztest über alle Variantenpaare | | `run_omega.sh` | zweistufige Reasoning-Messung mit gemessenem statt geratenem Budget | | `lib_testserver.sh` | trennt Testserver von Produktion beim Aufräumen | Alle Rohdaten liegen unter `bench/` — je Aufgabe die gelieferte Antwort, die erwartete, der Token-Verbrauch und der Abbruchgrund. Wer die Auswertung anzweifelt, kann sie nachrechnen. ### Ein Wort zu `lib_testserver.sh` Die Datei sieht nach Nebensache aus, hat uns aber einen halben Messtag gekostet. Die Benchmark-Skripte räumten mit `pgrep -x llama-server` auf — und trafen damit auch die Produktivdienste, weil die ebenfalls `llama-server` heißen. Der Ersatz filtert über die systemd-Zugehörigkeit. Die erste Fassung dieses Filters prüfte auf `*.service*` und war ebenfalls falsch: der Kontrollgruppenpfad einer Benutzer-Shell lautet `…/user@1001.service/tmux-spawn-….scope`. Das Muster passte, der Testserver galt als geschützt und überlebte den Abbau — mit 33 GB belegtem VRAM, sodass die Produktivmodelle nicht mehr luden. Richtig ist der Pfadpräfix `/system.slice/`. Wer solche Aufräumlogik schreibt, lässt sie **melden**, was sie beendet hat, und prüft danach, was überlebt hat.