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).
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 representationZ 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.
Problem
The plain average step can raise one task's loss.
Fix
Step against the shortest weighted sum of the task gradients.
Guarantee
For a small plain gradient step every task's batch loss falls, unless the gradients show no direction that lowers them all.
Figure 1. The model MGDA trains. Only box 2 is new; the rest is an ordinary step.
1 Dominated and Pareto-optimal models
Model B is dominated when some model A is no worse on any task and strictly better on at least one.
A model is Pareto-optimal when no task can improve without another getting worse.
The Pareto front is the curve of Pareto-optimal models' task losses.
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.
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.
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 pointd*; Σi sums over the T tasks, ‖·‖ is length, and w ∈ Δ means w is an allowed weight list.
d* = Σiwi*gi
It replaces the average d of the eq card in Section 2. The convex combination with the best weights wi*.
w* = argminw∈Δ ‖Σi wigi‖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.
MGDA picks w1 ≈ 0.35
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
length of d*
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∈Δ ‖Σiwigi‖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 wigi‖ = 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.
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 Σjwj Grj
It solves the minimum of eq card 1 in Section 3, here reaching the zero blend of the eq card in Section 5. ΣjwjGrj 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.
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
MGDA solves the weights afresh on every batch from its mean losses and keeps no state, so they can change from batch to batch.
Only the gradients on the shared weights enter G (MGDA-UB in Section 7.1 uses Z). G is only T by T, so the solve takes negligible time, per the 2018 paper. Memory goes to the T by P task-gradient matrix, where P, the shared-weight count, is often in the millions.
In the official code each head's gradient is multiplied by its task weight; the 2018 paper's pseudocode leaves it unscaled (how each head's gradient is scaled).
In the official code each step needs one extra forward and one extra backward pass per task (Figure 8).
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 ∇θshLi is gi.
‖Σiwi ∇θ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.
× ‖Σiwi ∇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.
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).
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).
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
1The iteration cap and the tolerance on gam (Section 9).
3Picks task t, the one the combination agrees with least (Section 6 card, line 1).
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.
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
1A trunk, two heads, and theta, the shared weights. keep is retain_graph=True since the final backward reuses the graph.
5One backward of the weighted loss. theta receives exactly d* and each head its gradient times wi, boxes 3 and 4 in Figure 1.
For MGDA-UB, pass [z] instead of theta to grad, so each call goes back only through its head, and z is far smaller than the shared weights.
The official full-MGDA path runs one forward per task, so dropout draws new random masks and batch norm updates its statistics per task, unlike this snippet's one forward.
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.
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.
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.