BERT模型有什麼調參技巧?
感覺很多nlp比賽都是bert調參比賽,那麼有什麼調參技巧可以脫穎而出呢?或者不用bert從哪些方面考慮能達到比bert更好的效果?
可以先看看這個
上文回答中提到How to Fine-Tune BERT for Text Classification,正好最近看到了這篇論文,這裡簡單說一下文中提到的技巧。
1. Fine-tune策略
神經網路的不同層可以捕獲不同的語法和語義信息。使用Bert去訓練下游任務需要考慮幾個問題:
- 預訓練的長本文,因為Bert的最長文本序列是512
- 層數選擇,正如上文所述哦,每一層都會捕獲不同的信息,因此我們需要選擇最適合的層數
- 過擬合問題,因此需要考慮合適的學習率。Bert的底層會學習到更多的通用的信息,文中對Bert的不同層使用了不同的學習率。 每一層的參數迭代可以如下所示:
其中
- 表示第l層第t步迭代的參數
- 表示第l層的學習率,計算方式如下。 表示衰敗係數,當&>1表示學習率逐層衰減,否則表示逐層擴大。當=1時和傳統的Bert相同。
2. 深度預訓練
Bert是在通用的語料上進行預訓練的,如果要在特定領域應用文本分類,數據分佈一定是有一些差距的。這時候可以考慮進行深度預訓練。
- Within-task pre-training:Bert在訓練語料上進行預訓練
- In-domain pre-training:在同一領域上的語料進行預訓練
- Cross-domain pre-training:在不同領域上的語料進行預訓練
3. 多任務Fine-tune
多任務微調就是使用Bert去訓練不同的下游任務但是除了最後一層,在其他層共享參數。
實驗比較多這裡有興趣可以去我的文章裏看一下:
lynne阿黎:Bert微調技巧實驗大全?zhuanlan.zhihu.comHow to Fine-Tune BERT for Text Classification?arxiv.org阿力阿哩哩:煉丹技巧 | BERT的下接結構調參?zhuanlan.zhihu.com
除了上述方法之外,還有很多 trick 可以提升 BERT 的效果與速度。這裡推薦大家讀一下 bienlearn 上的 BERT 專欄。
這個 BERT 專欄由自然語言處理領域的 KOL——「夕小瑤的賣萌屋」作者團主筆,幫助新手以及有一定基礎的同學快速上手 BERT,既包括原理、源碼的解讀,還有 BERT 系的改進串講與高級精調技巧。不管是準備面試、項目實戰還是比賽刷分,都可以找到對應的內容。
目前在限時優惠,更詳細的內容大家可以點擊下方卡片查看
之前寫過一篇文章,正好回答這個問題。
阿力阿哩哩:煉丹技巧 | BERT的下接結構調參?zhuanlan.zhihu.com現在我們基於(阿力阿哩哩:2019BDCI互聯網金融實體識別(單模第一,綜合第二名思路與代碼框架傻瓜式分享))代碼實踐來介紹一下BERT如何調參才能更加充分訓練,使得到的模型性能更好。
具體代碼鏈接:
https://github.com/ChileWang0228/Deep-Learning-With-Python/tree/master/chapter8?github.com?github.com1.Epoch
epoch:訓練模型的迭代次數。我們主要看損失是否收斂在一個穩定值,若收斂則當前設置的epoch為最佳。一般來說BERT的fine-tune epochs範圍為[2, 3, 4]。
2.BatchSize
BatchSize:我們用來更新梯度的批數據大小。一般來說,Batch Size設置的不能太大也不能太小,一般為幾十或者幾百。筆者的調參經驗是看GPU佔用率。我們在命令行輸入gpustat查看GPU佔用率,如圖 4.32所示。Batch Size越大,GPU佔用率也就越高,一般佔滿整個GPU卡訓練模型為最佳。業界傳聞使用2的冪次可以發揮更佳的性能,筆者並沒有嘗試過,大家可以去嘗試一下。
眾所周知,BERT模型比較大,所以我們fine-tune的時候Batch Size肯定不會太大的,所以儘可能佔滿GPU即可。
3.Learning Rate
我們在阿力阿哩哩:BERT的原理與應用提及BERT原文提示用Learning Rate:[5e-5, 3e-5, 2e-5]效果會最好,這是沒錯的,因為BERT原文的任務並沒有下接結構,直接用BERT本體去fine-tune了。
那麼如果我們加上了下接結構呢?比如我們在文章開頭提到的代碼實踐,我們的NER模型是由BERT + BiLSTM + CRF組成,也就是說除了本體BERT之外,我們還有下接結構BiLSTM + CRF,這時候我們的學習率應該有兩個:
BERT的fine-tune學習率:[5e-5, 3e-5, 2e-5]
下接結構BiLSTM + CRF學習率:1e-4
至於這麼做的原因也很簡單:BERT本體是已經預訓練過的,即本身就帶有權重,所以用小的學習率很容易fine-tune到最優點,而下接結構是從零開始訓練,用小的學習率訓練不僅學習慢,而且也很難與BERT本體訓練同步。
為此,我們將下接結構的學習率調大,爭取使兩者在訓練結束的時候同步:當BERT訓練充分時,下接結構也訓練充分了,最終的模型性能當然是最好的。
對BERT結構與下接結構分別採用不同的學習率進行微調,具體代碼如下:
1. with session.as_default():
2. model = Model(config) # 讀取模型結構圖
3. # 超參數設置
4. global_step = tf.Variable(0, name=step, trainable=False)
5. learning_rate = tf.train.exponential_decay(config.learning_rate, global_step, config.decay_step, config.decay_rate, staircase=True)
6. # 下接結構的學習率
7. normal_optimizer = tf.train.AdamOptimizer(learning_rate)
8.
9. all_variables = graph.get_collection(trainable_variables)
10. # BERT的參數
11. word2vec_var_list = [x for x in all_variables if bert in x.name]
12.
13. # 下接結構的參數
14. normal_var_list = [x for x in all_variables if bert not in x.name]
15. print(bert train variable num: {}.format(len(word2vec_var_list)))
16. print(normal train variable num: {}.format(len(normal_var_list)))
17.
18. normal_op = normal_optimizer.minimize(model.loss, global_step=global_step, var_list=normal_var_list)
19. num_batch = int(train_iter.num_records / config.batch_size * config.train_epoch)
20. embed_step = tf.Variable(0, name=step, trainable=False)
21. if word2vec_var_list: # 對BERT微調
22. print(word2vec trainable!!)
23. word2vec_op, embed_learning_rate, embed_step = create_optimizer(
24. model.loss, config.embed_learning_rate, num_train_steps=num_batch , num_warmup_steps=int(num_batch * 0.05) , use_tpu=False , variable_list=word2vec_var_list
25. )
26. # 組裝BERT與下接結構參數
27. train_op = tf.group(normal_op, word2vec_op)
28. else:
29. train_op = normal_op
我不知道您是做什麼的,我最近正好再用bert做求助內容的分類訓練。由於公司小,運營少。只給了1k的求助數據量,負樣本自己找的。emmm,可以想像,無論是bert分類還是bert embedding後+分類模型,相比於fasttext,都被全面碾壓。當日也可能是我調參調的不好。。。畢竟幾千萬參數。。
如果問的是預訓練調參,因為mlm本身訓練數據分佈很雜,需要很大的batch size, 特別是訓練後期。由於訓練規模較大,優化器的選擇和調參對結果都至關重要。需要先在小數據集上驗證各種參數的收斂速度,在推廣到大數據集。
bert 不同學習率下的指標。
lr:2e-5 auc:0.88 lr:5e-5 auc:0.87
推薦閱讀: