論文解讀:"Gradient Surgery for Multi-Task Learning"
1. 論文標題直譯
- Gradient Surgery: 梯度手術
- for Multi-Task Learning: 應用于多任務學習
合在一起就是:為多任務學習量身定制的梯度手術。這個名字非常形象地概括了它的核心思想。
2. 它要解決的核心問題:多任務學習中的“梯度沖突”
想象一下,你正在訓練一個AI模型來開一輛車,它需要同時完成兩個任務:
- 任務A: 識別紅綠燈(要求模型關注圖像上方的顏色區域)。
- 任務B: 保持在車道線內(要求模型關注圖像下方的白色線條)。
在訓練時,模型會根據任務A的錯誤計算出一個梯度?
,根據任務B的錯誤計算出另一個梯度?g_B
。梯度本質上是告訴模型參數“應該朝哪個方向更新才能做得更好”。
問題來了:?如果某次更新中,
?說“參數應該向東調整”,而?
?恰好說“參數應該向西調整”,那么把它們簡單相加( +
)的結果可能接近于零,模型幾乎學不到任何東西。
更常見的情況是,
?想讓參數向東走,
?想讓參數向西北走。它們的合力會是一個“折衷”的方向,這個方向可能對兩個任務都不是最優的,甚至可能提升一個任務的性能卻損害了另一個。
這種現象就叫做梯度沖突 (Gradient Conflict)?或?負遷移 (Negative Transfer)。這是多任務學習中一個長期存在的痛點,它會導致訓練不穩定,模型性能難以提升。
3. PCGrad 的解決方案:“梯度手術”
PCGrad
?(Projected Gradient Descent) 提出了一種非常聰明的解決方案,就像一個外科醫生一樣,在更新模型參數之前,先對這些相互沖突的梯度做一次“手術”。
手術流程如下:
第1步:分別計算每個任務的梯度?和傳統方法不同,它不把所有損失加起來,而是為每個任務的損失?,?
... 單獨計算梯度?
,?
...
第2步:診斷是否存在“沖突”?PCGrad 遍歷所有梯度對(如?
?和?
),并通過計算它們的點積 (dot product)?來判斷它們是否沖突。
- 如果?
dot(
: 說明兩個梯度的夾角小于90度,它們大方向一致,是“盟友”。無需手術。,
) > 0
- 如果?
dot(
: 說明兩個梯度的夾角大于90度,它們的方向是“敵對”的。診斷為沖突,需要手術!,
) < 0
第3步:執行“手術”——投影和矯正?當檢測到?
?和?
?沖突時,PCGrad 會執行以下操作:
- 投影 (Project):將梯度?
?投影到梯度?
?的方向上,得到一個分量?(
)
。這個分量可以被理解為?
?中與?
?“正面沖突”的那一部分。 - 矯正 (Correct):從原始梯度?
?中減去這個沖突分量:=
-
(
)
。
手術效果:?經過手術后的新梯度??與?
?變成了正交的(夾角為90度)。這意味著,?的更新方向中,已經完全剔除了與?
?直接對抗的部分。它只保留了對自己有益,且不傷害對方的部分。
PCGrad 會對所有發生沖突的梯度對都執行這個“手術”。
第4步:合并與更新?將所有經過“手術”矯正后的新梯度相加,得到最終的、和諧的、沒有內斗的梯度,然后用這個梯度去更新模型參數。
4. TensorFlow 實現中的 PCGrad
你在代碼中看到的?PCGrad
?通常是一個優化器包裝器 (Optimizer Wrapper)。它的用法一般是這樣的:
-
首先,定義一個基礎的優化器,比如 Adam。
base_optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3)
-
然后,用?
PCGrad
?包裝它。from .PCGrad import PCGrad optimizer = PCGrad(base_optimizer)
-
在訓練循環中,用法會稍有不同。 你不再是計算一個總的 loss 然后調用?
apply_gradients
。而是:# 1. 分別計算每個任務的 loss loss_A = compute_loss_A(y_true_A, y_pred_A) loss_B = compute_loss_B(y_true_B, y_pred_B) list_of_losses = [loss_A, loss_B]# 2. PCGrad 優化器會接管梯度的計算和矯正 # 這一步是 PCGrad 內部實現的,它會: # - 為每個 loss 計算梯度 # - 執行梯度手術 # - 返回最終的梯度 # 通常會通過一個自定義的 train_step 來實現 final_gradients = optimizer.get_gradients(list_of_losses, model.trainable_variables)# 3. 應用經過手術后的梯度 optimizer.apply_gradients(zip(final_gradients, model.trainable_variables))
總結
方面 | 解釋 |
---|---|
它是什么? | PCGrad ?是一種優化策略,而非損失函數或模型架構。 |
解決什么問題? | 解決多任務學習中的梯度沖突 (Gradient Conflict)?問題。 |
核心思想? | 梯度手術 (Gradient Surgery):在更新模型前,先檢測并消除梯度之間的沖突部分。 |
如何實現? | 通過向量投影,將沖突的梯度分量從原始梯度中移除,使它們變得正交。 |
最終效果? | 1. 訓練過程更穩定。 2. 避免了任務間的“內耗”,有助于所有任務性能的同步提升。 |
因此,當你看到代碼中使用了?PCGrad
,就可以立刻明白:這個項目正在處理一個多任務學習的場景,并且使用了一種相當先進的技術來確保不同任務能夠“和平共處”,協同進步。