Self-Training and Pseudo-Labeling
Self-training teaches a new model from the old model's most confident predictions, growing labeled data without growing the labeling bill.
Why Does This Exist?
Labeled images run out fast while unlabeled ones pile up. Training only on the labeled slice wastes the pile, but trusting every prediction poisons training with confident mistakes.
Self-training takes the middle path. Train a teacher on labeled data, predict the unlabeled pool, keep the confident slice as pseudo-labels, and retrain a student on the union. This page covers that outer loop specifically. The umbrella mechanisms live in semi-supervised learning, the threshold specialist is FixMatch, and the averaging teacher is mean teacher.
Think of It Like This
A senior who grades practice papers
A senior solves a thousand problems with answer keys, then attempts five thousand more without keys and marks only the solutions they feel sure about. A junior studies the solved thousand plus the confident attempts together.
Confidence is the marking, and retraining rounds are school terms. The analogy stops at calibration: seniors know their limits better than neural nets, whose confidence needs its own checking.
How It Actually Works
Round one trains on labeled images only. Round two runs the teacher over unlabeled images and keeps predictions above or the top- per class to protect the tail. Round three retrains from scratch or fine-tunes on labeled plus pseudo-labeled data, sometimes with stronger augmentation on the pseudo slice. Repeat until gains flatten, refreshing pseudo-labels each round so fixed mistakes do not fossilise.
Worked example
Start: labeled street images, model at accuracy. Teacher predicts unlabeled frames; clear confidence with roughly precision on a probe, adding about correct and wrong labels. Retrain on mixed images reaches . The wrong ones are the drift tax, paid for free teachers.
Code
Confident-slice selection with class balance guard.
def select_pseudo(max_probs: list[float], tau: float = 0.9) -> tuple[int, float]: """Count and share of predictions clearing the confidence gate.""" kept = sum(1 for p in max_probs if p >= tau) # hard gate per image return kept, kept / len(max_probs)
print(select_pseudo([0.95] * 1800 + [0.6] * 3200)) # -> (1800, 0.36)Watch Out For
Retraining on the same mistakes each round
Freezing pseudo-labels once and retraining for many rounds bakes early errors in deeper each time. The symptom is accuracy rising one round then sliding as wrong labels compound.
Refresh predictions every round and cap pseudo weight below labeled weight. Track probe precision of the kept slice, not just its size.
The Quick Version
- Self-training loops teacher prediction, confident selection, and student retraining.
- Gate at or top- per class keeps the tail represented.
- Worked numbers: of kept at share, to accuracy.
- About wrong labels ride along as the drift tax.
- Refresh pseudo-labels each round and weigh them below true labels.