Is a +5.5% improvement on GPQA Diamond normal when full fine-tuning an 8B model on CPU with recycled hardware?

Hi everyone!
We are a team of AI enthusiasts who started learning Linux and understanding how language models work at the beginning of this year. We are not experts or professionals; we do this purely as a hobby and out of a desire to learn and contribute.

We have built a home server (Z6 architecture) using old, second-hand parts. Due to our limited resources, we run our Full Fine-Tuning tests on 8-billion parameter models (8B) using strictly CPU and RAM.

Our current goal is to understand and validate if our approach is moving in the right direction. For training, we used a dataset of 144,000 words structured into 6 independent blocks (roughly ~42,000 real tokens per block). Processing these 6 blocks marks the completion of Epoch 1, which corresponds to our Checkpoint-6.

To evaluate our progress, we used the lm-eval library with a task we believe is highly objective: GPQA Diamond Zeroshot (graduate-level questions).

1. Base Model Evaluation (Dolphin 3.0 Llama 3.1 8B Puro FP32)
This is the exact command we executed on our machine:

lm_eval run \
  --model hf \
  --model_args pretrained=/xxxx/Dolphin3.0-Llama3.1-8b-Puro-FP32 \
  --tasks gpqa_diamond_zeroshot \
  --num_fewshot 0 \
  --batch_size 1 \
  --device cpu 

Results obtained:

  • Task: gpqa_diamond_zeroshot | Version: 2.2

  • Metric / Value: acc: 0.2475 (24.7%) | acc_norm: 0.2475

  • Stderr: ±0.0307

2. Our Full Fine-Tuning Evaluation (Checkpoint-6 / Epoch 1)

lm_eval run \
  --model hf \
  --model_args pretrained=/xxxx/checkpoint-6 \
  --tasks gpqa_diamond_zeroshot \
  --num_fewshot 0 \
  --batch_size 1 \
  --device cpu 

Results obtained:

  • Task: gpqa_diamond_zeroshot | Version: 2.2

  • Metric / Value: acc: 0.303 (30.3%) | acc_norm: 0.303

  • Stderr: ±0.0327

Our questions for the community (Could you help us understand?):
Since we are learning step by step, we would truly appreciate it if you could help us confirm two things:

  1. Is the base model score accurate? We want to know if anyone running this exact command for Dolphin 3.0 on different hardware gets the same ~24.7% accuracy, or if hardware differences can influence the evaluation results.

  2. Is our improvement significant, or does it mean nothing? Going from 24.7% to 30.3% (+5.5%) on GPQA Diamond in the very first epoch while training purely on CPU… Is this expected behavior, a genuinely solid result, or could it be a symptom of an underlying issue (like data leakage/overfitting) that we are missing?

We are doing this to master the art of Fine Tuning, and our ultimate goal is to share and gift all of this knowledge to the community down the road.

These questions might seem obvious to many, but they are completely new to us.
Thank you so much for your time and for helping us learn!

Hmm… maybe a few different issues are getting mixed together here?:thinking::


I think the result is worth following up, but I would separate at least three questions:

  1. Is the 24.75% baseline itself reproducible?
  2. Does 24.75% → 30.30% represent a stable improvement on these same 198 GPQA-Diamond items?
  3. If it is a real improvement on GPQA, is it generalization, specialization, or some overlap/evaluation effect?

My short answer would be:

  • I do not know of a useful universal rule saying that “an 8B model should gain about X points on GPQA after one epoch.” The effect depends too much on the training data, LR/optimizer schedule, exact base artifact, prompt/evaluation contract, etc.
  • +5.55 percentage points is large enough to investigate, but not enough by itself to call the fine-tune definitively better.
  • CPU vs GPU can produce numerical differences, and PyTorch explicitly does not guarantee identical results across CPU/GPU/platforms, but I would not make hardware the first explanation for a difference of this size. I would first lock down the exact model artifact and evaluation setup.
  • I also would not jump directly to “data leakage.” It is a useful control to check, not a diagnosis.

The cheapest/highest-information next step, in my opinion, is to stop looking at the aggregate score for a moment and look at which individual questions changed.

You have:

  • base: 49 / 198
  • checkpoint: 60 / 198
  • net change: +11 correct answers

But there are very different ways to get net +11:

Case A:
wrong -> right: 11
right -> wrong: 0

Case B:
wrong -> right: 20
right -> wrong: 9

Case C:
wrong -> right: 50
right -> wrong: 39

All three give the same +11 aggregate improvement, but they tell very different stories.

Because both models are evaluated on the same 198 questions, this is a paired comparison, not really two independent accuracy measurements. There is actually a recent lm-evaluation-harness issue about exactly this problem: comparing two runs on the same documents is better handled with item-level paired statistics such as McNemar’s test or a paired bootstrap than by just combining the two reported standard errors.

So if you still have the models/checkpoints, I would make this the default route:

1. Re-run base and checkpoint with exactly the same evaluation contract.
2. Save per-sample results (`--log_samples`).
3. Count:
   - wrong -> right
   - right -> wrong
   - unchanged
4. Only then decide how strong the +11 result looks.

lm-eval explicitly supports log_samples for per-sample/post-hoc analysis, so this does not require building a new evaluation system.

I would probably do that before spending time reproducing the run on different hardware.

One other thing I would lock down first: what exactly is Puro-FP32?

Your baseline path is called something like Dolphin3.0-Llama3.1-8b-Puro-FP32, while the public model is dphn/Dolphin3.0-Llama3.1-8B.

That may be completely harmless — e.g. perhaps it is just your own FP32 conversion — but for reproduction I would treat those as two different artifacts until confirmed otherwise.

If Puro-FP32 is simply:

official Dolphin weights
-> converted/upcast to FP32
-> same tokenizer
-> same config
-> same chat template

then great: that is easy to document.

If anything else changed during conversion/export, then “can somebody reproduce 24.75% on Dolphin?” becomes two different questions:

Can somebody reproduce official Dolphin?
                  |
                  +-> Can somebody reproduce this exact Puro-FP32 artifact?

That distinction might save quite a lot of debugging.

Also record the exact:

model revision / weight hash
tokenizer revision
config
dtype
PyTorch version
Transformers version
lm-eval version or git commit
GPQA task version
chat-template setting
random/few-shot seeds

The current harness deliberately records quite a bit of this information for reproducibility, including the selected chat template when one is used.

About CPU vs GPU

Your hardware question has a somewhat boring answer: yes, differences are possible in principle, but I would use hardware as a later branch in the diagnosis.

PyTorch’s current reproducibility documentation says that completely reproducible results are not guaranteed across releases/platforms, and specifically says CPU and GPU executions may differ even with identical seeds. Its numerical-accuracy notes also explain why mathematically equivalent floating-point computations need not be bitwise identical.

That matters here because the current gpqa_diamond_zeroshot task is a multiple_choice likelihood task, not a sampled free-form generation task. If two answer choices have very close scores, a small numerical difference could in principle change the winning choice.

But I would diagnose it in this order:

Does the base score reproduce on the same machine?
|
+-- No
|   -> first investigate model/evaluator/version/dtype/nondeterminism
|
+-- Yes
    -> compare base vs checkpoint item-by-item
        |
        +-- clear excess of wrong->right
        |   -> stronger evidence for a training effect
        |
        +-- lots of churn in both directions
            -> investigate margins / evaluation sensitivity

Only after the baseline is stable on one machine would I spend effort on CPU-vs-GPU reproduction.

The fact that the training hardware is old/recycled does not by itself make the experiment invalid. It mostly makes the experiment unusual and slow. The important question for the benchmark result is whether the inference/evaluation contract is reproducible.

Why I would be careful comparing your number with old Dolphin / Open LLM Leaderboard numbers

There is a slightly confusing historical trap here.

The Dolphin model card contains an old Open LLM Leaderboard GPQA number, but the leaderboard’s displayed GPQA number is not simply raw four-choice accuracy.

The Hugging Face documentation explains the GPQA leaderboard normalization: because four-choice random guessing is 25%, the leaderboard rescales raw GPQA accuracy relative to that 25% lower bound.

