Skip to main content

GradNorm - Pytorch

Project description

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

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}
}

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

gradnorm_pytorch-0.2.3.tar.gz (775.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gradnorm_pytorch-0.2.3-py3-none-any.whl (7.8 kB view details)

Uploaded Python 3

File details

Details for the file gradnorm_pytorch-0.2.3.tar.gz.

File metadata

  • Download URL: gradnorm_pytorch-0.2.3.tar.gz
  • Upload date:
  • Size: 775.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.17

File hashes

Hashes for gradnorm_pytorch-0.2.3.tar.gz
Algorithm Hash digest
SHA256 d1745d7c6beb5d019d700d828f50ebde30ff6e751a633de9dc74fe00c24dc499
MD5 c52bac18adffe2bd3728fc98d6daca60
BLAKE2b-256 a43897000c41113b33cfe09130fcaed47a804f61e28bc5a97ab3d17528d4787c

See more details on using hashes here.

File details

Details for the file gradnorm_pytorch-0.2.3-py3-none-any.whl.

File metadata

File hashes

Hashes for gradnorm_pytorch-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 bdedb0e3044a398d321a370fa1f4c23910774ffeeff0fe03b2fbe76c84bc592f
MD5 b22b9e3fcf17f7f00bfb9740dce29774
BLAKE2b-256 0683b1ebcd38e1e4deeeb91385c9881f9df76eddff2afae0fea392f6383fee9f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page