| # M1 findings — a 1.5B SFT process-verifier hits an arithmetic-verification ceiling |
|
|
| **Behavior:** Model V, a generative process verifier that reads a problem + a step-indexed |
| solution and returns the 0-based index of the first wrong step (`-1` = all correct), scored on |
| **ProcessBench** (first-error F1) with **PRMBench** as an adversarial check. |
|
|
| **Headline:** across two data recipes, more data, and higher LoRA rank, fine-tuning **did not |
| teach a Qwen2.5-Math-1.5B model to localize math errors** on ProcessBench. It instead made the |
| model *more* confident that solutions are correct. The failure is concentrated on **arithmetic** |
| verification, which a 1.5B model cannot do reliably without a calculator — exactly why GenPRM-1.5B |
| (the sub-4B precedent) needed **code execution**, a component we deliberately scoped out. This is |
| the sub-4B fragility `notes/research-small-vs-large-math.md` warned about, observed directly. |
|
|
| ## Setup |
| - Base: `Qwen/Qwen2.5-Math-1.5B-Instruct` (Apache-2.0, 4096 ctx). QLoRA, TRL 1.7.1 SFT. |
| - Data: PRM800K first-error labels (MIT), critiques distilled from `claude-opus-4-8`, |
| deduped vs ProcessBench/MATH-500. Two recipes (below). |
| - Eval: ProcessBench (objective F1) + PRMBench (adversarial). Objective checkers, **no LLM judge**. |
| - Baseline to beat: GPT-4o ProcessBench avg F1 = **61.9** (4-subset average). |
|
|
| ## Two data recipes tried |
| - **v1 — rationalized:** teacher told the gold index, writes a consistent critique. 1,430 examples |
| (rebalanced 50/50), LoRA r=16. |
| - **v2 — genuine detection:** teacher critiques *blind*; keep a critique only if its predicted |
| index matches the PRM800K gold (rejection sampling, **77% keep-rate**). 8,127 examples |
| (naturally ~50/50), LoRA r=32. This is the "distill the process, not the style" fix. |
|
|
| ## Results (ProcessBench gsm8k, 100 random examples) |
|
|
| | model | decode | acc_error | acc_correct | F1 | pred=−1 rate | |
| |---|---|---|---|---|---| |
| | base (untuned) | greedy | 0.089 | 0.855 | 0.161 | **0.76** | |
| | **v1** (rationalized, 1.4k, r16) | greedy | 0.111 | 0.945 | 0.199 | **0.83** | |
| | **v2** (genuine, 8.1k, r32) | greedy | 0.089 | 0.982 | 0.163 | **0.92** | |
| | v2 | Maj@4 | 0.067 | 1.000 | 0.125 | **0.94** | |
|
|
| **Reading it:** |
| - **Fine-tuning raised the "all-correct" rate (0.76 → 0.83 → 0.92)** — SFT taught the model to |
| *pass* solutions more confidently, the opposite of a verifier's job. `acc_error` never moved off |
| the base's ~0.09. |
| - **The "better" recipe was worse here:** v2 (genuine detection, 5.7× data, 2× rank) collapsed to |
| −1 *more* than v1 and scored *below* it on gsm8k. More/cleaner data did not help — a capability |
| signal, not a data-quantity signal (cf. LoRA-Learns-Less: hard new skills need more than low-rank |
| small-data SFT). |
| - **Maj@k hurts a non-confident verifier:** sampling scatters the error-index votes while −1 stays |
| the modal vote, so majority amplifies the −1 collapse (Maj@4 worse than greedy). Maj@k only helps |
| once the base predictions are good (the GenPRM regime). |
|
|
| ## The bright spot that explains the failure — PRMBench (196 modified, Maj@1) |
| - **detection 0.413** (flags *some* error on 41% of erroneous items), localization 0.148, |
| false-positive 0.205. |
| - Per category: **confidence 0.60, step_contradiction 0.50, domain_inconsistency 0.46, |
| counterfactual 0.46**, circular 0.39, missing_condition 0.39, deception 0.30, **redundancy 0.26**. |
| |
| The same model that flags errors only ~8% of the time on gsm8k flags them **41%** of the time on |
| PRMBench — because PRMBench's injected errors are **structural/logical** (circular reasoning, step |
| contradictions, confidence), which are detectable from language, whereas gsm8k errors are |
| **arithmetic**, which a 1.5B model can't verify by "reading." V learned to catch the errors it can |
| *reason about* and punts (→ −1) on the ones requiring *computation*. |
| |
| ## Diagnosis (why SFT alone can't fix it) |
| 1. **Arithmetic-verification ceiling.** 1.5B can't reliably recompute steps, so it hedges to "looks |
| correct" on arithmetic-heavy gsm8k. GenPRM-1.5B needed **code execution** to reach 63 F1. |
| 2. **The decision is a needle in the critique.** With `completion_only_loss` over ~400-token |
| critiques, the boxed index is ~1 token; SFT optimizes critique *prose* (token-acc 0.78) and |
| under-weights the actual verdict. |
| 3. **Distribution shift.** Trained on MATH-based PRM800K (opus critiques); ProcessBench-gsm8k |
| solutions come from other models with different, arithmetic-heavy error styles. |
| |
| ## What this validates (the honest thesis) |
| The project's premise — "a small model can win on the *easy side* of the generator–verifier |
| asymmetry" — holds **only where the checkable signal is cheap** (a compiler, a step label the model |
| can *read*). For **arithmetic** step-checking, a 1.5B model without a calculator is on the *hard* |
| side after all. This is a concrete, reproducible instance of the note's "sub-4B evidence is thin" |
| caveat, with the mechanism identified. |
| |
| ## Next steps (decided) |
| 1. **7B verifier** — retrain V on `Qwen2.5-Math-7B-Instruct` (Apache, fits the 80GB A100). Tests |
| whether raw capability alone lifts arithmetic verification. `configs/verifier_v_7b.yaml`. |
| 2. **Code execution (GenPRM's actual recipe)** — let V run Python to check steps, targeting the |
| arithmetic ceiling directly. The principled fix; bigger build. |
| |
| ## Reproduce |
| `results/processbench_base.json`, `processbench_tuned*.json`, `prmbench_tuned.json` (this dir). |
| Datasets: `42e/mathcompose-verifier` (v2, genuine detection). Code: `42e/mathcompose`. |
|
|