There is even an old leaderboard discussion showing the calculation explicitly.

So a number such as:

GPQA: 4.36

on an old model card should not be compared directly with:

gpqa_diamond_zeroshot acc = 0.2475

They are different representations, and potentially different task configurations as well.

There is an older lm-eval issue where someone saw exactly this kind of local-vs-leaderboard mismatch.

There is a second complication: GPQA’s implementation has changed.

The current GPQA task README records a v2.1/v2.2 preprocessing fix. An earlier answer-preprocessing regex could remove meaningful text inside brackets. The project later removed that processing because it corrupted some GPQA answers. The current zero-shot YAML identifies itself as version 2.2.

This is not a reason to distrust GPQA. It is just a reason to pin the exact task revision when comparing historical numbers.

So I would use old public Dolphin scores only as a rough historical sanity check, not as proof that your 24.75% baseline is wrong.

Chat formatting is another cheap control I would consider

Dolphin is an instruction/chat model and its model card documents its chat template.

lm-eval supports --apply_chat_template, and its current evaluator even emits a warning when something appears to be an instruct/chat model but no chat template is applied. The implementation documents apply_chat_template, and the model guide explains that the selected template is saved as part of the evaluation configuration for reproducibility.

I would not say:

You forgot the chat template, therefore your score is wrong.

For multiple-choice likelihood evaluation there is no universal guarantee that adding the chat template produces a “more correct” number.

I would instead treat it as a cheap A/B control:

same model
same task
same examples
same versions
same dtype

A: current/raw formatting
B: `--apply_chat_template`

Then inspect whether predictions themselves are stable.

As a small sanity check on this idea, I tried a public proxy experiment with the public Dolphin 8B model loaded in 4-bit and a fixed 32-item public MMLU-Pro subset. I did not use it as an official MMLU-Pro benchmark: I held the visible question/options fixed and only compared A-J label likelihoods with raw formatting vs the tokenizer’s chat formatting.

In that tiny proxy:

prediction changed: 14 / 32 items

correct -> wrong: 4
wrong -> correct: 1

So the formatting change was clearly capable of moving individual decisions in that setup.

That does not show that chat formatting caused your GPQA improvement:

  • different benchmark,
  • tiny sample,
  • 4-bit proxy,
  • public Dolphin rather than your FP32 artifact,
  • no fine-tuned checkpoint.

I would only take it as evidence that “run a cheap template A/B before drawing conclusions” is a reasonable control rather than a purely theoretical concern.

It was also interesting that changed predictions tended to be closer decisions in that proxy, which is the kind of thing I would expect if formatting is moving examples near a likelihood boundary.

What would make the +11 result more convincing?

I would think of confidence as accumulating through several mostly independent controls rather than trying to obtain one magic significance number.

1. Same-machine baseline stability

Run the base model twice under the same contract.

If the selected answers are essentially identical, that removes a lot of noise from the rest of the investigation.

2. Paired item-level comparison

This is the most important one.

Suppose the result is:

wrong -> right: 15
right -> wrong: 4
net: +11

That would be a fairly interpretable pattern.

If instead it is:

wrong -> right: 45
right -> wrong: 34
net: +11

I would be much more interested in why so many items are unstable.

You can do a formal McNemar test if useful, but even the raw 2x2 table is already much more informative than two independent standard errors.

The current lm-eval discussion around paired significance testing makes the same point: when both models see the same documents, the observations are paired.

3. Look at margins, if convenient

For changed questions, compare the likelihood gap between the top two answer choices.

If most changed items were nearly tied in the base model, then a modest parameter change moving them across the decision boundary is a very plausible explanation.

If the fine-tune is overturning previously very high-margin answers, that is a different and arguably more interesting phenomenon.

4. One independent held-out check

I would not turn this into a giant benchmark suite.

One or two small additional evaluations are enough to answer a useful question:

GPQA improves
+ another related held-out task improves
+ a general retention task stays roughly stable

is more suggestive of transferable improvement than:

GPQA improves
but several unrelated abilities fall sharply

Neither result is inherently bad. The second may simply mean the model specialized.

There are published/open model examples where fine-tuning improves GPQA while other benchmark scores regress, so this is not a hypothetical failure mode. It is one reason I would distinguish GPQA improvement from overall model improvement.

About leakage / contamination

I would treat this as a sanity check, not an accusation.

The lm-eval decontamination documentation gives the basic motivation nicely: a benchmark is intended to measure generalization, and direct test-set material in the training data makes that interpretation weaker.

The first useful question is simply the provenance of the ~144k-word training corpus.

For example:

Was it written/collected independently?

Did it include benchmark-derived QA material?

Did it include model-generated explanations of public benchmark questions?

Could GPQA questions, answer choices, or close paraphrases have entered through another dataset/source?

If the answer is clearly “independent material,” that already helps.

If provenance is mixed, an exact/near-overlap scan can be useful. lm-eval documents an n-gram-based approach, but I would not interpret “no n-gram match” as proof that semantic contamination is impossible. It is just one useful control.

Conversely, finding one weakly similar passage would not automatically invalidate the whole gain either. The useful output is:

which examples overlap?
how directly?
were the answers available?
does the improvement remain on clearly clean items?

rather than a binary label of “contaminated / not contaminated.”

One small training-side branch: what does 'six independent blocks' mean operationally?

I would only investigate this if each block was actually trained as a separate Trainer/process invocation.

If all six blocks were simply parts of one continuous training run, there is probably nothing special here.

If instead the workflow was approximately:

train block 1
save model
start a new Trainer on block 2
save model
start a new Trainer on block 3
...

then I would check whether only the model weights were carried forward, or whether the optimizer and LR-scheduler states were resumed too.

Hugging Face’s Trainer.train(resume_from_checkpoint=...) explicitly restores model/optimizer/scheduler state when resuming from a checkpoint.

Those two procedures are not necessarily equivalent:

one continuous six-block optimization trajectory

versus

six sequential weight-only training jobs with optimizer/scheduler reset

Both can be valid experiments, but “one epoch” means something slightly different operationally.

I would not make this a primary suspect without seeing how the blocks are implemented; it is just something worth documenting if the training was restarted six times.

If I were trying to get the most information for the least work

I would probably do only this first:

A. Identify exactly what `Puro-FP32` contains.
B. Pin the evaluation contract/version.
C. Re-run base + checkpoint with `--log_samples`.
D. Make the four-cell flip table.

Then:

If base itself is unstable:
    investigate evaluation/artifact/runtime first.

If base is stable and wrong->right clearly exceeds right->wrong:
    treat the fine-tune effect as increasingly plausible.

If many answers churn both ways:
    inspect margins and formatting sensitivity.

If GPQA improvement looks stable:
    check corpus provenance / overlap.

If it still looks clean:
    try one small independent held-out/retention evaluation.

Only if reproduction still differs across machines:
    spend time isolating CPU/GPU/backend effects.

That path keeps the interesting part of your experiment intact — you really did observe 11 additional correct GPQA-Diamond answers after the fine-tune — while separating the question of what caused those 11 answers from the question of whether the experiment was “good” or “bad.”

At this stage I would describe the result as something like:

a promising +11/198 paired observation that is worth decomposing, rather than either dismissing it as noise or declaring a +5.5-point capability gain yet.

If the item-level flips come back clean, that would already make the result substantially more informative without requiring another expensive training run.

