NLP 模型的特點
通常自然語言處理模型的輸入是非常稀疏的婆硬。對于包含幾十萬上百萬詞的詞表习贫,在訓練的每個 Batch 中能出現(xiàn)的獨立詞數(shù)不超過幾萬個。也就是說兄淫,在每一輪梯度計算過程中屯远,只有幾萬個詞的 embedding 的梯度是非 0 的,其它 embedding 的梯度都是 0捕虽。
Adam 優(yōu)化器的特點
Adam 優(yōu)化器可以說是目前使用最廣泛慨丐、收斂速度較快且收斂過程較穩(wěn)定的優(yōu)化器。Adam 的計算公式如圖所示泄私》拷遥可以看到公式中梯度的計算使用了動量原理,每一輪用于梯度下降的梯度是當前計算的真實梯度與上一輪用于梯度下降的梯度的加權和晌端。這樣動量的引入可以防止訓練時產生震蕩捅暴。Adam 優(yōu)化器的學習率對于不同參數(shù)也是不同的,由該參數(shù)歷史每一輪的真實梯度的大小決定咧纠。好處是對于 NLP 這種輸入極度稀疏且輸入特征極度不平衡(例如整個預料庫中“我”這樣的詞經常出現(xiàn)蓬痒,而“拉姆塞”這樣的詞只出現(xiàn)幾次)的任務,學習率是自適應的漆羔,一些在一次訓練 epoch 中只更新幾次的 embedding梧奢,在訓練后期還是會有較大的學習率狱掂。問題
NLP 輸入稀疏的特點與 Adam 使用動量計算梯度的特點相結合就引入了麻煩。每一輪更新參數(shù)時亲轨,只有極少數(shù) embedding 的梯度是非 0 的趋惨,大部分 embedding 的梯度是 0 即上圖公式中的 gt 是 0。但是惦蚊,計算了動量之后器虾,這些原本梯度都應該是 0 的 embedding 有了非零梯度 mt 用于梯度下降更新。想象一個極端的例子蹦锋,“拉姆塞”這個詞在一個 epoch 中只在第一個 batch 出現(xiàn)了兆沙,于是第一個 batch 計算了“拉姆塞”這個 embedding 的真實梯度 g0 用于更新參數(shù),在以后的每個 batch 中雖然“拉姆塞”這個詞沒有出現(xiàn)過晕粪,Adam 都會計算它的動量梯度 mt挤悉,并用于更新“拉姆塞”這個 embedding渐裸,實際上方向與 g0 完全相同巫湘,只是每一輪做一次 β1 倍的衰減。這樣的做法就相當于對這些出現(xiàn)次數(shù)較少的低頻詞的 embedding昏鹃,每次梯度下降的等效學習率是非常大的尚氛,容易引起類似過擬合的問題。
解決方法
知道了問題的根節(jié)洞渤,解決方法就很簡單了阅嘶,每輪迭代只更新這個 batch 中出現(xiàn)過的詞的 embedding 即可。TensorFlow 中可以使用 tf.contrib.opt.LazyAdamOptimizer载迄,也可參考 https://www.zhihu.com/question/265357659/answer/580469438 的實現(xiàn)讯柔。