← All tutorials

Introduction to Multitask Learning

Training one model on several tasks, the three common ways it goes wrong, and which methods fix each.

On this page

1One model, several tasks 2Why sharing one trunk helps 3Shared and task-specific parameters 4Train on the weighted sum of the losses 5Three common causes of negative transfer 6Four vector operations on gradients 7Whether a step helps each task 8Which method fixes which failure 9References

1One model, several tasks

Multitask learning trains one model on several tasks at once. A shared trunk of layers feeds one small head per task, each task has a loss (a number that scores how badly the model does that task), and training lowers the sum of the losses. Training on that sum can go wrong in three common ways. The fixes fall into two families: methods that learn a weight for each task’s loss, and methods that combine the tasks’ gradients (Section 3.1) afresh at every step (Figure 1).

losses ondifferent scalestasks learn atdifferent speedsgradients pointin conflictingdirectionslearn a weightper task lossGradNormUncertaintyWeightingcombine the taskgradients each stepPCGradGradVacCAGradMGDA12345
Figure 1. 1 to 3 are the failures (Section 5); 4 and 5 the two fix families.

2Why sharing one trunk helps

  1. One trunk instead of one model per task needs less memory and compute.
  2. Each task’s labels give the shared trunk extra training signal that can help the other tasks.
  3. A trunk that must serve several tasks is pushed toward features that hold across them, so it overfits less to one dataset’s quirks.

Caruana (1997) tested the extra-signal benefit with a robot’s camera: a small network looked at a horizontal strip of pixels from each door image to find the doorknob and to tell single from double doors, once alone and once with eight extra tasks that locate and measure the doorway, the door jambs and the door edges. Error is root-mean-squared error (RMSE) on test images, compared against the best of three single-task networks.

best of 3 single-task netsmultitask netdoorknob location.081.0621−23.5%door type.086.0592−31.4%0.05.10test RMSE
Figure 2. 1 23.5% and 2 31.4% lower test error with the extra tasks (ten trials).

Scene understanding is a standard use: one network predicts segmentation (a label for every pixel), depth and surface normals (the direction each surface faces) (Vandenhende et al., 2022).

3Shared and task-specific parameters

The trunk-and-heads design is called hard parameter sharing. Ruder (2017) calls it the most common approach to multitask learning in neural networks and says it greatly reduces the risk of overfitting, the third benefit in Section 2.

The trunk’s parameters, the weights training adjusts, are θsh. Task i’s head has its own parameters θi, and K is the number of tasks. Each step, task i’s loss Li is averaged over a batch, the small set of examples the model sees in that step. θ stands for all parameters, trunk and heads together.

input shared trunk θsh head 1 loss 1 head 2 loss 2 head 3 loss 3 123 input shared trunk θsh head 1 loss 1 head 2 loss 2 head 3 loss 3 123
forward pass gradient flow
Figure 3. Trunk 1 and heads 2 carry data forward; gradients 3 return to the trunk.

3.1A task gradient has one entry per shared weight

Task i’s gradient gi lists how fast its loss Li changes with each shared weight: it points where Li rises fastest, and its length says how fast. With one number per shared weight, a trunk with millions of weights gives a vector with millions of entries. Every arrow on this page is a 2D drawing of such vectors; two vectors always lie in one plane, so the lengths and angles drawn are exact. How each gi is computed in PyTorch is on Gradient Balancing Inside the Training Loop.

shared weights θshmillions in a real trunkg1… millionsg2… millions12g1g23
Figure 4. 1 One entry per shared weight; 2 millions in practice; 3 drawn as arrows.

4Train on the weighted sum of the losses

Take NYUv2, a set of indoor photos, and one network learning two tasks on it: semantic segmentation (seg, a class for every pixel) and depth (meters to every pixel). With wseg = wdepth = 0.5 the weighted total is half of each loss, so the step follows half of each task’s gradient. For two of the shared weights, illustrative gradients are gseg = (2, 1) and gdepth = (−6, 2).

