Registry / ai-ml / torch-ema

torch-ema

JSON →
library0.3pypypi✓ verified 87d ago

torch-ema is a compact PyTorch library designed for efficiently computing and managing exponential moving averages of model parameters during the training of deep learning models. It helps stabilize training and often leads to improved generalization. The current version is 0.3.0, with the last release in November 2021, indicating a slow release cadence.

pip install torch-ema
INSTALL
IMPORT
SIG · TORCH-EMA
T
torch-ema
ai-mlpythonv0.3
Install
65.7s avg
Import
5410ms
Disk
2136MB
Pass rate
9/ 10
Env Coverage9 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v0.2 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
glibc
py 3.10
✓ —
✓ 74.63s
py 3.11
✓ —
✓ 67.18s
py 3.12
✓ —
✓ 63.3s
py 3.13
✓ —
✓ 57.78s
py 3.9
✓ —
2/4 runs
2136MB installed
● package 2136MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

ExponentialMovingAverage
from torch_ema import ExponentialMovingAverage

Initialize `ExponentialMovingAverage` with your model's parameters and a decay rate. Call `ema.update()` after each optimizer step. For evaluation, use the `ema.average_parameters()` context manager to temporarily swap model weights with their EMA counterparts.

import torch import torch.nn.functional as F from torch_ema import ExponentialMovingAverage torch.manual_seed(0) x_train = torch.rand((100, 10)) y_train = torch.rand(100).round().long() x_val = torch.rand((100, 10)) y_val = torch.rand(100).round().long() model = torch.nn.Linear(10, 2) optimizer = torch.optim.Adam(model.parameters(), lr=1e-2) ema = ExponentialMovingAverage(model.parameters(), decay=0.995) # Train for a few epochs model.train() for _ in range(20): logits = model(x_train) loss = F.cross_entropy(logits, y_train) optimizer.zero_grad() loss.backward() optimizer.step() # Update the moving average with the new parameters ema.update() # Validation: original model model.eval() with torch.no_grad(): logits_orig = model(x_val) loss_orig = F.cross_entropy(logits_orig, y_val) print(f"Original model validation loss: {loss_orig.item():.4f}") # Validation: with EMA # The .average_parameters() context manager: # (1) saves original parameters before replacing with EMA version # (2) copies EMA parameters to model # (3) after exiting the `with`, restores original parameters to resume training later with ema.average_parameters(): with torch.no_grad(): logits_ema = model(x_val) loss_ema = F.cross_entropy(logits_ema, y_val) print(f"EMA model validation loss: {loss_ema.item():.4f}")
Debug
Known issues
breakingIn version 0.3.0, the behavior changed to apply EMA to *all* parameters passed to the `ExponentialMovingAverage` object, regardless of whether they have `requires_grad = True`. Prior versions (e.g., v0.2) would partially ignore parameters without `requires_grad = True`.
fix
If migrating from <0.3.0, review your parameter handling. If you intended to only track trainable parameters, ensure you filter `model.parameters()` passed to EMA. If you want all parameters tracked, v0.3.0+ handles this by default.
affects: <0.3.0 to 0.3.0+
gotchaWhen using `torch-ema` in a distributed training setup (e.g., DDP), the EMA parameters (`ema.shadow`) are not automatically synchronized across GPUs. This requires manual handling.
fix
After `ema.update()` in each process, you must explicitly synchronize the `ema.shadow` parameters across all ranks, typically using `torch.distributed.all_reduce()` on each shadow parameter.
affects: All
gotchaThe `ExponentialMovingAverage` object's internal state (shadow parameters and update count) must be explicitly saved and loaded when checkpointing your model to resume training correctly.
fix
Use `ema.state_dict()` and `ema.load_state_dict()` alongside your model and optimizer state_dicts.
affects: All
gotchaBy default, `torch-ema` primarily manages model *parameters*. Buffers (e.g., `running_mean`, `running_var` in BatchNorm layers) are not automatically tracked or averaged by `ExponentialMovingAverage`.
fix
If EMA for buffers is required, you would need to implement custom logic to manage them, or consider PyTorch's built-in `torch.optim.swa_utils.AveragedModel` which provides options to handle buffers during SWA/EMA.
affects: All
Errors
Common errors & fixes
EMA model does not converge or shows unexpected behavior with non-trainable parameters.
Prior to v0.3.0, `torch-ema` would ignore parameters that did not have `requires_grad=True`. If you upgraded to v0.3.0 or later, these parameters are now included, which might change expected behavior.
fix
If you are on v0.3.0+ and only want to track trainable parameters, ensure you explicitly filter the parameters passed to `ExponentialMovingAverage`: `ema = ExponentialMovingAverage(filter(lambda p: p.requires_grad, model.parameters()), decay=0.995)`. If you are on an older version and want all parameters, upgrade to v0.3.0+.
My EMA model performs poorly on multi-GPU (DDP) training, even though the base model trains well.
EMA parameters are not being synchronized across different distributed processes (GPUs). Each GPU is computing its own independent EMA.
fix
After calling `ema.update()`, iterate through `ema.shadow.items()` and apply `torch.distributed.all_reduce(param, op=torch.distributed.ReduceOp.AVG)` for each `param` in `ema.shadow` to ensure all GPUs have the same averaged EMA weights.
After loading a checkpoint, the EMA model's performance is as if it started from scratch, or worse.
The `ExponentialMovingAverage` object's state, including its `shadow` parameters and `update_count`, was not saved or properly loaded when resuming from a checkpoint.
fix
Always save `ema.state_dict()` and load `ema.load_state_dict(checkpoint['ema_state_dict'])` as part of your checkpointing routine, similar to how you handle your model and optimizer.
Upgrade
Version history
0.3latest on PyPI · released Nov 17, 2021
Audit
Dependencies
torchrequiredCore deep learning framework
Agent activity
30 hits · last 30 days
node
28
OpenAI (training)
1
Resources
torch-ema — pip install torch-ema · libregistry