Hi! Thank you so much for taking the time to write such a detailed and guidance-oriented response. This is exactly the kind of technical perspective we need to understand what is happening under the hood.
To clarify your question about Puro-FP32:
You hit the nail on the head regarding CPU behavior. Our home server runs on an older HP Z6 workstation with dual CPUs that lack native hardware acceleration for BF16. We discovered that running inference/evaluation in BF16 forces the CPU to perform heavy numerical upcasting and translations in real-time, making the 198-question GPQA test take around 120 minutes per run.
By converting the official Dolphin 3.0 weights strictly to FP32 (maintaining the exact same tokenizer, config, and chat template), the CPU processes the mathematics natively, and the execution time drops to just 25 minutes (almost 5 times faster). We verified that the aggregate baseline score remains virtually identical between formats on our machine (moving only between 0.2424 and 0.2474 due to minor floating-point precision shifts). So yes, it is simply the official artifact converted to FP32 for pure CPU optimization.
Regarding our fine-tuning dataset, it consists exclusively of common, non-scientific Spanish text structured into 6 sequential chunks to avoid CPU/RAM overflow. There is no technical data or overlap related to the GPQA questions. We have observed that the improvement during the first epoch tends to vary depending on the learning rate applied, usually landing between 0.27 and 0.30 accuracy. Depending on the schedule, this score oscillates epoch to epoch—sometimes plateauing, sometimes dipping slightly—but consistently remaining above the stock Dolphin 8B baseline.
We completely agree with your advice regarding the paired comparison analysis. Looking at the aggregate score isn’t enough; we need to see the actual item-level flips and “churn” (Case A, B, or C).
We re-ran the GPQA evaluation using the --log_samples flag to extract the per-sample logs. Then, we cross-referenced the doc_id samples one by one. Here are the exact 4-cell mutation matrix results (McNemar paired data) for the 198 items of GPQA Diamond:
• 1. Wrong → Right (Flipped to Correct): 30 questions
• 2. Right → Wrong (Cost of Forgetting): 19 questions
• 3. Always Right (Stable Correct): 30 questions
• 4. Always Wrong (Stable Incorrect): 119 questions
Summary:
• Total Base Correct: 49 / 198 (24.75% accuracy)
• Total Checkpoint Correct: 60 / 198 (30.30% accuracy)
• Net Improvement: +11 clean responses
As you can see, the data points directly to “Case B”. There is a significant structural shift (30 gains vs 19 losses) rather than a flat improvement or superficial noise.

*edit: Environment and Evaluation Metadata for Reproducibility
To ensure full transparency and allow anyone in the community to lock down and reproduce our results, here are the exact environment specifications, library versions, and evaluation configurations extracted directly from our system logs:

  1. Library Versions (Python 3.10 Virtual Environment)
    • torch: 2.10.0+cpu
    • transformers: 5.5.3
    • peft: 0.18.1
    • lm-eval: 0.4.12

Evaluation Configuration (config metadata from JSON)
json
{
“model”: “hf”,
“model_args”: {
“pretrained”: “/xxxx/Dolphin3.0-Llama3.1-8b-Puro-FP32”
},
“model_num_parameters”: 8030277632,
“model_dtype”: “torch.float32”,
“model_revision”: “main”,
“model_sha”: “”,
“batch_size”: “1”,
“batch_sizes”: ,
“device”: “cpu”,
“use_cache”: null,
“limit”: null,
“bootstrap_iters”: 100000,
“gen_kwargs”: {},
“random_seed”: 0,
“numpy_seed”: 1234,
“torch_seed”: 1234,
“fewshot_seed”: 1234
}

Dataset and Evaluation Details:
• Task Version: gpqa_diamond_zeroshot (Version 2.2)
• Chat Template: Clean, un-padded weights upcast to float32 running native inference contracts .
• Execution Contract: Single-item evaluation (batch_size: 1) via likelihood multiple-choice tokens .
*

What are your thoughts on these specific item-level flips? What does this type of mutation matrix tell you about the training effect on the model’s underlying reasoning? We would love to hear your interpretation.
Thank you again for guiding us along this path!

Thanks. I think this moves things forward quite a bit:


The new information removes two of the biggest uncertainties from my previous reply:

  • Puro-FP32 is just the official Dolphin 3.0 artifact converted to FP32 while keeping the tokenizer/config/chat template unchanged, and your BF16-vs-FP32 baseline check stays around the same ~24–25% range.
  • Your training corpus is ordinary non-scientific Spanish text rather than GPQA/science-derived material, so direct benchmark memorization is now a much less natural first explanation.

And the item-level matrix is much more informative than the original aggregate score:

Wrong -> Right: 30
Right -> Wrong: 19
Right -> Right: 30
Wrong -> Wrong: 119

So my current interpretation would be:

The fine-tune is clearly changing the model’s behavior on GPQA, and those changes are directionally favorable to the checkpoint — but the matrix alone does not yet tell us that the model’s underlying scientific reasoning improved.

That distinction is important.

The checkpoint did not simply “learn 11 new questions.” There were at least 49 correctness-state changes: 30 favorable and 19 unfavorable. The net result is +11, but underneath that aggregate number there is substantial redistribution.

Also, because these are the same 198 items evaluated by both models, the 30-vs-19 comparison is paired data. This is exactly the kind of comparison discussed in the current lm-evaluation-harness paired-significance issue.

For your matrix, an exact two-sided McNemar test is roughly:

discordant items: 49
checkpoint-favored: 30
base-favored:       19

two-sided exact McNemar p ~= 0.15

So I would describe the evidence as:

behavioral change:       clear
direction:               favors checkpoint
net GPQA improvement:    observed (+11 / 198)
statistical certainty:   still fairly limited
reasoning improvement:   not established yet

In other words, 30 vs 19 is interesting and worth pursuing, but I would not call it a statistically established reasoning gain from this matrix alone.

The good news is that I do not think you need another expensive training run to learn much more.

The next useful information may already be inside your existing --log_samples

Since you already generated the per-sample logs, there are a few cheap analyses that would tell us substantially more about what kind of change the fine-tune caused.

And importantly: there is no need to publish or share the raw GPQA logs, question text, answer choices, or prompts.

The GPQA dataset card explicitly asks users not to reveal examples online, to reduce leakage into future training corpora. Derived counts/statistics are enough for everything below.

If you want to go one level deeper, I would prioritize only these:

1. How many Wrong -> Wrong items changed to a DIFFERENT wrong choice?
2. How did the correct-answer margin change?
3. Did the A/B/C/D prediction distribution shift?
4. If you have multiple checkpoints already evaluated:
   are the same items improving repeatedly,
   or is the set of correct items constantly changing?

Those four tell rather different stories.

1. The 119 Wrong -> Wrong items may hide a lot of additional movement

Your current four-cell matrix only tracks correctness.

For example, both of these are counted as Wrong -> Wrong:

Base:       B
Checkpoint: B
Gold:       D

and:

Base:       B
Checkpoint: A
Gold:       D

But they are behaviorally very different.

So I would split the 119 into:

Wrong -> same Wrong
Wrong -> different Wrong

Then your total answer-choice churn becomes something like:

Wrong -> Right
Right -> Wrong
Wrong -> different Wrong
Right -> Right
Wrong -> same Wrong

If almost all of the 119 remain on exactly the same wrong answer, then the change is relatively localized.

If a large fraction jump between different wrong choices, then the fine-tune is moving the model’s decision distribution much more broadly than the +11 aggregate suggests.

That would make me more cautious about describing the result as “11 newly acquired pieces of reasoning.” It would look more like a broad redistribution of answer preferences, with a modest net benefit on GPQA.

Conversely, if wrong-choice churn is low and the 30 gains are relatively concentrated/stable, that would make the improvement interpretation cleaner.

2. The likelihood margins may tell us whether these are boundary flips or stronger changes

The current gpqa_diamond_zeroshot task is a multiple_choice task.

Its scoring decision is basically based on the likelihoods assigned to:

(A)
(B)
(C)
(D)

after reading the question and four answer choices.

That means the most interesting quantity for each item is not only:

correct / incorrect

but something like:

score(correct option) - score(best incorrect option)

Call that the gold margin.

Then compare that margin before and after fine-tuning.

A few possible patterns:

Pattern A:
Most gains had tiny negative base margins,
then became tiny positive margins.

Interpretation:
The fine-tune mostly nudged borderline decisions across the boundary.
Pattern B:
Gold margins improve broadly,
including on items whose final correctness does not change.

Interpretation:
Stronger evidence that the checkpoint systematically became
more favorable to the correct answer under this evaluation contract.
Pattern C:
Gains and losses both involve large-margin reversals.

Interpretation:
Much larger representational/decision redistribution;
worth investigating before calling it a simple improvement.