Training several tasks at once adds their losses into one total and walks all the parameters θ downhill on that single number.
L(θ) = Σi wi Li(θ)
The total loss L adds each task’s loss Li times its loss weight wi; Σi means add over the tasks i = 1 to K. Raising wi makes task i count for more in every step, lowering it shrinks the task’s share of each step, at 0 the task drops out of training, and every weight at 1 gives the plain sum.
θ ← θ − η∇L(θ)
Each step of gradient descent replaces the parameters θ (← reads “becomes”) by themselves minus η times ∇L, the gradient of the total over all parameters; the gradient points uphill, so subtracting it, a step against ∇L, moves downhill. The step size η (the learning rate) sets how far each step goes: larger moves faster but can overshoot and make the loss jump, smaller is steadier but slower; PyTorch’s SGD defaults to 0.001 (SGD, Momentum and Nesterov). The methods in this series keep this step and change the weights inside L or the direction the step takes.
So the whole recipe is one weighted total and one downhill step on it: with w = 0.5 each, the gradient of the total on the two shared weights is half of (2, 1) plus half of (−6, 2), which is (−2, 1.5), and the step goes against it.
lowest loss∇L−η∇L123
Figure 5. 1 Equal-loss lines; 2 ∇L points uphill; 3 the step −η∇L goes downhill.

5Three common causes of negative transfer

When tasks are trained together on the plain sum, a task can end up worse than a separate model trained on that task alone; this is called negative transfer. Every task’s gradient changes the same trunk weights, so one task’s update can undo another’s. Three common causes, each with a different fix, are shown in Figure 1.

5.1Losses on different scales

Multiplying a loss by a number multiplies its gradient by the same number, so a loss measured on a larger scale, such as a loss near 600 next to one near 0.4, usually has a far longer gradient and so decides most of the step. It also makes up almost all of the total loss (Figure 6).

Each task’s share of the total loss
task 1 (made-up loss 600) task 2 (made-up loss 0.4)

Figure 6. The weights set each task’s share of the total; at equal weights task 2 gets a sliver.

Hand-tuned weights wi can fix this, but the tuning has to be redone whenever the tasks change.

5.2Tasks learn at different speeds

When one task is nearly solved early and another keeps improving, weights that were fair at the start are unfair later, so the balance has to change during training.

010020030000.51training steploss / starting losstoy run, two quadratic lossesstep size 0.5task 1task 2123
Figure 7. 1 Task 1 is under 5% by step 30; 2 task 2 is at 74%; 3 at 5% near step 300.

5.3Task gradients can point in conflicting directions

The cosine of the angle between two task gradients measures how much they point the same way. Past a right angle, part of each gradient works against the other; when that opposition is strong enough, a step against their sum raises one task’s loss (Section 7 gives the exact condition). Loss weights can pick a step that helps both tasks at one moment. A fixed weight keeps the same factor for all of training while the gradients’ lengths and angle change, so a setting that helps both tasks early can hurt one of them later. A combination chosen afresh at every step can be picked to help both whenever such a step exists.

g1g2g1g2g1g20°, cosine 1190°, cosine 02180°, cosine −13
Figure 8. A step against the sum lowers both losses at 1 and 2; at 3 loss 2 rises.

6Four vector operations on gradients

Two of the failures in Section 5, scale and direction, come down to the lengths and angles of task gradients.

6.1The norm is a gradient’s length

Recap The norm of a gradient is its length, the measure behind the scale failure of Section 5.1. Taught in Vectors and Matrices, Section 2.

In the pair of Section 4, depth’s gradient (−6, 2) is much longer than seg’s (2, 1).

