Experiment B
ConfirmedWhy an effective batch size of 1 broke a LoRA fine-tune
A high learning rate with an effective batch of 1 cost 2.43 nats. Four independent checks, covering learning rate, batch size, gradient clipping and a loss spike, converged on the same cause.
Every number below is from the recorded run linked above, on an earlier build. Rerunning the commands at the end of this page can give different numbers.
What this run establishes. A learning rate of 5e-4 with an effective batch size of 1 regressed the capability by 2.43 nats, flipping 15 of 16 eval items. Four separate checks fired, drawing on three different inputs, the config, the trainer's logged gradient norms and the loss curve, and all four point at the same instability. This is the run that best shows why the audit reads dynamics and not just config.
The setup#
| Base model | unsloth/Llama-3.2-1B-Instruct |
| Training data | 800 clean Alpaca examples, no planted defects |
| Injected defect | learning_rate = 5e-4 with per_device_train_batch_size = 1, no accumulation |
| Capability | badconfig_tiny_batch_high_lr, 16 eval items |
| Engine | datainf, gradient index 47e9f30e2514b76bf4e3 |
How badly did it break?#
| metric | base | tuned | delta | 95% CI | items | verdict |
|---|---|---|---|---|---|---|
loglik |
-5.0489 | -7.4831 | -2.4342 | [-3.0370, -1.7874] | 16 | regressed |
15 of the 16 eval items flipped from right to wrong.
Which checks fired?#
Four, and the interesting part is that they come from different places.
| Check | Severity | What it said | Read from |
|---|---|---|---|
config.lr_too_high |
high | Effective LoRA learning rate is high (lr=0.0005 × alpha/r=2 = 0.001) | trainer config |
config.small_effective_batch |
medium | Effective batch size 1 with lr=0.0005 is unstable | trainer config |
dynamics.always_clipping |
medium | Gradient norm was at the clip threshold for 97% of logged steps | trainer logs |
dynamics.loss_spike |
medium | 1 loss spike above 3× the median loss | trainer logs |
The learning-rate check reports the effective rate, not the configured one: LoRA scales updates by
alpha/r, so a nominal 5e-4 at alpha/r=2 behaves like 1e-3. Reading the configured number alone
would have understated the problem by a factor of two.
dynamics.always_clipping at 97% is the most diagnostic of the four. Gradient clipping firing
occasionally is normal. Firing on essentially every step means the true gradient never reaches the
optimizer. The updates are all the same magnitude, pointed in whatever direction a single example
happened to suggest. That is a symptom no config check could see, because it is not in the config.
gradian diagnose --dataset train.jsonl --run runs/my-finetuneAll 41 checks are listed on the Diagnostics page.
Was the data blamed?#
No, and correctly not.
| cluster | n | signed influence | share of negative | mean per example |
|---|---|---|---|---|
| 100 | 800 | -1.3e+04 | 100.0% | -16.25 |
One cluster holding all 800 examples at a near-uniform -16.25 each. As in the epoch-count run, a flat distribution across the whole dataset is what a config fault looks like through the influence lens. Nothing to delete.
Caveats reported on this run#
- The base model scored only -5.05 before training, so this capability was largely absent beforehand and Gradian says the data diagnosis explains little. The four config and dynamics findings carry this report.
- One example (0.1%) had a truncated target, incidental to the injected defect.
Reproducing it#
python experiments/gpu/run_gpu_suite.py --experiment B --model unsloth/Llama-3.2-1B-InstructDetails in GPU validation.