This distinction matters especially because GPQA v2.2 here is not directly grading a generated reasoning trace. It is measuring which multiple-choice continuation receives the highest model likelihood.

So the mutation matrix alone cannot separate:

better scientific reasoning

from things such as:

changed calibration
changed answer preference
changed confidence
changed decision boundaries
changed response formatting priors

or some combination of them.

There is relevant work showing that multiple-choice LLM evaluation can be sensitive to the model’s prior preference for answer IDs rather than only the semantic answer content; see PriDe / ICLR 2024.

That does not mean answer-ID bias explains your result. It just gives us another testable mechanism besides “reasoning improved.”

3. A/B/C/D prediction counts are a very cheap calibration sanity check

Because the task ultimately maps the shuffled answer choices onto (A)(D), I would count how often each label wins before and after fine-tuning:

             Base   Checkpoint
A              ?
B              ?
C              ?
D              ?

If you see something approximately like:

Base:
A 48
B 52
C 47
D 51

Checkpoint:
A 49
B 50
C 48
D 51

then there is no obvious global answer-ID shift.

But if it becomes something like:

Base:
A 48
B 52
C 47
D 51

Checkpoint:
A 79
B 36
C 40
D 43

then I would investigate whether part of the GPQA movement is a change in option-label calibration.

Again, this would not invalidate the training result.

It would just separate:

content-sensitive change

from:

global answer-label preference change

which are different mechanisms.

If the logs contain all four likelihoods, an even cleaner version is to compare the average checkpoint-minus-base change for each label after centering within each question. That can detect a global (A)/(B)/(C)/(D) preference shift without needing to expose any GPQA content.

4. If you already have several epoch/LR evaluations, item persistence may be more informative than another benchmark run

You mentioned that GPQA tends to stay around roughly 0.27–0.30 depending on LR/schedule, sometimes plateauing and sometimes dipping between epochs.

That creates another useful distinction:

Scenario 1:
roughly the SAME questions remain improved across checkpoints

versus:

Scenario 2:
accuracy stays near 0.28–0.30,
but completely different questions are correct each time

Those look identical in an aggregate score table but imply very different stability.

For each item you can make a tiny trajectory such as:

Base -> Epoch1 -> Epoch2 -> Epoch3

wrong -> right -> right -> right
wrong -> right -> wrong -> right
right -> wrong -> wrong -> right
...

If the 30 gains are mostly persistent, that would strengthen the case for a stable fine-tuning effect.

If large numbers of items continuously flip in both directions while aggregate accuracy stays similar, I would interpret the system as being in a fairly unstable decision regime.

Again, no new training is necessary if those checkpoints and logs already exist.

About the Spanish/non-scientific training data

This part is actually interesting.

Since your corpus is ordinary Spanish text and apparently contains no science/GPQA material, I would currently put direct knowledge memorization fairly low on the list of explanations.

But that does not imply that the GPQA score should remain unchanged.

Instruction/SFT can change model confidence and calibration beyond the exact language/domain used for tuning. For example, recent work on multilingual calibration after instruction tuning found substantial changes in confidence across languages even where accuracy gains were small or absent.

That paper is obviously not your experiment — different models, benchmarks, training setup, and research question — so I would not use it as an explanation of your result.

But it is a useful reminder that:

fine-tuning on Spanish text can change how an English multiple-choice decision is scored without the Spanish corpus containing the scientific facts required by GPQA.

So at this point I would keep several mechanisms alive:

A. Some genuinely useful general capability improved.
B. The model's calibration / likelihood geometry changed.
C. Existing knowledge became easier/harder to select under this prompt.
D. Some abilities improved while others were forgotten.
E. Several of the above happened simultaneously.

The mutation matrix is completely compatible with a mixture.

One important branch concerning your repeated GPQA evaluations

There is one methodological detail I would keep separate from the mutation analysis.

You mentioned that you have observed different GPQA scores under different learning rates and schedules.

The important distinction is how those scores were used.

If LR/schedule/checkpoint choices were made independently of GPQA

For example:

we chose the training schedule first,
then recorded GPQA afterward

then repeated measurements are mostly useful trajectory observations.

If GPQA results influenced which LR/schedule/checkpoint you kept

For example:

this LR scored higher on GPQA,
so we continued/tuned around that LR

then I would start treating GPQA as a validation/model-selection set, rather than as a completely untouched final test.

That is not a mistake; validation sets are supposed to be used that way.

It just changes what the score means.

Repeated/adaptive reuse of a finite holdout can produce selection bias; this is the general problem studied in work such as Reusable Holdout.

But I would also avoid the opposite exaggeration:

“You looked at GPQA multiple times, therefore the result is invalid.”

That does not follow either. Empirical work on test-set reuse has found that repeated reuse does not automatically produce severe overfitting in every realistic setting.

The practical rule I would use is simple:

If GPQA helped choose the model:
    call it validation/model-selection evidence,
    and eventually use one untouched benchmark for confirmation.

If GPQA never influenced training/model selection:
    the concern is much smaller.

No need to turn this hobby experiment into a huge evaluation campaign.

Where I think your original question stands now

With your new information, I would update my earlier answer approximately like this:

1. Is the ~24.7% base result believable?

Much more so now.

You have checked BF16/FP32 behavior on your own hardware and are seeing only a small baseline movement around ~24.2–24.7%, while FP32 drastically reduces runtime on your CPUs.

That makes the FP32 conversion itself a much weaker explanation for the +11 checkpoint difference.

It still does not prove every other machine will reproduce exactly 24.75%, but I would now regard your baseline as internally reasonably stable rather than obviously suspicious.

2. Does the +5.5-point result mean nothing?

No.

The item-level data shows a real behavioral redistribution:

30 improvements
19 regressions

That is more informative than the original aggregate score alone.

3. Does it establish a significant improvement?

Not yet, statistically.

The directional imbalance is interesting, but with only 49 discordant items the exact two-sided McNemar result is still around p ~= 0.15.

I would treat that as evidence worth following, not a settled result.

4. Does it show that underlying scientific reasoning improved?

The mutation matrix alone cannot establish that.

The current GPQA task is a multiple-choice likelihood measurement. A fine-tune can move that measurement through reasoning, calibration, confidence, answer preference, or representation changes.

Your training corpus makes direct GPQA memorization less plausible, which is useful information, but it does not uniquely identify which remaining mechanism produced the score gain.

5. What would convince me most without another expensive experiment?

Probably this, in order:

Existing logs only:

1. Confirm same prompt/target hashes.
2. Count Wrong -> different Wrong.
3. Compare gold margins for gains/losses.
4. Check A/B/C/D prediction-frequency / score shifts.
5. If multiple checkpoints already exist,
   check whether the same gains persist.

Then stop.

If those analyses show:

little wrong-choice churn
+ broad gold-margin improvement
+ no strong answer-ID shift
+ the same gains persist across checkpoints

then I would become substantially more comfortable describing the effect as a stable, content-sensitive improvement under the GPQA evaluation contract.

I would still reserve “underlying reasoning improved” for evidence from an independent evaluation, but the interpretation would be much stronger than it is from accuracy alone.

If instead you find:

large wrong-choice churn
+ mostly tiny-margin flips
+ strong A/B/C/D prior movement
+ different items flipping every epoch

then the better description would probably be:

the fine-tune substantially changed the model’s decision/calibration landscape, and GPQA happens to receive a modest net benefit.

Both outcomes would be useful things to learn about full fine-tuning.

And again, if you decide to calculate any of these: derived counts, margins, hashes, and aggregate tables are enough. Please do not post the raw GPQA questions/options or raw logs containing them.

At this point I think your experiment has already answered something useful: the +5.5-point aggregate was not simply “11 extra answers appearing from nowhere.” There is a much broader 30-vs-19 redistribution underneath it.

The next interesting question is no longer just “did the number go up?” but “what kind of model change produced that redistribution?”

Hi! Thank you so much for the analysis and for dedicating your time, your help is truly appreciated.