A gradient’s length says how hard its task is pushing the shared weights at this step.
‖v‖ = √v12 + v22 + … + vn2
The task gradients measured here are the parts of the weighted-sum step of Section 4. For a vector v with entries v1 to vn, square each entry, add, and take the square root: Pythagoras’s theorem over all n entries, where for a gradient n is the number of shared weights.
So the norm turns each task’s push into one length to compare: seg’s (2, 1) has length √5 ≈ 2.236 and depth’s (−6, 2) has √40 ≈ 6.325, almost three times longer.
31v‖v‖ = √10 ≈ 3.1612
Figure 9. 1 Entries 3 and 1 are the legs; 2 the norm ‖v‖ = √10 ≈ 3.16 is the long side.

6.2The dot product and the cosine

Recap The dot product and the cosine say whether two gradients point the same way, the measure behind the direction failure of Section 5.3. Taught in Vectors and Matrices, Section 3.

In the same pair, seg’s (2, 1) points right and up while depth’s (−6, 2) points mostly left, so the two lean apart.

The dot product says whether two gradients pull the same way, and the cosine says it with their lengths taken out.
⟨u, v⟩ = Σj uj vj
Multiply matching entries uj and vj and add over all j.
⟨u, v⟩ = ‖u‖ ‖v‖ cos ψ
The same number equals both lengths, the norms of Section 6.1, times cos ψ, where ψ (psi) is the angle between the vectors. Lengths are positive, so the dot product’s sign is the sign of cos ψ: positive when the vectors lean the same way, zero at a right angle, negative when they lean apart.
cos ψ = ⟨u, v⟩‖u‖ ‖v‖
Dividing by both lengths removes scale: a long and a short gradient pointing the same way have cosine 1, which is why the cosine is the standard check for conflicting directions and the norm the check for scale.
So a negative dot product is the sign that one shared step cannot fully please both tasks: for seg and depth it is 2 × (−6) + 1 × 2 = −10, and the cosine is −10 over 2.236 × 6.325, which is −0.707, an angle of 135 degrees.

Figure 10 shows the dot product turning negative once two gradients lean apart past a right angle.

Figure 10. The arc is orange past a right angle, red if a small step against the average raises a loss, which happens only when the dot product is more negative than that task’s own squared length.

6.3Projecting one gradient onto another

Recap Projection splits one gradient into the part along another gradient and the part at a right angle to it. Taught in Vectors and Matrices, Section 4.

Because seg and depth lean apart, the part of seg’s (2, 1) that lies along depth’s (−6, 2) points against depth.

Projecting keeps the part of one gradient that lies along another, and what is left over sits at right angles to it.
proj = ⟨g1, g2⟩‖g2‖2 g2
The top of the fraction is the dot product of Section 6.2. The fraction is one number: how many copies of g2 make up g1’s part along it. It is negative when the two point apart, and then the projection points against g2.
g1 − proj ⟂ g2
Subtracting the projection leaves the remainder; ⟂ means “at a right angle to”, so the remainder’s dot product with g2 is 0.
So the projection splits g1 into a part that fights g2 and a part g2 never feels; PCGrad keeps that remainder. For seg on depth the fraction is −10 over 40 = −0.25, so the projection is (1.5, −0.5) and the remainder (0.5, 1.5).

Figure 11. The projection lies along g2; the remainder is at a right angle.

PCGrad and GradVac build on this projection.

6.4A convex combination is a weighted average

Recap A convex combination mixes the task gradients with weights that are zero or more and add to one; the plain average gives every task 1/K.

The weighted sum of Section 4 with w = 0.5 each steps against half of seg’s (2, 1) plus half of depth’s (−6, 2): one step that mixes both tasks.

A convex combination is a weighted average of the task gradients, so the step always lies between them.
d = Σi wi gi
The projection remainder of Section 6.3 changes one gradient; a blend keeps every gradient whole and only weights it. d is the combined direction. Each gi is the gradient of its own loss, so d is the gradient of the weighted sum of Section 4 with these weights: choosing a combination is choosing loss weights for one step.
wi ≥ 0,   Σi wi = 1
The weights are shares of a whole, so for two tasks the tip of d lies on the segment joining the two gradient tips.
So the plain average, w = 0.5 each, is the midpoint (−2, 1.5) of the segment from (2, 1) to (−6, 2), and other weights pick other points.
g1g2average12
Figure 12. 1 Each combination ends between the tips; 2 the average is midway.

