Mixed Precision Training
Train faster with fp16 and bf16 – half the memory
Mixed precision training uses 16-bit instead of 32-bit floating point numbers for most computations. This halves memory requirements and speeds up training on modern GPUs by 2–3×.
fp32 vs. fp16 vs. bf16 – the detailed comparison
| Format | Bits | Exp. Bits | Mantissa | Numeric Range | Precision | Recommendation |
|---|---|---|---|---|---|---|
| float32 | 32 | 8 | 23 | ±3.4e38 | Very high | Safe, but slow |
| float16 | 16 | 5 | 10 | ±65,504 | Medium | ⚠️ Overflow risk |
| bfloat16 | 16 | 8 | 7 | ±3.4e38 | Low-medium | ⭐ Best choice |
Why bf16 is better than fp16
BFloat16 has the same exponent range as fp32 (8 exponent bits), but fewer mantissa bits. fp16 has only 5 exponent bits → much smaller numeric range → overflow with large activations. bf16 solves this problem.
fp16 overflow problem: If activations > 65,504: → Overflow → NaN → training crashes! Workaround: loss scaling (automatic, but complex) bf16 no overflow: Same numeric range as fp32 → No loss scaling needed → Simpler, more stable GPU support for bf16: NVIDIA Ampere (RTX 30xx, A100): bf16 hardware support ✓ NVIDIA Turing (RTX 20xx, T4): fp16 hardware only ✗ NVIDIA Volta (V100): fp16 hardware only ✗ Apple Silicon (M1/M2/M3): bf16 hardware support ✓ AMD RDNA3+: bf16 hardware support ✓
Automatic Mixed Precision (AMP)
During mixed precision training, not all computations run in 16-bit. Some critical operations stay in fp32:
Mixed precision training – what runs at which precision:
fp16/bf16 (fast, low memory):
✓ Forward pass (activations)
✓ Backward pass (gradients)
✓ Model weights (inference copy)
fp32 (safe, precise):
✓ Master copy of weights (optimizer states)
✓ Weight updates
✓ Loss computation
✓ Batch normalization (statistics)
Result: ~2× less VRAM, 2–3× faster
with minimal quality lossMemory savings from mixed precision
In FrameTrain
Gradient Checkpointing
Halve VRAM by selectively recomputing activations
Gradient checkpointing (also called activation checkpointing) is a technique that reduces VRAM requirements at the cost of some compute time. Ideal when VRAM is the limiting factor.
The problem: activation memory
During normal backpropagation, all intermediate activations (outputs of every layer) must be stored in VRAM to compute gradients:
Normal training (N=32 layers, L=7B):
Forward pass: store all 32 layer outputs
Activation memory: ~4–8 GB (at BS=4, seq=512)
Problem: with large BS or long sequences:
BS=16, seq=2048 → ~32 GB for activations ALONE!
Gradient checkpointing:
Store only every Kth "checkpoint" (e.g. every 4th layer)
During the backward pass: unstored activations
are RECOMPUTED
Trade-off:
Memory: ÷2 to ÷4 (roughly 30–60% less)
Speed: ×0.7–0.8 (20–30% slower)How much memory gradient checkpointing saves
The ultimate memory optimization combo
Maximum memory savings – all tricks combined:
Base 7B model (fp32): 28 GB VRAM
+ Mixed precision (bf16): ÷2 14 GB
+ LoRA (train only adapters): ÷3 ~5 GB gradients
+ QLoRA (4-bit base): ÷4 ~3.5 GB base
+ Gradient checkpointing: -2GB ~4 GB activations
+ Gradient accumulation (BS=1): -1GB ~3 GB batches
Total: ~5–6 GB VRAM for 7B fine-tuning!
→ Possible on an RTX 3070 (8 GB) ✓
Without any optimization: 60+ GB → impossible on a consumer GPUGradient checkpointing in FrameTrain
In FrameTrain, you can enable gradient checkpointing in the Training Panel. It's automatically recommended when the system detects VRAM might get tight. Rule of thumb: always enable it when VRAM < 12 GB and the model has > 1B parameters.
When gradient checkpointing pays off
Early Stopping
Automatically stop at the optimal point
Early stopping monitors the validation loss and automatically stops training when no meaningful improvement is happening anymore. It automatically loads the best checkpoint.
Why early stopping matters so much
Without early stopping
- Training runs all planned epochs
- The model overfits past the optimal point
- Last checkpoint ≠ best checkpoint
- Wasteful: training past the overfitting point is useless
With early stopping
- Training stops automatically at the optimal point
- The best checkpoint is loaded automatically
- No overfitting from training too long
- Saves compute time when a plateau is reached early
Early stopping parameters explained
patience
Typical: 3–5 epochsHow many epochs without improvement are tolerated before stopping.
Effect: Too low: stops too early (during temporary fluctuations). Too high: overfitting happens anyway.
💡 patience=3 for short training runs. patience=5 for long training runs with fluctuations.
min_delta
Typical: 0.0001–0.001Minimum improvement in validation loss to count as "better".
Effect: Prevents stopping when only minimal noise slightly improves the metric.
💡 min_delta=0.001 is a good starting value.
monitor
"val_loss" or "val_accuracy"Which metric is monitored.
Effect: val_loss is more stable and direct. val_accuracy can plateau while val_loss is still decreasing.
💡 Always monitor val_loss, not val_accuracy.
restore_best_weights
True (always recommended)Whether the best checkpoint is automatically loaded when stopping.
Effect: Without: last checkpoint (after overfitting). With: best checkpoint loaded.
💡 Always True. Only exception: if the last checkpoint is explicitly desired.
Early stopping strategy by training type
Short fine-tuning (3–5 planned epochs): patience = 2 min_delta = 0.001 → Little tolerance for fluctuations Medium fine-tuning (5–20 epochs): patience = 3 min_delta = 0.0005 → Standard setup Long fine-tuning (20+ epochs): patience = 5 min_delta = 0.0001 → Enough tolerance for learning curve plateaus Combined with an LR scheduler (ReduceLROnPlateau): LR is reduced on plateau, then 3 more epochs are tried → Early stopping only after that → better use of training
Best practices
ALWAYS monitor val_loss, not train_loss (train_loss keeps decreasing forever)
Enable restore_best_weights=True – otherwise you load the worst model
Save the best checkpoint separately (save_best_only=True)
A patience of 3 survives short spikes without being too lenient
Combine with cosine LR decay: LR cools down before early stopping kicks in
With little data: base early stopping on validation F1, not just loss
Model Ensembles
Combine multiple models for maximum performance
Ensembles combine the predictions of multiple models. They're almost always better than a single model – at the cost of more compute at inference time.
Ensemble methods in detail
Majority Voting (Classification)
Ø +1–5% accuracy typicalEach model gives one class prediction. The most common class wins (like an election).
# Combining 3 model predictions:
predictions = [model1.predict(x), # "positive"
model2.predict(x), # "positive"
model3.predict(x)] # "negative"
from collections import Counter
final = Counter(predictions).most_common(1)[0][0]
# → "positive" (2 of 3 models)Use case: When class labels (not probabilities) are available
Probability Averaging ⭐ (Recommended)
Ø +2–8% typical over a single modelSoftmax probabilities of all models are averaged. Then the highest probability determines the class.
# Averaging probabilities: probs_1 = model1.predict_proba(x) # [0.8, 0.2] probs_2 = model2.predict_proba(x) # [0.6, 0.4] probs_3 = model3.predict_proba(x) # [0.9, 0.1] avg_probs = np.mean([probs_1, probs_2, probs_3], axis=0) # → [0.77, 0.23] final_class = np.argmax(avg_probs) # class 0 = "positive"
Use case: When softmax probabilities are available – almost always better than majority voting
Checkpoint Ensemble
Ø +1–3% typicalDifferent checkpoints from the same training run are combined. Cost-effective – no separate training needed.
# Last N checkpoints from one training run:
checkpoints = [
'model_epoch_8.pt',
'model_epoch_9.pt',
'model_epoch_10.pt'
]
# Average predictions from all checkpoints
ensemble_probs = np.mean([
load_and_predict(ckpt, x)
for ckpt in checkpoints
], axis=0)Use case: When multiple full training runs are too expensive – reuses existing checkpoints
Diverse Ensemble (different seeds/HPs)
Ø +3–10% typicalSame model, but different random seeds or slightly different hyperparameters. More diversity = better.
# 5 runs with different seeds:
models = []
for seed in [42, 123, 456, 789, 1337]:
model = train_with_seed(seed, lr=2e-5)
models.append(model)
# Ensemble of the 5 models:
ensemble_pred = np.mean([
m.predict_proba(x) for m in models
], axis=0)Use case: Competitions, when maximum performance is needed
Stacking (Meta-Learning)
Ø +3–15% possible, high effortA meta-model learns to optimally combine the outputs of the base models. More complex but more powerful.
# Stacking procedure:
# 1. Train base models (cross-validation)
# 2. Use base model predictions as features
# 3. Train a meta-model on these features
# Simplest meta-learner: logistic regression
from sklearn.linear_model import LogisticRegression
meta_features = np.column_stack([
model1.predict_proba(X_val),
model2.predict_proba(X_val),
model3.predict_proba(X_val)
])
meta_model = LogisticRegression().fit(meta_features, y_val)Use case: When base models are very different (different architectures)
Ensemble diversity – the key to success
Ensembles work best when the individual models make different mistakes. Diversity comes from:
Different random seeds
Simplest method, always recommended
Different hyperparameters
Slightly vary LR, rank, dropout
Different model architectures
Combine BERT + RoBERTa + DeBERTa
Different training splits
Cross-validation folds as an ensemble
Different data augmentation
Each model on slightly different data
Checkpoint ensemble
Different points in training
Ensembles with FrameTrain
Done! You now know all the basics
From ML basics to advanced techniques like ensembles and mixed precision – you've made it through the whole AI Training Coach. Time to put what you've learned into practice.