One-line circuit breaker for PyTorch training — catches NaN gradients, logs spikes, prevents model corruption.
Project description
⚡ StabilityGuard
One-line circuit breaker for PyTorch training.
Add one line. See exactly which layer is about to explode.
The Problem
Training large models? Gradient spikes and NaN explosions silently corrupt your model weights. You lose hours of GPU time, and the error message tells you nothing about which layer caused it.
The Fix
pip install stabilityguard
Before StabilityGuard (standard PyTorch):
from torch.optim import AdamW
optimizer = AdamW(model.parameters(), lr=2e-4)
for batch in dataloader:
loss = model(batch)
loss.backward()
optimizer.step()
optimizer.zero_grad()
After StabilityGuard (one-line change):
from torch.optim import AdamW
from stabilityguard import GuardedOptimizer # ← the only change
base_opt = AdamW(model.parameters(), lr=2e-4)
optimizer = GuardedOptimizer(base_opt, model,
spike_threshold=10.0, # gradient norm ratio to trigger alert
nan_action="skip", # "skip" | "rollback" | "raise"
log_every=50 # steps between diagnostic summaries
)
for batch in dataloader:
loss = model(batch)
loss.backward()
optimizer.step() # GuardedOptimizer intercepts here
optimizer.zero_grad()
What You See
When a spike hits at step 847:
╔══════════════════════════════════════════════════════════════╗
║ ⚠ STABILITYGUARD — SPIKE DETECTED @ step 847 ║
╠══════════════════════════════════════════════════════════════╣
║ Trigger layer : transformer.h.11.mlp.c_proj ║
║ Grad norm : 847.3 (baseline: 1.2, ratio: 706.1x) ║
║ Action taken : optimizer.step() SKIPPED ║
║ Loss (pre-skip): 14.71 ║
╚══════════════════════════════════════════════════════════════╝
stabilityguard.log written → ./sg_logs/spike_step847.json
Your model weights are untouched. Training continues.
How It Works
- Backward hooks on every
nn.Modulecapture per-layer gradient L2 norms - EMA baselines track normal gradient behavior (α=0.01, ~100 step lookback)
- Spike detection fires when
current_norm / ema_baseline > threshold - NaN/Inf short-circuit catches corrupted gradients via
torch.isfinite - Actions execute automatically: skip the step, rollback to checkpoint, or raise
Configuration
| Parameter | Default | Description |
|---|---|---|
spike_threshold |
10.0 |
Ratio of current norm to EMA baseline that triggers a spike |
nan_action |
"skip" |
Action on spike: "skip", "rollback", or "raise" |
log_every |
50 |
Steps between periodic diagnostic summaries |
log_dir |
"./sg_logs" |
Directory for JSON spike reports |
ema_alpha |
0.01 |
EMA smoothing factor (smaller = slower adaptation) |
warmup_steps |
10 |
Steps before spike detection activates |
verbose |
True |
Print diagnostic summaries to stdout |
Actions
| Action | Behavior |
|---|---|
skip |
Skip optimizer.step() — corrupted gradients discarded, weights unchanged |
rollback |
Restore model + optimizer to the last clean checkpoint |
raise |
Throw GradientSpikeError for interactive debugging |
Integrations
Weights & Biases
from stabilityguard.integrations.wandb import WandBBridge
bridge = WandBBridge()
# Metrics logged under sg/ namespace automatically
MLflow
from stabilityguard.integrations.mlflow import MLflowBridge
bridge = MLflowBridge()
HuggingFace Transformers
from stabilityguard.integrations.huggingface import StabilityGuardCallback
trainer = Trainer(
model=model,
args=training_args,
callbacks=[StabilityGuardCallback(spike_threshold=10.0)],
)
Performance
| Metric | Value |
|---|---|
| Per-step overhead (no spike) | < 0.2ms on A100 |
| Per-step overhead (spike detected) | ~3ms (includes JSON write) |
| External dependencies | 0 (only PyTorch) |
| License | MIT |
Install from source
git clone https://github.com/stabilityguard/stabilityguard.git
cd stabilityguard
pip install -e ".[test]"
pytest tests/ -v
License
MIT — use it anywhere, no restrictions.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file stabilityguard-0.1.0.tar.gz.
File metadata
- Download URL: stabilityguard-0.1.0.tar.gz
- Upload date:
- Size: 21.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1d19dcbbe9f77d7afe8f88bd70327220de2eba785d859a2f7e91d13718d546e8
|
|
| MD5 |
0bc3eb47cf79a36b4dd488286c6206b4
|
|
| BLAKE2b-256 |
32cb0d5efd28d2859418026e43c24c8528cdf540344351d052009cac77267a07
|
File details
Details for the file stabilityguard-0.1.0-py3-none-any.whl.
File metadata
- Download URL: stabilityguard-0.1.0-py3-none-any.whl
- Upload date:
- Size: 21.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
783d1950c2a4bdd6c77b59c9ee89171d9f4d27afa606e28433a99aebdc3b7af1
|
|
| MD5 |
33d3e63433704a36a36bbab260c809f1
|
|
| BLAKE2b-256 |
1eb7ccd09b885fd3cfe1a6d70f3a16b4220f04418a1aae1d952a6209e0a5a1a2
|