預訓練模型 fine tune 方法小結

  • 2021 年 4 月 12 日
  • AI

還有一些其它雜七雜八的文獻以及百度和google上的網友分享的經驗之談。


1、數據層面:

分詞算法和pretrained model保持一致沒什麼問題,

(1)截斷問題:使用三種方法,簡單取頭512個tokens,尾512個tokens,頭128+尾382個tokens三種策略(關於超長文本的bert 應用其實有非常多的方法,這裡僅僅使用了比較簡單的截斷)

(2)用下游任務對標的語料繼續pretrain一下然後再finetune,因為下游語料的分佈可能和訓練語料的分佈存在差異;還有用不同領域的語料來繼續pretrain的。。迷茫。

(3)數據增強,推薦nlp_augment和text attack 這兩個library,實現了大部分常見的nlp數據增強的方法,除此之外,還有人通過graph來增強的。

2、layers 層面:

(1) 因為bert的不同layer對於不同下游任務具有不同的適應性,比如k層對A任務效果更好,L層對B任務效果更好,所以做法就是嘗試用不同層的輸出直接完成下游任務,不一定到最後一個transformer block;

(2) 凍結不同層,僅fine tune部分層

(3)不同層的輸出做concat,各種交叉組合balabala

3、輸出層面:

sentence bert 中提到比較多策略,mean max pooling或者cls,mean pooling效果據說最好,除此之外,因為bert的layer輸出是一個sequece,這和早期文本分類的各種網絡結構輸入sentence的每個詞的embedding的形式一樣,所以接各類cnn ,lstm甚至新的self attention結構也沒什麼問題,可以統一把 cnn,rnn,mean,max,self attention等都看作是pooling(GNN里就把LSTM看作一種pooling了)

4、超參數設置:

(1)learning rate:2e-5,weight decay 不對layer norm和bias做僅對其它weights做(hugging face的trainer的默認策略)克服遷移過程中的災難性遺忘問題;

(2)分層學習率,類似於CNN,淺層transformer block學習泛化represent,高層學習特定represent,所以越淺則學習率越低,第一個transformer block用2e-5,按照1/0.95的速率增長,越深層學習率越大;

(3)batch size,可承受範圍內盡量大,主要為了快,至於效果,說不準。

(4)warm up steps,lr schedule,epochs數量,dropout rate等,太trick,不同paper用的都有一些不太一樣,沒啥好總結的,建議一開始按照hugging face上官方默認的超參數設置就好,然後根據需要自己微調。

5、多任務學習:

這塊看MTDNN比較好,多任務獲得很好的效果,簡單來說就是多個任務頭,多個loss直接簡單相加(目前基本上沒看到什麼好的結果是關於在多任務上做多目標優化得到的),多個任務的選擇比較關鍵,然後一個技巧就是多任務學完再到最終的目標任務上再fine tune一下。

另外還有一大堆針對特定nlp任務做的其它的一些技巧,這部分算了吧,推薦還是看比賽的solution代碼以及huggingface上的各種tutorial,最實際效果最好。

最後是個人使用的經驗:

1、盡量大batch節約時間,learning rate盡量小,覺得慢就大點學習率+lr schedule慢慢調,大小建議按照官方給的就好了別瞎改;

2、輸出pooling效果普遍比僅用cls好;

3、pretrain效果還是可以,下游對標的語料繼續pretrain可以找到更好的起點,這個方法還是比較立竿見影的;

4、盡量把torch的性能優化做好,不知道會給你節約多少時間,fp16,deepspeed,DDP,多gpu這類的(這部分放到torch的性能優化總結,都很簡單,都封裝好了,幾行代碼就完事兒了)

5、數據永遠是第一位,無他,數據增強還是不錯的;

6、語料還是需要做一定預處理的,但是做過頭了反而損失性能,這很尷尬,至於怎麼做預處理,刪什麼東西,補什麼東西,我也總結不了,不同的應用可能做起來效果差很多;

7、過擬合上正則,weight de’cay,dropout,對抗訓練之類的,這個和常規的網絡優化差不多;

8、盡量多focus在數據上少focus在調參上,bert跑一次普通的機器要跑死,沒什麼空間給你調太多參數的。