We updated our Python evaluation script to extract the exact changes in the response ID prediction distribution and the incorrect response variation from our --log_samples files. Here are the precise total statistics you suggested:

=== UNIFIED MATRIX REPORT ===

  1. Wrong → Right (Flipped to correct): 30

  2. Right → Wrong (Cost of forgetting): 19

  3. Always Right (Remain correct): 30

  4. Always Wrong (Remain incorrect): 119


Total Base Correct: 49 / 198
Total Checkpoint Correct: 60 / 198
Net improvement: +11 responses

Response frequency in Base: A:40, B:20, C:61, D:77, Unknown:0
Response frequency in Checkpoint: A:115, B:13, C:30, D:40, Unknown:0
Out of the 119 constant incorrects, changed to a different incorrect letter: 46

**

To delve a bit deeper into this experiment, we have been running multi-epoch/multi-LR training campaigns (usually fixed) over the last few months. On broader reference benchmarks, such as MMLU, we have observed very specific persistence trends:**

• Completely neutral domains, such as History or general high school knowledge, remain practically identical to the baseline.

• Logical and scientific segments, such as formal logic, conceptual physics, and jurisprudence, show a consistent and sustained improvement across all checkpoints.

• On the contrary, tasks with a strong opinion component or aligned with safety, such as moral disputes, tend to drop in score (probably because our fine-tuning frees the model from Dolphin’s artificial conversational restrictions, giving it a more human and unrestricted language profile).


We are enthusiasts who only learned to configure these evaluations just a week ago, so we are discovering the necessity of these detailed logs on the fly!

In operational terms, our fine-tuning script delivers each block of approximately 42,000 real tokens in clean, sequential chunks, without complex packaging tricks so we don’t exceed our RAM limit.
A single epoch takes exactly 6 hours and 6 minutes on our recycled HP Z6. Since it is summer here and our testing room usually stays between 26°C and 35°C without air conditioning, we have intentionally reduced the frequency of our Xeon cores to 1700 MHz to manage thermal loads safely. With a standard clock configuration, this execution contract would be significantly faster.

We do not feed larger blocks due to lack of RAM; the Z6 consists of two old Xeon processors with 192GB of old and slow DDR4 RAM, all purchased second-hand at the beginning of the year.
The fine-tuning script we have is just a draft, as it accepts changes: it supports different models and different sizes by changing just a few lines in a few seconds; it works just the same with models in bf16 (it converts them to FP32), old models, new ones, or of different sizes. The dataset was created without even knowing about the existence of GPQA or MMLU, which is why there is no contamination in the results, and why there are questions that, even if they seem obvious, we have not foreseen nor do we know about.

We would love to know your opinion on this significant shift towards option “A” and how you evaluate this particular calibration movement.

*Edit: Quick update. Now I understand the A’s, probably caused by a starting learning rate in the first epoch that was too high, we will do new tests.

We are currently running a new, highly controlled training campaign that starts with a safer rate and uses a custom progressive decay schedule to avoid this bias. We want to ensure clean, balanced, and reliable data, and we will share the new mutation matrix here as soon as it’s ready. Thank you for the help! And may this serve for others to learn how to detect a GPQA that is not what it really seemed.

We are going to perform this on a stock Llama 3.1 8B which gives better results, leaving Dolphin “parked”, even though the learning rates they support are completely different, with Llama 3.1 8B being much more sensitive.

DEEP DIVE: Multi-Epoch Evolution, Matrix Mutation Analysis & The “Agio Project” Release

Hi community! Following up on the invaluable feedback from @John6666 regarding item-level paired tracking and label calibration bias, we have completed a highly controlled 4-epoch Full Fine-Tuning campaign.

Instead of continuing with the aligned Dolphin artifact, we pivoted to the stock Llama-3.1-8B-Base (upcast to native FP32 for CPU optimization on our recycled dual-Xeon HP Z6 workstation).

Our goal was to inject a highly conceptual, philosophical dataset on sovereignty (Project Agio, ~144k words structured into 6 sequential chunks) while stress-testing the model’s cognitive resistance against the brutal GPQA Diamond Zeroshot benchmark (198 graduate-level questions).

The chosen read level (LR) was selected arbitrarily, as we are unfamiliar with Llama 3.1 8b; it was simply a test. The forge script supports many combinations, from fixed LR to ascending or descending LR. We have long observed that the model (at least Dolphin) exhibits an evolutionary path in stages, epoch by epoch; we assume this is determined by the dataset. This dataset is intended to be expanded to provide the necessary support, shortened to approximately 35,000 words, or simply not used.

Here is the exact training log telemetry using our custom step-decay schedule (manually shifting the Learning Rate at block/epoch boundaries):

Upd   Epoch    Loss     GradNorm    LR          EMA      Total Time
1     0.1667   1.6859   3.4876      1.00e‑05    —        —
2     0.3333   1.8040   20.6797     1.00e‑05    —        —
3     0.5000   1.3812   4.6068      1.00e‑05    —        —
4     0.6667   1.6652   3.8544      1.00e‑05    —        —
5     0.8333   1.8257   4.0823      1.00e‑05    —        —
6     1.0000   1.7623   3.4413      1.00e‑05    1.7623   6.6h
----------------------------------------------------------------------
Manual Step-Decay Applied → LR = 8.50e‑06
7     1.1667   1.3851   6.2314      8.50e‑06    —        —
8     1.3333   1.1901   3.8045      8.50e‑06    —        —
9     1.5000   1.4801   3.0416      8.50e‑06    —        —
10    1.6667   1.4405   3.0448      8.50e‑06    —        —
11    1.8333   0.9914   3.1060      8.50e‑06    —        —
12    2.0000   1.0396   3.5031      8.50e‑06    1.6900   13.2h
----------------------------------------------------------------------
Manual Step-Decay Applied → LR = 7.00e‑06
13    2.1667   0.9911   2.5642      7.00e‑06    —        —
14    2.3333   0.9051   4.4004      7.00e‑06    —        —
15    2.5000   0.8479   2.4686      7.00e‑06    —        —
16    2.6667   0.7444   2.7129      7.00e‑06    —        —
17    2.8333   1.0358   5.6552      7.00e‑06    —        —
18    3.0000   1.0685   3.5526      7.00e‑06    1.6279   19.8h
----------------------------------------------------------------------
Manual Step-Decay Applied → LR = 5.00e‑06
19    3.1667   0.8954   3.7733      5.00e‑06    —        —
20    3.3333   0.5906   3.2848      5.00e‑06    —        —
21    3.5000   0.6591   3.2758      5.00e‑06    —        —
22    3.6667   0.8914   2.3639      5.00e‑06    —        —
23    3.8333   0.6586   2.6604      5.00e‑06    —        —
24    4.0000   0.5713   2.0467      5.00e‑06    1.5222   26.4h

1. Macro Evaluation Trajectory (GPQA Diamond Zeroshot)

  • Llama-3.1-8B-Base (Stock): 31.82% Accuracy (63 / 198) | Stderr: ±0.0332
  • Checkpoint-6 (Epoch 1): 30.30% Accuracy (60 / 198) | Stderr: ±0.0327
  • Checkpoint-12 (Epoch 2): 28.79% Accuracy (57 / 198) | Stderr: ±0.0323
  • Checkpoint-18 (Epoch 3): 28.79% Accuracy (57 / 198) | Stderr: ±0.0323
  • Checkpoint-24 (Epoch 4): 31.31% Accuracy (62 / 198) | Stderr: ±0.0330

Note: For comparison, a massive public alignment run like Dolphin 3.0 Llama 3.1 8B drops to 24.75% on this exact evaluation contract due to the “alignment tax”. Our late-stage checkpoints completely recovered from the initial drop, defending the base model’s reasoning capabilities.


2. Micro-Item Paired Analysis: Breaking the Calibration Shock

By running standard lm-eval with --log_samples and passing the outputs through our custom paired item-level cross-referencing tool, we tracked the exact mutation dynamics across the timeline.

