# Why Corrupted Training Data Doesn't Show Up as High Loss

> Source: <https://dev.to/bedvibe_studios/why-corrupted-training-data-doesnt-show-up-as-high-loss-1ibp>
> Published: 2026-08-25 03:06:06+00:00

*Originally published at ai.bedvibe.studio.*

There is an assumption almost every practitioner carries without examining it: **if your dataset has bad samples in it, the loss will tell you.** Corrupted rows spike. Broken files stick out. Sort by per-sample loss, look at the top of the list, and there is your garbage.

I believed it too. Two separate failures in my own work say it is wrong, and they fail in the same direction — quietly.

While validating [trainproof](https://github.com/Mormolykos/trainproof) I ran a controlled fault-injection study: one base setup, a Qwen2.5-3B QLoRA, run six ways, three seeds each, eighteen runs total. Every log ships in the repo so the verdicts can be checked rather than believed.

One configuration shuffled the dataset's labels into pure noise. The labels no longer corresponded to the inputs at all. This is not a hard dataset or a noisy dataset. It is a dataset that **cannot be learned**, because there is no relationship left in it to learn.

That run **reduced its loss by 62%.**

On its own curve it was textbook-healthy — a clean downward slope, no spike, no plateau, nothing a human or a rule would flag. It was learning nothing useful. It was memorising the statistics of noise, which any sufficiently large network will happily do. From a single run's loss curve it is indistinguishable from a real one.

That is where the assumption broke for me. Not "loss is a weak signal for this." *Loss is not a signal for this at all, in isolation.*

The second failure came from real work rather than an experiment, and it is the one I think about more.

Building a text-to-speech corpus of roughly 110,000 recordings, a small number of the files were pure loud white noise. Not corrupted in the file-format sense — they opened fine, played fine, had valid headers and valid duration. They simply contained no speech. Just noise, at volume.

They did not surface as high-loss outliers.

Being precise about the epistemic status of this one matters: **those training logs no longer exist.** I cannot show the numbers and I am not going to reconstruct them from memory. It is a production observation, not a measurement. Treat it as the anecdote that sent me looking, and treat the fault-injection study above as the part carrying evidence.

But the two line up, and that is the reason to write it down.

The mechanism is the same in both cases, and the surprise goes away once you see it.

We treat "noise" as a synonym for "unpredictable" and then quietly assume a model will fail loudly on it. White noise is not unpredictable in the way that matters to a loss function. It is *stationary* and *uniform*. Its distribution is simple and consistent. A network fits that distribution quickly and cheaply — and fitting it registers as loss going down.

Shuffled labels are the same story from the other side. The mapping is destroyed, so nothing generalisable remains, but the network can still memorise the marginal statistics of the targets. Loss falls. Nothing spikes.

**In both cases the model learned something. It just was not the thing you wanted.** The loss function has no opinion about which of the two it did.

Two things follow and neither is exotic.

**Compare against a baseline; do not judge in isolation.** The shuffled-labels run becomes obvious the moment you put it beside a known-good run and look at the *relative* floor each one reaches — the corrupted run's floor sits in a different regime entirely. One run alone lies; two runs side by side tell the truth. That is why trainproof has a `compare`

mode at all: not as a convenience, but because single-run rules provably cannot catch this class of failure.

**Check the data as data, before training.** This is the part I got wrong for longer than I would like. I was inferring dataset quality from the training curve, which is an indirect measurement of an indirect measurement. For audio the checks are cheap and direct: spectral flatness, dynamic range, silence ratio, speech-band energy. A pure white-noise file is trivially separable from speech by any of them — *if you look at the audio.* It is not separable by looking at the loss.

This generalises past my two cases, and it is worth stating plainly:

**A loss curve measures whether the model is fitting something. It does not measure whether that something is your task.**

Any corruption that replaces your signal with a distribution the model can fit will pass every loss-shaped check you own. Truncated samples, silence, duplicated rows, label noise, wrong-language text, empty targets — none of these are guaranteed to spike. Some of them are guaranteed *not* to.

The failures that burn the most GPU hours are not the ones that crash. They are the ones that look exactly like success.

The fault-injection logs are all in the [trainproof repo](https://github.com/Mormolykos/trainproof), including the shuffled-labels run and a 9.8-hour Coqui XTTS fine-tune that diverged on its own with nobody touching it.

If you have hit a failure mode a deterministic check would have caught, tell me on the repo — it goes in, with credit.
