本文譯自Deep Multi-Task Learning – 3 Lessons Learned by Zohar Komarovsky
在過去幾年裡,Multi-Task Learning (MTL)廣泛用於解決多個Taboola(公司名)的業務問題。在這些業務問題中, 人們使用一組相同的特徵以及深度學習模型來解決MTL相關問題。在這裡簡單分享一下我們做MTL時學習到的一些小知識。
小知識第一條:整合損失函數
MTL模型中的第一個挑戰: 如何為multiple tasks定義一個統一的損失函數?最簡單的辦法,我們可以整合不同tasks的loss function,然後簡單求和。這種方法存在一些不足,比如當模型收斂時,有一些task的表現比較好,而另外一些task的表現卻慘不忍睹。其背後的原因是不同的損失函數具有不同的尺度,某些損失函數的尺度較大,從而影響了尺度較小的損失函數發揮作用。這個問題的解決方案是把多任務損失函數「簡單求和」替換為「加權求和」。加權可以使得每個損失函數的尺度一致,但也帶來了新的問題:加權的超參難以確定。
幸運的是,有一篇論文《Multi-Task Learning Using Uncertainty to Weigh Losses for Scene Geometry and Semantics》通過「不確定性(uncertainty)」來調整損失函數中的加權超參,使得每個任務中的損失函數具有相似的尺度。該算法的keras版本實現,詳見github。
小知識第二條:調整學習率 learning rate
在神經網絡的參數中,learning rate是一個非常重要的參數。在實踐過程中,我們發現某一個learnig rate=0.001能夠把任務A學習好,而另外一個learning rate=0.1能夠把任務B學好。選擇較大的learning rate會導致某個任務上出現dying relu;而較小的learning rate會使得某些任務上模型收斂速度過慢。怎麼解決這個問題呢?對於不同的task,我們可以採用不同的learning rate。這聽上去很複雜,其實非常簡單。通常來說,訓練一個神經網絡的tensorflow代碼如下:
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(loss)
其中AdamOptimizer定義了梯度下降的方式,minimize則計算梯度並最小化損失函數。我們可以通過自定義一個minimize函數來對某個任務的變量設置合適的learning rate。
all_variables = shared_vars + a_vars + b_vars
all_gradients = tf.gradients(loss, all_variables)
shared_subnet_gradients = all_gradients[:len(shared_vars)]
a_gradients = all_gradients[len(shared_vars):len(shared_vars + a_vars)]
b_gradients = all_gradients[len(shared_vars + a_vars):]
shared_subnet_optimizer = tf.train.AdamOptimizer(shared_learning_rate)
a_optimizer = tf.train.AdamOptimizer(a_learning_rate)
b_optimizer = tf.train.AdamOptimizer(b_learning_rate)
train_shared_op = shared_subnet_optimizer.apply_gradients(zip(shared_subnet_gradients, shared_vars))
train_a_op = a_optimizer.apply_gradients(zip(a_gradients, a_vars))
train_b_op = b_optimizer.apply_gradients(zip(b_gradients, b_vars))
train_op = tf.group(train_shared_op, train_a_op, train_b_op)值得一提的是,這樣的trick在單任務的神經網絡上效果也是很好的。
小知識第三條:任務A的評估作為其他任務的特徵
當我們構建了一個MTL的神經網絡時,該模型對於任務A的估計可以作為任務B的一個特徵。在前向傳播時,這個過程非常簡單,因為模型對於A的估計就是一個tensor,可以簡單的將這個tensor作為另一個任務的輸入。但是後向傳播時,存在著一些不同。因為我們不希望任務B的梯度傳給任務A。幸運的是,Tensorflow提供了一個API tf.stop_gradient。當計算梯度時,可以將某些tensor看成是constant常數,而非變量,從而使得其值不受梯度影響。代碼如下:
all_gradients = tf.gradients(loss, all_variables, stop_gradients=stop_tensors)
再次值得一提的是,這個trick不僅僅可以在MTL的任務中使用,在很多其他任務中也都發揮著作用。比如,當訓練一個GAN模型時,我們不需要將梯度後向傳播到對抗樣本的生成過程中。
感謝閱讀,希望本文對您有所幫助!謝謝!
如果覺得文章對您有幫助,可以關注本人的微信公眾號:機器學習小知識
推薦閱讀
AINLP年度閱讀收藏清單
自動作詩機&藏頭詩生成器:五言、七言、絕句、律詩全了
From Word Embeddings To Document Distances 閱讀筆記
模型壓縮實踐系列之——bert-of-theseus,一個非常親民的bert壓縮方法
這門史丹福大學自然語言處理經典入門課,我放到B站了
可解釋性論文閱讀筆記1-Tree Regularization
徵稿啟示 | 稿費+GPU算力+星球嘉賓一個都不少
關於AINLP
AINLP 是一個有趣有AI的自然語言處理社區,專注於 AI、NLP、機器學習、深度學習、推薦算法等相關技術的分享,主題包括文本摘要、智能問答、聊天機器人、機器翻譯、自動生成、知識圖譜、預訓練模型、推薦系統、計算廣告、招聘信息、求職經驗分享等,歡迎關注!加技術交流群請添加AINLPer(id:ainlper),備註工作/研究方向+加群目的。