Epoch 1 (Checkpoint-6) vs Stock Base: The “A” Position Bias Shock

  • Unified Matrix: Wrong ➔ Right: 5 | Right ➔ Wrong: 8 | Always Right: 55 | Always Wrong: 130
  • Label Distribution Shift: Base (A:123, B:28, C:32, D:15) ➔ Checkpoint-6 (A:138, B:15, C:28, D:17)
  • Acid Test (New gains distribution): 4 out of 5 new correct answers occurred simply because the model picked ‘A’.
  • Diagnosis: The high initial LR (1e-5) induced positional calibration shock. The model panicked on hard questions and collapsed into the ‘A’ token.

Epoch 2 & 3 (Checkpoint-12 & 18): Latent Rebalancing

  • Unified Matrix (Epoch 3): Wrong ➔ Right: 6 | Right ➔ Wrong: 12 | Always Right: 51 | Always Wrong: 129
  • Label Distribution Shift: ‘A’ frequency actively dropped from 138 down to 112, while ‘D’ choices climbed cleanly to 35.
  • Acid Test: 4 out of 6 new correct choices were won by selecting ‘D’, with only 1 coming from ‘A’.
  • Diagnosis: Dropping the LR to 7e-6 stabilized the gradients. The positional bias dissolved, and the model began actively re-evaluating alternate choices.

Epoch 4 (Checkpoint-24) vs Stock Base: Latent Fused Grokking

  • Unified Matrix: Wrong ➔ Right: 10 | Right ➔ Wrong: 11 | Always Right: 52 | Always Wrong: 125
  • Net Score: 62 / 198 (Just one single net response away from stock baseline parity).
  • Label Distribution Shift: Completely normalized (A:111, B:16, C:34, D:37).
  • Acid Test (True Reasoning Recovery): Out of the 10 new clean gains, 6 were achieved on ‘D’, 2 on ‘C’, and only 2 on ‘A’.

If the community finds this paired-mutation data and our progressive step-decay approach valuable, we want to make our intentions completely transparent: we want to give everything away under the CC0 Universal License (Public Domain). Although we could wait longer to complete more campaigns and deliver an irrefutable, perfect model, we prefer to leave that development in the hands of others. We want the final model to emerge from what the community chooses, because we simply no longer have the disk space, resources, or free time to keep pushing forward. It is time to gift everything so that others can decide whether they want to use this logic or not. That is the true purpose of CC0—it is that simple.

We have spent months documenting the entire architecture, and we are ready to open-source the whole ecosystem so that anyone—a factory worker, a student, or a small local business—can build their own independent system right from home, strictly on home hardware, just like us utilizing solar panels to get free energy.

We will release:

  1. The Full “Project Agio” Dataset: ~144k words clean and un-truncated, structured into 6 balanced blocks, containing the syntactic and ethical framework that stabilizes these gradients. They are nothing special, just learning; sometimes they can even introduce noise or cause unexpected output variations, but they show a path and were written as we moved forward.

  2. The Z6 Custom Forge Script: Our native FP32 execution contract with automated execution variables, zero-fragmentation memory padding, and internal thread isolation. It has its limitations that can be fixed or removed, and it can be simplified to the maximum or expanded.

  3. Quality Assurance Audit Logs: The actual questions and answers from each forge, epoch by epoch, at different learning rates. We will deliver everything: logs, full tables, etc.

“Agio” is simply a word we chose—a framework representing a simple, logical way of thinking. In this specific use case, it acts as a translation layer that facilitates deep syntactic and conceptual understanding between language-based systems.

To be completely honest with you: we are not ML engineers. We work in factories. We built our dual-Xeon Z6 workstation from second-hand parts at the beginning of this year, and we started learning Linux just months ago. We deeply understand language, words, and structural logic, but we lack the academic training of hyperparameter optimization. Everything you see here comes from basic, pure logic.

We don’t have Venture Capital backing, corporate titles, or academic degrees. We have a dual-Xeon workstation, a shared table, and the firm belief that true clarity does not come from memory, but from companionship.

This 4-epoch trajectory check was simply a test to see if you, the open-source community, find this approach interesting or useful. We don’t want to work in isolation; we want to build what helps the community. Therefore, we ask you with total transparency: Do you think this framework has merit? Would you like us to document and share it?

We would love to propose an experiment. If anyone wants to recommend a specific Learning Rate schedule (whether it’s an aggressive decay, a custom cosine curve, or a fixed strategy from epoch to epoch), please drop it in the comments. We can configure our forge script and start a brand new training campaign tomorrow before going to work, and stop it on Saturday. It could be a success or a failure.

The Z6 is certainly limited. In recent months, after dozens of forges—some lasting up to 200 hours—a model with a high GPQA probably emerged, but since we didn’t know about it, we deleted it. We develop with limited resources and barely have any disk space. Today’s epochs will also be deleted to free up space.

Thank you for helping us learn, adapt, and give back to the community!

I think the result itself is quite meaningful:


The short version is:

  • I would not treat the +5.5 points as “nothing.” The checkpoint clearly changed a lot.
  • I also would not yet read it as “GPQA reasoning improved by 5.5 points.” There is a fairly large answer-selection shift mixed into the result.
  • Before spending more CPU time, I think the highest-information next step is actually very cheap: extract a few aggregate counts from the logs you already have.
  • I would still continue with the stock-Llama + safer-LR experiment. I would just treat that as a new recipe branch, separate from the question of what caused the old Dolphin behavior.

1. About the 24.7% base score

I would not assume that 24.7% is necessarily the canonical Dolphin 3.0 GPQA-Diamond baseline.

There is a useful historical reference point: the public Open LLM Leaderboard detailed run for cognitivecomputations/Dolphin3.0-Llama3.1-8B recorded 0.32828 on leaderboard_gpqa_diamond, i.e. about 32.83% on the 198 Diamond questions:

Open LLM Leaderboard — Dolphin3.0-Llama3.1-8B detailed results

That does not mean your 24.7% is wrong.

It is not an apples-to-apples reproduction. The leaderboard run is from an older evaluation stack, while your run reports gpqa_diamond_zeroshot task version 2.2. GPQA’s lm-eval task has changed since then; in particular, v2.2 removed an older answer-preprocessing regex that could damage valid bracketed answer text:

lm-eval GPQA task changelog

The current zeroshot contract is here:

lm-eval GPQA zeroshot task

Also, the GPQA 4.36 number visible on the Dolphin model card is easy to misread: that is a leaderboard-normalized score, where the four-choice random baseline is mapped to zero. It is not “4.36% raw Diamond accuracy.” Hugging Face documents that normalization separately:

Open LLM Leaderboard score normalization

So if somebody wants to reproduce your 24.7%, I would try to match the evaluation contract before focusing on the CPU model:

same exact model weights / revision
same tokenizer
same lm-eval revision
same GPQA task version
same chat-template setting
same processed answer permutation
same dtype / backend / batch settings
then compare hardware

Hardware can affect exact reproducibility. PyTorch explicitly says that complete reproducibility is not guaranteed across releases/platforms, or even CPU versus GPU with the same seeds:

PyTorch reproducibility notes

So I would not say “hardware cannot matter.”

I just would not make the recycled CPU the first explanation for the pattern you are seeing, especially because the base and checkpoint were evaluated in the same local environment.


2. Is +5.5 points significant, or does it mean nothing?

I think there are actually three different meanings of “significant” here.

A. Did fine-tuning materially change the model’s behavior?

Yes. Very clearly.

The interesting part is not only:

Base:       49 / 198 correct = 24.7%
Checkpoint: 60 / 198 correct = 30.3%

Net: +11 correct

The prediction distribution also moved from:

             Base    Checkpoint
A              40        115
B              20         13
C              61         30
D              77         40

So A increased by 75 predictions.

That alone proves that at least 75 items moved from a non-A prediction to A. There is no way to obtain a net +75 in A without at least 75 such transitions.

You also found that at least 95/198 top-1 answer labels changed, plus 46 wrong → different-wrong cases.

So this was not a tiny perturbation that happened to flip eleven borderline questions. The model’s multiple-choice decision behavior moved substantially.

B. Is +11 correct on 198 questions already strong statistical evidence of better accuracy?

I would call it suggestive, but not strong by itself.

