ACL2020 Best Paper有一篇論文提名獎,《Don't Stop Pretraining: Adapt Language Models to Domains and Tasks》。這篇論文做了很多語言模型預訓練的實驗,系統的分析了語言模型預訓練對子任務的效果提升情況。有幾個主要結論:
在目標領域的數據集上繼續預訓練(DAPT)可以提升效果;目標領域的語料與RoBERTa的原始預訓練語料越不相關,DAPT效果則提升更明顯。
在具體任務的數據集上繼續預訓練(TAPT)可以十分“廉價”地提升效果。
結合二者(先進行DAPT,再進行TAPT)可以進一步提升效果。
如果能獲取更多的、任務相關的無標註數據繼續預訓練(Curated-TAPT),效果則最佳。
如果無法獲取更多的、任務相關的無標註數據,採取一種十分輕量化的簡單數據選擇策略,效果也會提升。
雖然在bert上語言模型預訓練在算法比賽中已經是一個穩定的上分操作。但是上面這篇文章難能可貴的是對這個操作進行了系統分析。大部分中文語言模型都是在tensorflow上訓練的,一個常見例子是中文roberta項目。可以參考https://github.com/brightmart/roberta_zh
使用pytorch進行中文bert語言模型預訓練的例子比較少。在huggingface的Transformers中,有一部分代碼支持語言模型預訓練(不是很豐富,很多功能都不支持比如wwm)。為了用最少的代碼成本完成bert語言模型預訓練,本文借鑒了裡面的一些現成代碼。也嘗試分享一下使用pytorch進行語言模型預訓練的一些經驗。主要有三個常見的中文語言模型
(https://huggingface.co/bert-base-chinese)
這是最常見的中文bert語言模型,基於中文維基百科相關語料進行預訓練。把它作為baseline,在領域內無監督數據進行語言模型預訓練很簡單。只需要使用官方給的例子就好。
https://github.com/huggingface/transformers/tree/master/examples/language-modeling (本文使用的transformers更新到3.0.2)
python run_language_model_bert.py --output_dir=output --model_type=bert --model_name_or_path=bert-base-chinese --do_train --train_data_file=train.txt --do_eval --eval_data_file=eval.txt --mlm --per_device_train_batch_size=4
(https://github.com/ymcui/Chinese-BERT-wwm)
哈工大訊飛聯合實驗室發布的預訓練語言模型。預訓練的方式是採用roberta類似的方法,比如動態mask,更多的訓練數據等等。在很多任務中,該模型效果要優於bert-base-chinese。 因為中文roberta類的配置文件比如vocab.txt,都是採用bert的方法設計的。英文roberta模型讀取配置文件的格式默認是vocab.json。對於一些英文roberta模型,倒是可以通過AutoModel自動讀取。這就解釋了huggingface的模型庫的中文roberta示例代碼為什麼跑不通。 https://huggingface.co/models?
如果要基於上面的代碼run_language_modeling.py繼續預訓練roberta。還需要做兩個改動。
假設config.json已經改好,可以運行如下命令。
python run_language_model_roberta.py --output_dir=output --model_type=bert --model_name_or_path=hflroberta --do_train --train_data_file=train.txt --do_eval --eval_data_file=eval.txt --mlm --per_device_train_batch_size=4
https://github.com/nghuyong/ERNIE-Pytorch)
ernie是百度發布的基於百度知道貼吧等中文語料結合實體預測等任務生成的預訓練模型。這個模型的準確率在某些任務上要優於bert-base-chinese和roberta。如果基於ernie1.0模型做領域數據預訓練的話只需要一步修改。
python run_language_model_ernie.py --output_dir=output --model_type=bert --model_name_or_path=ernie --do_train --train_data_file=train.txt --do_eval --eval_data_file=eval.txt --mlm --per_device_train_batch_size=4