CoolFace
Datasetpublic

yyuan244/speculative-reasoning-matheval-4b-sweep

MathEval sweep — speculative reasoning on Qwen3-4B Per-sample generations and grading for four arms of a MathEval run, measuring what speculative reasoning costs and saves against a base model that does not speculate. Code and write-up: yurun-yuan/speculative-reasoning — see docs/05-rl-4b.md. The arms All four answer the same 1,547 MathEval problems under a 20,000-token response budget. split model runtime base_plain Qwen/Qwen3-4B plain — no speculation… See the full description on the dataset page: https://huggingface.co/datasets/yyuan244/speculative-reasoning-matheval-4b-sweep.

sourceHugging Faceapache-2.0updated 13d agoView on Hugging Face
0likes74downloads
Dataset Card

MathEval sweep — speculative reasoning on Qwen3-4B

Per-sample generations and grading for four arms of a MathEval run, measuring what speculative reasoning costs and saves against a base model that does not speculate.

Code and write-up: yurun-yuan/speculative-reasoning — see `docs/05-rl-4b.md`.

The arms

All four answer the same 1,547 MathEval problems under a 20,000-token response budget.

splitmodelruntime
base_plainQwen/Qwen3-4Bplain — no speculation
rl_step0the SFT start — Q3-4B-own-d06-SFT-e2, not publishedspeculative
rl_step27yyuan244/Qwen3-4B-spec-grpo-density, step 27speculative
rl_step45same repo, step 45speculative

rl_step0 is the checkpoint the RL run started from: Qwen3-4B fine-tuned for 2 epochs on a speculative corpus built from its own rollouts, filtered to at least 0.6 hand-off sites per 1k main-line tokens. The weights are not on the Hub; the recipe that produces them is `scale-4b/own-corpus-assemble-sft.sh` and it is described in `docs/04-model-scale.md`.

In the speculative runtime the model may pause mid-thought, write a <Pending> task and a <Predict> guess, and carry on under <Assumed/> while a check branch settles the task. On MATCH the branch is discarded unread; on MISMATCH it is spliced in and the guess is withdrawn. Check branches draw from the same 20k budget as the main line.

Sampling and grading

AIME24, AIME25 and AMC23 are sampled 32× per problem; the other 1,447 problems once. That is 4,647 rows per arm.

Grading averages within a problem first, then across problems, so the 100 competition problems contribute 100 votes rather than 3,200. Reproduce it from this data with:

python
import collections
from datasets import load_dataset

ds = load_dataset("yyuan244/speculative-reasoning-matheval-4b-sweep", split="rl_step27")
by_problem = collections.defaultdict(list)
for r in ds:
    by_problem[(r["data_source"], r["uid"])].append(r["correct"])
accuracy = sum(sum(v) / len(v) for v in by_problem.values()) / len(by_problem)

This returns the accuracy field of the matching summary-*.json, exactly, for all four arms. The same fold over critical_path returns mean_critical_path.

Single-sample scoring is not equivalent: the three competition sets read .5667 / .4333 / .8500 for rl_step0 at one sample per problem, 7 to 11 points below their 32-sample values, from draw luck alone.

Results

armaccuracyvs basecritical pathvs basemain linesitestruncated
base_plain.6836—7,743—7,7430.091
rl_step0.6485−3.508,274+6.9%7,3672.32.105
rl_step27.6600−2.357,779+0.5%6,8693.02.092
rl_step45.6411−4.246,674−13.8%4,7016.76.034

By source — accuracy:

sourcensamplesbasestep 0step 27step 45
AIME2430960.6448.5635.5521.4740
AIME2530960.5427.4448.4406.4188
AMC23401,280.9211.8750.8828.8508
MATH500500500.9180.8980.9180.8980
Minerva272272.4118.3971.4081.3787
OlympiadBench675675.6133.5644.5719.5615

By source — critical path:

sourcebasestep 0step 27step 45step 45 vs base
AIME2412,74414,92914,63413,732+7.8%
AIME2514,43316,19315,74514,500+0.5%
AMC237,8828,4428,1817,259−7.9%
OlympiadBench9,68510,3299,8118,432−12.9%
MATH5004,9655,2734,7584,227−14.9%
Minerva6,7237,0616,5965,083−24.4%

Schema

One row per sample.

fieldtypemeaning
armstringwhich of the four arms
data_sourcestringmath_eval_aime24, …_aime25, …_amc23, …_math500, …_minerva_math, …_olympiadbench
uidint32problem id, stable within a data_source
sample_idxint320–31 on the competition sets, 0 elsewhere
problem, answerstringthe prompt and the reference answer
textstringthe full generation, including any spliced-in resolve bodies
runtimestringplain or speculative
stop_reasonstringstop, length, context_full, max_sites
correctfloat321.0 / 0.0, requires a closed </think> and a \boxed{}
correct_no_think_reqfloat32same without the </think> requirement
truncatedfloat321.0 if the response hit the 20k budget
spine_tokensint32the response as written
check_tokensint32all check-branch tokens
mismatched_check_tokensint32check tokens at MISMATCHED sites only
critical_pathint32spine_tokens + mismatched_check_tokens — a matched branch is treated as free
discarded_tokensint32continuation thrown away by a rollback
n_sites, n_mismatchint32hand-off sites, and how many mismatched
siteslist of structper site: site_index, pending, predict, verdict, check_text, check_tokens, check_on_spine, discarded_continuation, discarded_tokens

sites is an empty list for every base_plain row.

Files

summary-<arm>.json carries the aggregate for each arm, including per_source breakdowns and stop_reasons. These are the same files checked into `eval-results/` in the repo.