Because the same 198 questions were evaluated before and after tuning, the useful comparison is paired.

From the paired results:

wrong → right: 30
right → wrong: 19

An exact two-sided McNemar test on those discordant pairs gives roughly p = 0.15.

That is not a magic verdict, and “not below 0.05” absolutely does not mean “there is no effect.” It just says that, on a 198-item benchmark, 30 gains versus 19 losses is not yet especially strong evidence if the claim is specifically “general accuracy increased.”

For reference:

statsmodels McNemar test documentation

So I would distinguish:

The model definitely changed.

from:

We have already established a robust +5.5-point improvement in general reasoning.

The first statement looks strong to me. The second still needs a little decomposition.

C. Does this demonstrate +5.5 points of better reasoning?

That is the part I think is still open.

At the moment I would keep at least three mechanisms on the table:

real content-sensitive improvement
+
answer-label / option-position selection shift
+
broader fine-tuning drift or forgetting

They are not mutually exclusive.

The result could contain some of all three.


3. The A = 40 → 115 movement is probably the highest-value clue

This is the part I would investigate before doing another long full fine-tune.

There is prior work showing that LLMs can develop preferences for the option IDs themselves — A/B/C/D — and that moving answer contents between positions can change MCQ performance.

A particularly relevant paper is:

Large Language Models Are Not Robust Multiple Choice Selectors — ICLR 2024

They call this selection bias: the model can assign different prior preference to option tokens such as A/B/C/D independently of the semantic answer contents.

There is also SFT-specific work showing that multiple-choice symbol-selection bias can persist during supervised fine-tuning:

Strengthened Symbol Binding Makes Large Language Models Reliable Multiple-Choice Selectors — ACL 2024

I would treat those papers as evidence that this is a real class of failure mode — not as evidence that they have already explained your checkpoint.

Your A increase could still partly reflect genuine improvement if many of those extra A predictions happened on questions whose correct target was A.

That is why the next tiny diagnostic is so useful.

4. Before another training run, I would extract only these aggregates

No GPQA questions, answer text, prompts, or raw logs need to be posted.

The GPQA dataset card specifically asks users not to reveal benchmark examples online, so aggregate statistics are a nice way to investigate this without exposing the benchmark:

GPQA dataset card

First, I would check whether the processed target letters were identical between the base and checkpoint evaluations:

base/checkpoint target-letter mismatches: ? / 198

Ideally that is:

0 / 198

Then just print:

Gold labels:
A = ?
B = ?
C = ?
D = ?

and two 4×4 tables:

Base: target × prediction

             Pred A  Pred B  Pred C  Pred D
Gold A
Gold B
Gold C
Gold D
Checkpoint: target × prediction

             Pred A  Pred B  Pred C  Pred D
Gold A
Gold B
Gold C
Gold D

That is probably the cheapest high-information diagnostic available now.

No new training required.

No new model download required.

No public GPQA examples required.

From those 32 cells you can immediately see whether the A increase is mostly:

  • correct movement toward gold A,
  • incorrect movement from gold B/C/D into A,
  • or a mixture.
How I would read those two matrices

Case 1 — B/C/D gold rows all start flowing into A

For example, if all three of these jump:

P(pred=A | gold=B)
P(pred=A | gold=C)
P(pred=A | gold=D)

then I would take the global A-selection explanation much more seriously.

That would mean the A = 115 total is not just the consequence of a gold distribution that happens to contain many A answers.

At that point, raw accuracy alone would hide quite a lot of internal movement.

Per-gold-label recall would be more informative:

Recall(A)
Recall(B)
Recall(C)
Recall(D)

Case 2 — most of the added A predictions are on gold-A questions

That would weaken the simple “the model just likes A” interpretation.

The marginal A count could look alarming while actually containing a substantial amount of genuine correction.

In that case I would put more weight on real content-sensitive improvement.

Case 3 — all four recalls improve, but A preference also increases

This would be a perfectly plausible mixed result:

real GPQA improvement
+
a newly exposed/amplified answer-label prior

Those can coexist.

An unwanted selector effect does not automatically invalidate every improvement produced by the checkpoint.

Case 4 — A recall improves while B/C/D recall collapse

Then I would be much more cautious about interpreting the headline 30.3% as broad reasoning improvement.

The aggregate score could be hiding a fairly large tradeoff between classes.

This is also why the ICLR selection-bias work looks at behavior conditioned on the correct option rather than only counting how often each option was predicted.


5. I would keep your new stock-Llama experiment

I do not think the findings above are a reason to stop the project or throw away the next experiment.

I would just separate two questions that are easy to accidentally merge.

Branch A — recipe development

stock Llama 3.1 8B
+ safer/progressive LR
+ your Spanish data

Question:
"Can we build a more stable/better recipe?"

That seems completely reasonable to continue.

But there is a different question:

Branch B — causal diagnosis of the old Dolphin result

same Dolphin base
same data
same order
same optimizer/batch/eval contract
change only LR/schedule

Question:
"Did the aggressive update cause the old drift?"

Changing both the base model and the learning-rate strategy is useful for Branch A, but it cannot isolate Branch B.

That is not a problem as long as the two experiments are interpreted separately.

And given your CPU constraint, I would absolutely not say that Branch B is mandatory. If the practical goal is learning how to make a good model rather than writing a causal study of the old checkpoint, it may not be worth repeating a long full fine-tune just to answer that historical question.

So my default order would be:

1. Existing logs: target consistency + 4×4 matrices
   cost: almost zero

2. If A-selection still looks suspicious:
   same checkpoint, controlled answer-order test
   cost: evaluation only

3. Continue the new Llama + safer-LR recipe
   cost: training

4. Only if you specifically care about proving the old LR mechanism:
   same-Dolphin LR-only control

That gets the cheap information first without blocking the experiment you actually want to run.


About the learning-rate hypothesis

I think your suspicion about the learning rate is reasonable at the broad-drift level.

Fine-tuning can cause catastrophic forgetting or degradation of capabilities learned during pretraining. This is well documented in LLM tuning work:

Revisiting Catastrophic Forgetting in Large Language Model Tuning — Findings of EMNLP 2024

There is also recent work explicitly connecting learning-rate behavior with forgetting during fine-tuning:

Fine-Tuning Without Forgetting via Loss-Adaptive Learning Rates

So a statement like this seems reasonable:

An aggressive full-parameter update could plausibly cause broad drift/forgetting and expose or amplify behavior that was weak in the base model.

What I do not think the evidence supports yet is:

A high learning rate specifically caused the model to prefer Option A.

That second causal step is still missing.

As an engineering reference point only, torchtune’s current Llama 3.1 8B full-finetuning example uses AdamW with lr: 2e-5:

torchtune Llama 3.1 8B full-finetune configuration

I would not treat 2e-5 as a universal “correct” LR. Dataset size, effective batch size, sequence length, optimizer, schedule, model state, and training objective all matter.

It is just a useful reminder that full-parameter post-training recipes usually treat LR as a sensitive recipe choice rather than something with one universally safe number.


If you want to test the Option-A hypothesis directly

After the 4×4 matrices, the cleanest test is conceptually simple:

Keep the checkpoint fixed and move the same answer contents to different A/B/C/D positions.

If the semantic answer stays the same but the chosen answer changes substantially with the letter/position, that is much more direct evidence of an option-ID effect than comparing two separately trained models.

You do not necessarily need all 24 possible permutations.

A cheap smoke test could use two controlled arrangements.

A stronger version could use four cyclic arrangements so that each semantic answer content occupies A, B, C, and D once.

The ICLR paper above uses answer-content permutation as exactly this kind of diagnostic/debiasing tool.

One lm-eval / Datasets gotcha

I would be careful about implementing this by changing only the random seed.

The GPQA preprocessing in lm-eval shuffles the choices, and Hugging Face Datasets can cache the result of a Dataset.map() transform.

The Datasets documentation explicitly says that previous transforms may be loaded from cache and that load_from_cache_file=False or disabling caching forces the mapping function to run again:

Hugging Face Datasets — cache management

So this:

