GradNorm - Pytorch
A practical implementation of GradNorm, Gradient Normalization for Adaptive Loss Balancing, in Pytorch
Increasingly starting to come across neural network architectures that require more than 3 auxiliary losses, so will build out an installable package that easily handles loss balancing in distributed setting, gradient accumulation, etc. Also open to incorporating any follow up research; just let me know in the issues.
Will be dog-fooded for SoundStream, MagViT2 as well as MetNet3
Appreciation
- StabilityAI, A16Z Open Source AI Grant Program, and 🤗 Huggingface for the generous sponsorships, as well as my other sponsors, for affording me the independence to open source current artificial intelligence research
Install
$ pip install gradnorm-pytorch
Usage
import torch
from torch.optim import Adam
from gradnorm_pytorch import (
GradNormLossWeighter,
MockNetworkWithMultipleLosses
)
# a mock network with multiple discriminator losses
network = MockNetworkWithMultipleLosses(
dim = 512,
num_losses = 4
)
optim = Adam(network.parameters(), lr = 3e-4)
# backbone shared parameter
backbone_parameter = network.backbone[-1].weight
# grad norm based loss weighter
loss_weighter = GradNormLossWeighter(
num_losses = 4,
learning_rate = 1e-4,
restoring_force_alpha = 0., # 0. is perfectly balanced losses, while anything greater than 1 would account for the relative training rates of each loss. in the paper, they go as high as 3.
grad_norm_parameters = backbone_parameter
)
# mock input
mock_input = torch.randn(2, 512)
losses = network(mock_input)
# backwards with the loss weights
# will update on each backward based on gradnorm algorithm
loss_weighter.backward(losses)
# the usual
optim.step()
optim.zero_grad()
You can also do it with respect to the gradients flowing through an intermediate activation, say a generated modality
# same as above ...
loss_weighter = GradNormLossWeighter(
num_losses = 4,
learning_rate = 1e-4,
restoring_force_alpha = 0.,
grad_norm_parameters = None # this is now None and the activations need to be returned on network forward and passed in on backwards
)
# mock input
mock_input = torch.randn(2, 512)
losses, backbone_output_activations = network(mock_input, return_backbone_outputs = True)
# backwards with the loss weights and backbone activations from which gradients backpropagate through from all losses
loss_weighter.backward(losses, backbone_output_activations)
# optimizer
optim.step()
optim.zero_grad()
You can also switch it to basic static loss weighting, in case you want to run experiments against fixed weighting.
loss_weighter = GradNormLossWeighter(
loss_weights = [1., 10., 5., 2.],
...,
frozen = True
)
# or you can also freeze it on invoking the instance
loss_weighter.backward(..., freeze = True)
To control which loss is subjected to GradNorm, pass in a list[bool] with the loss_mask kwarg
loss_weighter = GradNormLossWeighter(
loss_mask = [True, True, False, True], # 1st, 2nd, and 4th losses are grad normed
...,
)
# you can also override on .backward
loss_weighter.backward(..., loss_mask = [True, True, False, False])
For use with 🤗 Huggingface Accelerate, just pass in the Accelerator instance into the keyword accelerator on initialization
ex.
accelerator = Accelerator()
network = accelerator.prepare(network)
loss_weighter = GradNormLossWeighter(
...,
accelerator = accelerator
)
# backwards will now use accelerator
Todo
- take care of gradient accumulation
- handle freezing of some loss weights, but not others
- handle sets of loss weights
- allow for a prior weighting, accounted for when calculating gradient targets
Citations
@article{Chen2017GradNormGN,
title = {GradNorm: Gradient Normalization for Adaptive Loss Balancing in Deep Multitask Networks},
author = {Zhao Chen and Vijay Badrinarayanan and Chen-Yu Lee and Andrew Rabinovich},
journal = {ArXiv},
year = {2017},
volume = {abs/1711.02257},
url = {https://api.semanticscholar.org/CorpusID:4703661}
}
Metadata
Release files for gradnorm-pytorch 0.2.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gradnorm_pytorch-0.2.3.tar.gz | 775.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gradnorm_pytorch-0.2.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 783.0 kB
Release files / gradnorm_pytorch-0.2.3.tar.gz
| Download URL | gradnorm_pytorch-0.2.3.tar.gz |
|---|---|
| Size | 775.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d1745d7c6beb5d019d700d828f50ebde30ff6e751a633de9dc74fe00c24dc499
|
|
BLAKE2b-256 checksum How to use checksums |
a43897000c41113b33cfe09130fcaed47a804f61e28bc5a97ab3d17528d4787c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.17
|
Release files / gradnorm_pytorch-0.2.3-py3-none-any.whl
| Download URL | gradnorm_pytorch-0.2.3-py3-none-any.whl |
|---|---|
| Size | 7.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bdedb0e3044a398d321a370fa1f4c23910774ffeeff0fe03b2fbe76c84bc592f
|
|
BLAKE2b-256 checksum How to use checksums |
0683b1ebcd38e1e4deeeb91385c9881f9df76eddff2afae0fea392f6383fee9f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.17
|