← All tutorials

MGDA (Multiple Gradient Descent Algorithm)

MGDA picks one weight per task, each zero or more and all summing to one, so the weighted sum of the task gradients is as short as possible, then steps against that sum. For a small step every task's batch loss falls, unless that sum is zero, which makes the model Pareto-stationary (Section 5).

On this page

1 Dominated and Pareto-optimal models 2 The average step can hurt one task 3 The minimum-norm point 4 The minimum-norm point shrinks as training goes on 5 Pareto-stationary points 6 Frank-Wolfe for three or more tasks 7 When MGDA runs and what it costs 8 MGDA in a PyTorch training step 9 MGDA's settings 10 Which stationary point MGDA reaches 11 MGDA among the balancing methods 12 References

A multitask network has one shared encoder, with shared weights θsh, and one small head per task (Figure 1). The encoder turns the input into a representation Z that every head reads. Each task's gradient on the shared weights points where its loss rises fastest. Désidéri introduced MGDA in a 2009 report; Sener and Koltun (2018) made it practical for deep networks.

ProblemThe plain average step can raise one task's loss.
FixStep against the shortest weighted sum of the task gradients.
GuaranteeFor a small plain gradient step every task's batch loss falls, unless the gradients show no direction that lowers them all.
input shared encoder weights θsh Z representation head 1 head 2 MGDA balances only these weights 1 · one gradient per task on θsh 2 · solve one weight per task 3 · step θsh against the weighted sum 4 · each head steps on its own loss, scaled by wi
Figure 1. The model MGDA trains. Only box 2 is new; the rest is an ordinary step.

1 Dominated and Pareto-optimal models

Take NYUv2, indoor photos, with one network learning semantic segmentation (seg, a class for every pixel) and depth (metres to every pixel). Three checkpoints have illustrative (seg, depth) losses A = (0.9, 0.5), B = (0.9, 0.7) and C = (0.8, 0.9). A dominates B: the same seg loss and a lower depth loss. A and C each win one task, a trade-off. In Figure 2, B plays the part of ②, straight above A, and A the part of ③.

Model A beats model B outright when it is no worse on any task and strictly better on at least one. Li(A) is task i's loss for A.
Li(A) ≤ Li(B)
A is at least as good on every task i.
Lj(A) < Lj(B)
A is strictly better on at least one task j.
So best for several tasks means not dominated, a set of models rather than one; the eq card in Section 2 shows how a plain averaged step moves a model along that trade-off instead of helping every task.

MGDA looks for steps that make no task worse, so it moves a dominated model toward the front.

task 1 loss task 2 loss ① Pareto front ② dominated ③ on the front ↙ lower is better

Figure 2. ① The Pareto front. ② A dominated model. ③ One that beats ②.

2 The average step can hurt one task

With two shared weights, each task gradient is an arrow: g1 = (2, 0) and g2 = (−1, 0.5), the pair from the intro's average-step example. Training steps against a direction d built from them.

On NYUv2 with illustrative gradients gseg = (2, 1) and gdepth = (−6, 2), the average is (−2, 1.5). Its dot product with gseg is −2.5 and with gdepth 15, so the average step raises seg’s loss. Figure 3 after the card shows the same failure on the pair above: the average is 127° from g2, so ⟨g2, d⟩ = −0.38 and task 2’s loss rises.

A step helps a task when it points along that task’s gradient, and the plain average can fail that test for one task.
⟨gi, d⟩ > 0
The average step trades seg for depth, so it moves the model along the trade-off of the eq card in Section 1 instead of to a model that dominates the current one. Then task i improves. For a small step against d, its loss drops by about the step size times this dot product. It is negative exactly when the angle between gi and d is over 90°.
d = 12(g1 + g2)
Each gradient gets weight one half, so the average leans toward the longer gradient.
So the average is not safe for every task; eq card 1 in Section 3 picks a different blend that is.
127° to g2 g1 g2 average d ⟨g1, d⟩ = +1.00 ⟨g2, d⟩ = −0.38