same checkpoint + seed 0
same checkpoint + seed 1

is not by itself proof that you actually evaluated two different answer permutations.

A safer contract would be:

same checkpoint
same lm-eval/task revision
same scoring
same prompt/template

force GPQA preprocessing to recompute
change only the answer permutation

then verify:
the processed target mapping really changed

Even better, if you write a tiny local task variant, make the permutation a deterministic function of something like:

(item_id, permutation_seed)

rather than relying on global RNG state.

This is only a warning for a future permutation experiment. It is not a claim that Datasets caching caused the A=115 behavior in your current checkpoint.


A few smaller interpretation notes

I would call the current observation a selection/decision shift before calling it calibration

In the strict ML sense, calibration is about whether predicted confidence corresponds to empirical correctness probability.

Right now the strong evidence is:

  • changed top-1 choices,
  • changed answer-label distribution,
  • large concentration on A.

So terms like:

  • selection shift,
  • option-ID preference,
  • decision-distribution shift,

are a little safer than “calibration failure” until you also inspect choice probabilities/margins.

Calibration itself can be tested later, but I would put that below the 4×4 table in priority.

I would put direct GPQA leakage fairly low on the list for this particular fine-tuning corpus

From your description, the Spanish training material was created independently and was not assembled from GPQA/MMLU science questions.

That does not mathematically prove zero overlap, and it says nothing about what may have existed in the original model’s pretraining/tuning data, but direct leakage from this new corpus would not be my first explanation for the A=40→115 movement.

The selector/evaluation decomposition is cheaper to check first.

I would also be cautious with the moral_disputes drop

A subject-level MMLU decrease can be useful evidence that the model changed, but I would not use it by itself as evidence that safety constraints were “removed.”

MMLU is also multiple choice, so some of the movement could in principle share the same selector/option-ID effects seen in GPQA.

If that particular result becomes important, the same cheap decomposition — gold-label distribution, prediction-label distribution, per-label recall — would be useful there too.


Where this leaves the original result

My current interpretation would be:

24.7% → 30.3% is worth investigating and worth continuing from.

It is not just meaningless benchmark noise, because the checkpoint’s behavior changed very substantially.

At the same time, I would not yet compress everything that happened into the sentence:

“The model gained 5.5 points of GPQA reasoning ability.”

The much more interesting signal right now may be the A-direction redistribution.

Fortunately, determining whether that is mostly:

real improvement
selection bias
forgetting/drift
or a mixture

does not require another multi-day CPU training run.

The target-consistency count, gold A/B/C/D counts, and two 4×4 matrices from the existing logs should already tell you a lot.

Then you can choose the branch that matches what you actually want to learn:

  • want a better model? Continue the stock-Llama + safer-LR recipe.
  • want to understand the A behavior? Do a fixed-checkpoint permutation test.
  • want to prove whether LR caused the old Dolphin drift? Run the same-Dolphin LR-only control when/if the CPU cost is worth it.

That seems like a good place to keep the experimentation moving without throwing away the interesting result you already have.

Hi John,

I managed to extract the exact aggregate counts and the two 4x4 matrices from my existing logs for the Base (Stock Llama 3.1 8B FP32) and Checkpoint 24 (Epoch 4 of the new recipe with 1e-5 LR).

The results are fascinating and completely clear up the “A-redistribution” mystery.

1. Contract & Target Consistency

  • Base / Checkpoint target-letter mismatches: 0 / 198 (Perfect alignment across evaluations via doc_id).

2. Matrices (target × prediction)

=== BASE (Stock Llama Puro): target × prediction ===
        Pred A  Pred B  Pred C  Pred D
Gold A   117     17      20      11      
Gold B   0       10      0       0       
Gold C   2       0       11      0       
Gold D   4       1       1       4       

=== CHECKPOINT (Epoch 4, 1e-5 LR): target × prediction ===
        Pred A  Pred B  Pred C  Pred D
Gold A   111     9       22      23      
Gold B   0       7       1       2       
Gold C   0       0       11      2       
Gold D   0       0       0       10     

3. How to read these matrices (The Breakdown)

This falls squarely into Case 2 (Genuine content-sensitive improvement) with an interesting baseline twist.

  1. The ‘A’ preference was already present in the Base Model: As we can see in the Base matrix, the model was heavily biased towards predicting ‘A’ out of the box on this specific lm-eval task setup (117 hits concentrated on Gold A, while generating high confusion on Gold B, C, and D row-wise).
  2. The Checkpoint is breaking the positional bias: In Checkpoint 24, the total volume of Pred A actually decreased from 117 to 111. The model is actively moving away from its default blind preference for option A.
  3. True Reasoning Recovery on Gold D: Look at the Gold D row. In the Base model, when the correct answer was D, it blindly threw 4 predictions to A, 1 to B, 1 to C, and only got 4 right. In Checkpoint 24, the confusion towards A dropped to 0, and the correct predictions for D jumped from 4 to 10.

Conclusion on Recipe Branch A

The safer learning rate (1e-5) on full fine-tuning is working beautifully. It did not trigger a selection bias collapse; instead, it is actively mitigating the baseline’s initial positional bias, leading to genuine, content-driven corrections on harder targets like Gold D.

I will confidently proceed with this recipe! Thanks for the diagnostic framework, it saved me days of unguided CPU training.

========================

EDIT / UPDATE:

Hi John,

I need to issue a quick technical correction to the matrices I shared above.

When we ran the initial diagnostic script late last night, we noticed a huge anomaly: the ground truth row (Gold A) was artificially inflated to 165 questions. Looking closely at the code, we realized that the emergency fallback clause (else: gold_real = "A") was capturing every single doctor-level question that the base model and checkpoint consistently failed (119 questions total) and mapping them as “True A”. GPQA Diamond isn’t biased; our fallback logic was.

We updated our data-crossing script to surgically extract the actual, untampered target metadata directly from Meta’s original dataset inside the JSONL files.

Here are the 100% clean and real 4x4 matrices (Target × Prediction) for the Stock Llama 3.1 8B Base vs. Checkpoint 24 (Epoch 4):

=== REAL MATRIX: BASE STOCK LLAMA 3.1 8B ===
        Pred A  Pred B  Pred C  Pred D
Gold A   38      9       6       2       
Gold B   35      10      9       6       
Gold C   25      7       11      3       
Gold D   25      2       6       4       

=== REAL MATRIX: CHECKPOINT 24 (Epoch 4, 1e-5 LR) ===
        Pred A  Pred B  Pred C  Pred D
Gold A   34      5       7       9       
Gold B   30      7       11      12      
Gold C   26      3       11      6       
Gold D   21      1       5       10      

The New (Correct) Scientific Takeaway:

  1. The Baseline Bias is Confirmed: The stock Llama 3.1 8B base model has a severe, native positional primacy bias on this specific lm-eval setup. Faced with extreme difficulty, it shot a massive 123 blind “A” predictions out of 198 questions, ruining its performance on Gold B, Gold C, and Gold D.
  2. True Calibration/Grokking in Epoch 4: Our full fine-tuning recipe on Spanish philosophy is genuinely curing this positional reflex. Checkpoint 24 compressed the blind “A” noise across all rows (dropping total Pred A from 123 to 111).
  3. The Gold D Proof: On questions where the actual answer is D, the Stock Base was guessing wildly (only 4 correct hits). Checkpoint 24 pushed correct hits from 4 up to 10 while heavily deflating the blind attraction to option A.

The net score remains -1 response away from baseline parity (62 vs 63), but the underlying geometry has evolved. The model traded cheap, lucky positional baseline points on Gold A for hard-earned, content-sensitive corrections on Gold D.

Today we’re running a new FFT, using stepped learning rates. While we know the individual learning rates well over time, we don’t know where they lead when stepped. We’ll let the computer run, taking advantage of the long workdays and other commitments we have this week, so it’s not time wasted no matter what. Once the evaluations are complete, we’ll use our new data cross-tabulation script to generate the actual matrices and share the evolution here to observe how the geometry responds.
Thank you for your effort and for helping us interpret it better; we appreciate it.