7Whether a step helps each task

Each method in this series steps against some direction d over the shared weights; whether that step helps task i depends on the dot product of gi with d.

In the illustrative pair of Section 4, the average step (−2, 1.5) has dot product −2.5 with seg’s gradient (2, 1) and 15 with depth’s (−6, 2), so at a step size of 0.1 seg’s loss rises by about 0.25 while depth’s falls.

A step helps a task exactly when the step and that task’s gradient point the same way.
si = ⟨gi, d⟩
This is the dot product of Section 6.2, taken between a task gradient and the step. Task i’s score si is the dot product of its gradient with d, a measure of how much d agrees with gi. It is positive when d leans the same way as gi, and then a step against d lowers task i’s loss.
Li(θsh − η d) ≈ Li(θsh) − η si
For a small step size η, stepping the shared weights against d, with the heads held fixed, changes task i’s loss by about η times its score: down when si is positive, up when it is negative. ≈ means “close to, for small η”.
d = 12(g1 + g2)
This is the plain average of the two task gradients, the direction that equal loss weights give.
s2 = 12⟨g1, g2⟩ + 12‖g2‖2
Put the average into task 2’s score: half its dot product with g1 plus half its own squared length. The squared length is never negative, so only a negative dot product can pull the score below zero.
s2 < 0  ⇔  ⟨g1, g2⟩ < −‖g2‖2
⇔ means “exactly when”: the average hurts task 2 only when the dot product is more negative than task 2’s own squared length. Task 1 works the same way with ‖g1‖2, so at a right angle, where the dot product is 0, both tasks gain.
So the test reads straight off the gradients whether one shared step hurts a task. With d the average of Section 6.4, sseg = −2.5 and sdepth = 15. With seg as task 2 the last line reads −10 < −5, true, so seg is hurt; with depth as task 2 it reads −10 < −40, false.
g1 = (2, 0)s1 = +1.00, loss fallsg2 = (−1, 0.5)s2 = −0.38, loss risesaverage dmade-up numbers123
Figure 13. 1 The average leans to the longer g1; 2 loss 1 falls, 3 loss 2 rises.

MGDA builds on this score.

8Which method fixes which failure

Each failure from Section 5 leaves a different signal in the logged gradients or losses.

Failure, and what the logs showMethods that fix it
1 Losses on different scales (Section 5.1)One task’s gradient norm is far larger than the others’ from the start.GradNorm, Uncertainty Weighting
2 Tasks learn at different speeds (Section 5.2)The losses, each as a fraction of its start, drift apart during training.GradNorm
3 Conflicting directions (Section 5.3)The cosine between two task gradients is negative.PCGrad, GradVac, CAGrad, MGDA
Figure 14. Each failure 1 to 3, its logged signal, and its fixes.
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?
MGDAWhich convex combination of task gradients lowers every task's loss at once, and when does no such combination exist?
Figure 15. The question each method answers.

Whichever method you use, the loss scale still sets the gradients going in, and the optimizer and gradient clipping (capping a gradient’s length) still change the combined gradient coming out; Gradient Balancing Inside the Training Loop shows how.

Which of these failures does your own run have? The Multitask Field Guide reads it off the logged norms and cosines.

9References

  1. Caruana, R. (1997). Multitask learning. Machine Learning, 28(1), 41-75.
  2. Ruder, S. (2017). An overview of multi-task learning in deep neural networks. arXiv:1706.05098.
  3. Vandenhende, S., et al. (2022). Multi-task learning for dense prediction tasks: A survey. IEEE TPAMI, 44(7), 3614-3633.