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-emaVerified import paths — ran on the pinned version, not inferred.
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.
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.
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.
Use `ema.state_dict()` and `ema.load_state_dict()` alongside your model and optimizer state_dicts.
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.
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+.
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.
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.