Figure 3. The average d is over 90° from g2, so task 2's loss rises.

3 The minimum-norm point

A convex combination of the T task gradients is a weighted sum whose weights wi are zero or more and sum to one. The allowed weight lists form the simplex Δ, and all convex combinations together form the convex hull of the gradients.

On the NYUv2 pair the shortest point of the segment is d* = (0.154, 1.231), at wseg = 0.769, with squared length 1.538 (illustrative). Figure 4 draws the same idea on the pair of Section 2, where d* sits at w1 = 0.35 with both scores 0.11.

MGDA steps along the shortest blend of the task gradients, because that blend points into every task at once. It is the hull’s minimum‑norm point d*; Σi sums over the T tasks, ‖·‖ is length, and w ∈ Δ means w is an allowed weight list.
d* = Σi wi* gi
It replaces the average d of the eq card in Section 2. The convex combination with the best weights wi*.
w* = argminw∈Δ ‖Σi wi gi‖2
argmin returns the weight list w* that makes the squared length smallest. The shortest combination is unique; the weights that give it need not be.
So the shortest point is what makes the step safe for every task; eq card 2 in Section 3 shows why it helps both tasks by the same amount.

On the NYUv2 pair, ⟨gseg, d*⟩ = ⟨gdepth, d*⟩ = 1.538, equal to ‖d*‖2 (illustrative). On Figure 4’s pair both scores read 0.11 at d*.

At the shortest point both tasks improve by exactly the same amount: with two tasks and both weights above zero, d* has the same dot product with both gradients, and that value is its squared length.
⟨g1 − g2, d*⟩ = 0
d* is the minimum-norm point of eq card 1 in Section 3. d* meets the segment between the two tips at a right angle (Figure 4).
⟨g1, d*⟩ = ⟨g2, d*⟩
So both dot products are equal.
‖d*‖2 = w1⟨g1, d*⟩ + w2⟨g2, d*⟩
The weights sum to one, so the shared dot product equals d*'s squared length, which is above zero unless d* = 0. A small plain gradient step against d* then lowers both losses on the batch, each by about the step size times that value. Adam rescales each coordinate, so with Adam this holds only approximately (see Adam's per-coordinate scaling).
So the shortest blend helps both tasks equally, by its own squared length; the eq card in Section 3.1 gives its weight in one line for two tasks.

3.1 The two-task closed form

On the NYUv2 pair with seg as task 1: gdepth − gseg = (−8, 1), its dot product with gdepth is 48 + 2 = 50, and ‖gseg − gdepth‖2 = 64 + 1 = 65, so wseg = 50 over 65 = 0.769 and wdepth = 0.231 (illustrative). On Figure 4’s pair the same formula gives 3.25 over 9.25 = 0.351, the tool’s 0.35.

For two tasks the shortest blend’s weight has a closed form, so no solver is needed: the 2018 paper’s formula for task 1’s weight, clipped to the range 0 to 1; then w2 = 1 − w1.
w1* = ⟨g2 − g1, g2⟩‖g1 − g2‖2
This is the weight w* of eq card 1 in Section 3, and it gives the equal scores of eq card 2. w1* is where the perpendicular from the origin meets the segment, measured from g2's tip toward g1's tip as a fraction of the segment's length. Values below 0 become 0 and values above 1 become 1. Then d* is one task's gradient, and its dot product with the other gradient is at least ‖d*‖2. So a small step against d* still lowers both losses.
So the safe weight comes straight from two dot products; the eq card in Section 4 watches this blend shrink as training goes on.
g1 g2 convex hull d*

Figure 4. w1 moves d on the dashed line; the shortest, d*, meets it at 90°.

d* has equal dot products

‖d‖, the length
0.33
⟨d, g1⟩, task 1
0.11
⟨d, g2⟩, task 2
0.11

4 The minimum-norm point shrinks as training goes on

Figure 5. Four training steps. Gold is d*; the bar is its length.

The stepper uses its own made-up pairs: d* shrinks from 0.329 long at step 1 to 0.035 at step 4, about a tenth, and the later panels zoom 2× and 8× to keep the short arrows visible. The NYUv2 pair shrinks the same way under an illustrative rule: two toy losses, each a bowl ½‖θ − c‖2 with its lowest point at c = (−2, −1) for seg and (6, −2) for depth, start at θ = (0, 0) and step by −0.5 d*. Then ‖d*‖ goes 1.240, 0.620, 0.310, 0.155 as the cosine between the two gradients falls from −0.707 to −0.994.

As training nears a trade-off point the shortest blend shrinks, so MGDA’s steps shrink with it.
minw∈Δ ‖Σi wi gi‖2
Each step’s weight comes from the closed form of the eq card in Section 3.1. The same problem as in Section 3, solved again with this training step's gradients.
‖d*‖ ≈ 0 ⇒ step ≈ 0
When d* is nearly zero, the shared weights barely move. Each batch gives slightly different gradients, so in real training its length stays above zero even where no step could lower every loss, and it is no clean stop signal (see MGDA's shrinking gradient).
So MGDA slows down on its own near the trade-off curve; the eq card in Section 5 names the point where the step vanishes.
g1 task 1's gradientg2 task 2's gradientwi task i's weightd* the shortest combinationΔ the simplex, every allowed weight list‖‖ lengthmin the smallest value of≈ approximately

5 Pareto-stationary points

A point is Pareto-stationary when d* = 0, so the gradients show no direction that lowers every loss.

Add a third NYUv2 task, surface normals (the direction each pixel’s surface faces), with illustrative gnormals = (1, −2). Then 0.4 (2, 1) + 0.2 (−6, 2) + 0.4 (1, −2) = (0, 0), so this point is Pareto-stationary. Figure 6 draws the same case on its own three gradients. The NYUv2 pair alone is the other case: its shortest blend has length 1.240, never 0, and both tasks gain 1.538 = ‖d*‖2.

At a Pareto-stationary point the shortest blend is zero and MGDA’s step vanishes; anywhere else its step helps every task.
minw∈Δ ‖Σi wi gi‖ = 0
This is where the shrinking step of the eq card in Section 4 vanishes. The point is Pareto-stationary when the origin lies in the shaded triangle, the convex hull, edges included (Figure 6).
⟨gi, d*⟩ ≥ ‖d*‖2
Otherwise this holds for every task i. d* is the point of the hull nearest the origin, so its dot product with every task's gradient is at least its squared length, which is above zero, and a small step against it lowers every loss. With two tasks this is the card in Section 3.
So a zero blend means no step helps every task, and any non-zero d* helps all of them. On mini-batches ‖d*‖ is never exactly 0, so this describes the point, not a stop test; the eq card in Section 6 finds d* for three or more tasks.
g1 g2 g3 ② d* = 0 ① convex hull
Figure 6. ① The convex hull. ② d* = 0, from weights of about 0.31, 0.33 and 0.37.

A Pareto-stationary point need not be Pareto-optimal. The gradients can also cancel at a saddle point, where losses rise in some directions and fall in others.

6 Frank-Wolfe for three or more tasks

With three or more tasks there is no closed form, so the 2018 paper uses Frank-Wolfe, an iterative method.

On the three NYUv2 gradients of Section 5, from one third each the blend is (−1, 0.333). Seg and normals tie for the smallest dot product, −1.667, and the tie goes to the first task, seg. The corners then run seg, normals, depth, normals, depth, normals and onward. After 22 moves the best move size γ falls below 0.00001, the TOL of the code in Section 8.1, so iteration 23 stops, at weights 0.4, 0.2 and 0.4 and blend (0, 0) (illustrative gradients). Figure 7 draws the same moves on its own three gradients.

With three or more tasks MGDA finds the weights by moving weight, again and again, toward the task the current blend helps least. G is the Gram matrix, which holds every pair's dot product, Gij = ⟨gi, gj⟩. The weights start equal at 1T, and each iteration moves them part of the way toward one task's corner of the simplex with these three lines.
t = argminr Σj wj Grj
It solves the minimum of eq card 1 in Section 3, here reaching the zero blend of the eq card in Section 5. Σj wj Grj is task r's dot product with the current combination, and argminr picks the task t where it is smallest.
w ← (1 − γ) w + γ et
Move a fraction γ of the way toward task t's gradient. et is the weight list with 1 at task t and 0 elsewhere. γ comes from the two-task formula, with the current combination in place of g2 and gt in place of g1.
stop when γ ≈ 0
The iterations stop when the best move is nearly zero, or at an iteration cap.
So Frank-Wolfe reaches the shortest blend for any number of tasks; the eq card in Section 7.1 makes each solve cheaper.
① start ② ③ ④ d* g1 g2 g3 origin
Figure 7. ① Equal weights. ② Toward g2. ③ Toward g1. ④ The point nearest the origin.

The official code (min_norm_solvers.py) runs gradient descent on the weights instead and pulls them back onto the simplex after each step, starting from the best pair of tasks. Its loop counter never increases, so its cap of 250 never fires; it stops when the weights change by less than 1e-5, summed over all tasks.

7 When MGDA runs and what it costs

7.1 MGDA-UB, gradients at the representation

MGDA-UB (UB for upper bound) takes each task's gradient at Z (Figure 1) instead of at θsh.

On NYUv2 with a shared encoder output Z, plain MGDA runs the encoder backward once per task to get each gi (Figure 8); MGDA-UB needs one backward pass through each head, none through the encoder, and then one encoder pass for the chosen blend.

MGDA-UB solves on gradients taken at the shared representation instead of the shared weights, which is cheap; the bound ties that blend to the real one, but, as the paragraph after the card shows, it does not guarantee a safe step. ∇ means gradient, so ∇θsh Li is gi.
‖Σi wi ∇θsh Li‖2
This is the squared length that the Frank-Wolfe solve of the eq card in Section 6 makes small. The squared length MGDA makes small, built from gradients on the shared weights.
≤ ‖∂Z∂θsh‖2
The Jacobian of Z, how each entry of Z changes with each shared weight. It does not depend on the weights wi.
× ‖Σi wi ∇Z Li‖2
The same combination at Z. MGDA-UB minimizes this second factor instead of the left side. Computing it needs one backward pass through each head and none through the encoder.
So MGDA-UB buys a cheap solve and gives up the guarantee; the eq card in Section 9 adds the normalizers applied before any solve.

The 2018 paper claims MGDA-UB still lowers every loss or stops at a Pareto-stationary point when the Jacobian of Z has full rank, meaning the weights can move Z in every direction. This does not hold in general. In a two-weight example built for this page, with a full-rank 2 by 2 Jacobian, MGDA-UB picks 0.5 and 0.5, and a small step against that direction raises task 1's loss; exact MGDA picks 0.7 and 0.3.

plain sum · 1 forward, 1 backward ① MGDA · 4 forward, 4 backward ② MGDA-UB · 2 forward, 1 backward encoder forward encoder backward a head
Figure 8. Passes per step, three tasks. ① repeats the encoder; ② only the heads.

The 2018 paper times both on Cityscapes (semantic segmentation, instance segmentation and depth) and CelebA (200K face images, 40 yes/no attributes as tasks, ResNet-18).

Cityscapes, 3 tasks (paper gives no unit) MGDA38.6 MGDA-UB23.3 CelebA, 40 tasks MGDA429.9 h MGDA-UB16.1 h each bar's length is its time as a share of MGDA's time
Figure 9. Training times from the 2018 paper's Table 2, on a Titan Xp.

8 MGDA in a PyTorch training step

MGDA sits between the losses and the optimizer step (Figure 10).

1 · Forwardeach task computes its loss2 · Backwardper-task gradients, shared layers3 · Balancecombine the task gradients4 · Clipcap the gradient's length5 · Optimizer stepupdate the network's parameters6 · Logrecord what this step didloss-weighting methods act heregradient methods act here
Figure 10. MGDA acts at stages 2 and 3; clipping and the optimizer act on its result.

8.1 The minimum-norm weight solver

min_norm turns G into the weights by the Frank-Wolfe iteration of Section 6.

import torch

ITERS, TOL = 250, 1e-5

def min_norm(G):
    # G[i, j] = g_i . g_j, (T, T)
    T = len(G)
    w = G.new_ones(T) / T
    for _ in range(ITERS):
        t = (G @ w).argmin()
        dd = w @ G @ w
        dg = w @ G[t]
        gg = G[t, t]
        den = dd - 2 * dg + gg
        if den <= 0:
            break
        gam = (dd - dg) / den
        gam = gam.clamp(0, 1)
        if gam < TOL:
            break
        w = (1 - gam) * w
        w[t] += gam
    return w
  1. 1The iteration cap and the tolerance on gam (Section 9).
  2. 2Equal weights 1/T, marker ① in Figure 7.
  3. 3Picks task t, the one the combination agrees with least (Section 6 card, line 1).
  4. 4dd, dg and gg are dot products of the combination and gt, den is their squared distance (the loop stops at zero), and gam is the Section 3.1 formula.
  5. 5Stops when gam is nearly zero, otherwise moves toward task t (Section 6 card, lines 2 and 3).

8.2 The full training step

mgda_step runs one training step for two regression tasks with one shared forward; paste it below the min_norm solver of Section 8.1.

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import grad
from torch.optim import Adam

trunk = nn.Linear(16, 32)
h1 = nn.Linear(32, 1)
h2 = nn.Linear(32, 1)
heads = nn.ModuleList([h1, h2])
theta = list(trunk.parameters())
H = list(heads.parameters())
opt = Adam(theta + H, lr=5e-4)
keep = dict(retain_graph=True)

def mgda_step(x, ys):
    # x: (B, 16), ys: two (B, 1)
    z = F.relu(trunk(x))
    losses = []
    for h, y in zip(heads, ys):
        L = F.mse_loss(h(z), y)
        losses.append(L)
    rows = []
    for L in losses:
        g = grad(L, theta, **keep)
        v = [u.ravel() for u in g]
        rows.append(torch.cat(v))
    # Gm: (T, P), one row per task
    Gm = torch.stack(rows)
    w = min_norm(Gm @ Gm.T)
    opt.zero_grad()
    Ls = torch.stack(losses)
    (w @ Ls).backward()
    opt.step()
    return w
  1. 1A trunk, two heads, and theta, the shared weights. keep is retain_graph=True since the final backward reuses the graph.
  2. 2One forward and each task's batch-mean loss.
  3. 3One gradient per task on theta, flattened to a row of P numbers (box 1 in Figure 1). The training-loop page shows how each task gradient is computed.
  4. 4The Gram matrix and the solve of Section 8.1, box 2 in Figure 1.
  5. 5One backward of the weighted loss. theta receives exactly d* and each head its gradient times wi, boxes 3 and 4 in Figure 1.

9 MGDA's settings

MGDA has no hand-set loss weights, but four settings change its step.

Gradient normalization
Without a normalizer ni, a longer gradient gets less weight, and a loss scaled by 10 has a 10 times longer gradient (see how loss scale enters the gradient). The official sample config uses loss+; the 2018 paper uses none.

With ni = ‖gi‖, the NYUv2 pair becomes unit arrows (0.894, 0.447) and (−0.949, 0.316). Their shortest blend has weights 0.5 and 0.5, so the step on the raw gradients is the plain average (−2, 1.5) again and seg’s score falls back to −2.5, where the raw pair gave wseg = 0.769 and 1.538 for both (illustrative). Figure 11 shows the same switch on Figure 4’s pair.

Before solving, each gradient can be divided by a normalizer so one big task does not decide the blend alone.
gi ← gini
Like MGDA-UB in the eq card in Section 7.1, this changes what the solve sees; here it moves the weight of the eq card in Section 3.1, 0.769 raw against 0.5 after l2. The weights found this way then multiply the raw losses.
ni = 1, ‖gi‖, Li, or Li‖gi‖
none, l2, loss and loss+. l2 keeps only directions, so with two tasks it always gives 0.5 and 0.5, the plain average (Figure 11). loss and loss+ make a small-loss task's row longer, so it gets less weight.
So the normalizer decides how much each task’s size counts in the blend.
Solver stopping
The Section 8.1 snippet stops after ITERS (250) iterations or once gam is below TOL (1e-5). A higher cap or lower tolerance gives a combination nearer d* at more cost; the opposite is faster and leaves it longer. A cap of 1 makes one Frank-Wolfe move from equal weights. In 100 random cases of four tasks, each gradient 6 random normal numbers, the snippet hit the cap in 77, leaving the combination a median 0.18% and at most 4.8% too long. The official solver stops on the weight change instead (Section 6).
MGDA-UB on or off
On (the sample config) takes gradients at Z: one encoder backward instead of T, but an approximation (Section 7.1). Off solves the exact problem.
Learning rate
The guarantee needs a small step. A larger rate trains faster but can overshoot and raise a task's loss; a smaller one keeps every loss falling, more slowly. The sample config uses Adam at 5e-4; the training script cuts it by 15% every 10 epochs.
① none ② l2 d* w1 = 0.35, both fall average w1 = 0.50, task 2 rises
Figure 11. ① Without normalization, d* lowers both losses. ② l2 gives the average.

10 Which stationary point MGDA reaches

Which Pareto-stationary point MGDA reaches depends mainly on the network's initialization. Pareto MTL (Lin et al., 2019) gives each run a preference direction limiting which part of the front it may end in, so several runs spread along the front, as sketched below.

task 1 loss task 2 loss ① starts ② ends front
Figure 12. ① Three initializations. ② Each ends at a different front point.

11 MGDA among the balancing methods

MGDA solves its weights fresh each batch from the task gradients' lengths and angles. GradNorm instead learns per-task loss weights so tasks train at similar rates.

MethodThe question it answers
GradNormHow much weight should each task's loss get so all tasks train at a similar rate? (learned during training from how fast each loss falls)
Uncertainty WeightingHow much weight should each task's loss get, given how noisy that task's targets are? (the noise level is learned along with the model)
PCGradHow should a task gradient be edited when it conflicts with another task's gradient?
GradVacHow should each pair of task gradients be moved toward a target cosine, a running average of that pair's past cosines?
CAGradHow can a step raise the smallest per-task improvement while staying near the average gradient?
MGDA (this page)Which convex combination of task gradients lowers every task's loss at once, and when does no such combination exist?

12 References

  1. Désidéri, J.-A. (2009). Multiple-Gradient Descent Algorithm (MGDA). INRIA Research Report RR-6953.
  2. Désidéri, J.-A. (2012). Multiple-gradient descent algorithm (MGDA) for multiobjective optimization. Comptes Rendus Mathématique, 350(5-6), 313-318.
  3. Silberman, N., Hoiem, D., Kohli, P., and Fergus, R. (2012). Indoor Segmentation and Support Inference from RGBD Images. ECCV.
  4. Sener, O., and Koltun, V. (2018). Multi-Task Learning as Multi-Objective Optimization. NeurIPS. arXiv:1810.04650.
  5. Lin, X., et al. (2019). Pareto multi-task learning. NeurIPS.
  6. Official code at isl-org/MultiObjectiveOptimization (discontinued), and the LibMTL library.