超詳細中文預訓練模型ERNIE使用指南

本文做者:楊蕊1002html

實習之後由於各類事就很久沒寫過文章了。最近在工做上處理的都是中文語料,也嘗試了一些最近放出來的預訓練模型(ERNIE,BERT-CHINESE,WWM-BERT-CHINESE),比對以後仍是以爲百度的ERNIE效果會比較好,並且使用十分方便,因此今天就詳細地記錄一下。但願你們也都能在本身的項目上取得進展~git

1A Glance at ERNIEgithub

關於ERNIE模型自己的話這篇不會作過多介紹,網上的介紹文檔也不少了,相信從事NLP的同窗們確定都很是熟悉啦。web

 

2ERNIE源碼淺嘗bash

Okay,當咱們瞭解了ERNIE模型的大致框架及原理以後,接下來就能夠深刻理解一下具體的實現啦。ERNIE是基於百度本身的深度學習框架飛槳(PaddlePaddle)搭建的,(百度推這個飛槳的力度仍是蠻大的,還開放了免費算力),你們平時煉丹用的更多的多是TensorFlow和Pytorch,這裏關於運行ERNIE的飛槳環境安裝能夠參考快速安裝指南(https://www.paddlepaddle.org.cn/#quick-start)。框架

2.1 關於輸入dom

模型預訓練的輸入是基於百科類、資訊類、論壇對話類數據構造具備上下文關係的句子對數據,利用百度內部詞法分析工具對句對數據進行字、詞、實體等不一樣粒度的切分,而後基於 tokenization.py中的 CharTokenizer 對切分後的數據進行 token 化處理,獲得明文的 token 序列及切分邊界,而後將明文數據根據詞典 config/vocab.txt 映射爲 id 數據,在訓練過程當中,根據切分邊界對連續的 token 進行隨機 mask 操做。通過上述預處理以後的輸入樣例爲:函數

 

1 1048 492 1333 1361 1051 326 2508 5 1803 1827 98 164 133 2777 2696 983 121 4 19 9 634 551 844 85 14 2476 1895 33 13 983 121 23 7 1093 24 46 660 12043 2 1263 6 328 33 121 126 398 276 315 5 63 44 35 25 12043 2;0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1;0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55;-1 0 0 0 0 1 0 1 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 1 0 1 0 0 0 0 1 0 0 0 0 -1 0 0 0 1 0 0 1 0 1 0 0 1 0 1 0 -1;0工具

 

一共有五個部分組成,每一個部分之間用分號;隔開:源碼分析

  • token_ids:輸入句子對的表示;
  • sentence_type_ids:0或者1表示token屬於哪個句子;
  • position_ids:絕對位置編碼
  • seg_labels: 表示分詞邊界信息,0表示詞首、1表示非詞首、-1爲佔位符
  • next_sentence_label:表示該句子對是否存在上下句的關係(0爲無1爲有)

reader.pretraining.py中的parse_line函數.

2.2 關於mask策略 batching.py

咱們知道,相較於BERT,ERNIE最大的改進就是中文 + 短語/實體掩碼(這個短語掩碼的操做後來也被BERT採用訓練出了WWM-BERT),因此咱們首先來看看ERNIE的掩碼機制是怎麼樣實現的。

2.3 關於infer過程代碼改寫

ERNIE代碼很方便使用,可是有一個不足的地方就是目前官方尚未給出infer.py文件,也就是模型訓練以後給出快速推理結果的文件。Github上簡直萬人血書求接口呀。

 

因此咱們的目的就是須要改寫源碼,完成這樣一個接口:輸入爲咱們須要預測的文件predict.tsv,調用接口後輸出爲相應任務的結果pred_result。下面咱們以分類任務爲例,改寫一個infer接口。

Step 1. finetune下的classifier.py

在文件中完成predict函數

Step 2. run_classifier.py

修改predict_only=True時的邏輯

Step 3. finetune_args.py

在該文件中添加一個參數do_predict

OK, 篇幅有限後面還要介紹具體ERNIE實戰,源碼閱讀部分就先這樣,其實剩下的不少都跟BERT代碼比較類似,感興趣的同窗也能夠參考以前的 BERT源碼分析系列https://blog.csdn.net/Kaiyuan_sjtu/article/details/90265473

 

3ERNIE實戰指南

上面扯的都是務虛的,接下來咱們務實地來看看ERNIE這個預訓練模型的具體應用。和BERT相比,ERNIE的使用更加簡單,在以前介紹過的BERT模型實戰之多文本分類(https://blog.csdn.net/Kaiyuan_sjtu/article/details/88709580中,咱們須要手動改寫一個適應本身任務的Processor,而對於ERNIE來講,簡單到只須要三步:

  • 把數據準備成要求的格式(源碼中使用tsv格式,不過在bert中咱們也說過了,能夠修改爲各類格式的)
  • 寫一下訓練腳本sh
  • 跑腳本獲得結果bash run_script.sh

準備工做

對於最近大火的預訓練模型來講,絕大多數咱們是不太可能本身從頭開始訓練的,最多使用的是官方開源的模型進行特定任務的Finetune。因此第一步就是下載模型代碼

https://github.com/PaddlePaddle/ERNIE/tree/develop/ERNIE

以及相應的參數https://baidu-nlp.bj.bcebos.com/ERNIE_stable-1.0.1.tar.gz

接下去就是準備咱們任務的數據,使其符合ERNIE模型輸入要求。通常來講字段之間都是label和text_a用製表符分割,對於句對任務還須要額外的text_b字段。在後面咱們會具體介紹每種任務的示例輸入。

ok,前面咱們一直強調ERNIE是超友好上手超快的模型,下面咱們結合實際任務來看一看到底有多簡單~

情感分類

情感分類是屬於很是典型的NLP基礎任務之一,由於以前BERT寫過文本分類,因此這裏咱們就稍微換一換口味~這裏咱們只考慮最簡單狀況的情感分類任務,即給定一個輸入句子,要求模型給出一個情感標籤,能夠是隻有正負的二分類,也能夠是包括中性情感的三分類。ok,咱們來看看數據,網上隨便找了一個財經新聞數據集,數據來源於雪球網上萬得資訊發佈的正負面新聞標題,數據集中包含17149條新聞數據,包括日期、公司、代碼、正/負面、標題、正文6個字段,其中正面新聞12514條,負面新聞4635條。大概長這樣:

處理成ERNIE分類任務所須要的輸入,大概長這樣:

將處理完成的數據和前面下載好的預訓練模型參數放置到合適的位置,就能夠開始寫咱們跑模型的腳本文件了:

嗯,這樣一個任務就結束了…運行腳本後等待輸出結果便可,是否是很簡單~

固然若是你還想玩點花樣的話,就能夠多看看論文。好比復旦以前有一篇文章是在BERT的基礎上,將ABSA情感分類的單句分類任務轉變成了句子對的類似度匹配任務。簡單來講就是經過構建輔助句子,把輸入這家餐館的鍋包肉超好吃變成了這家餐館的鍋包肉超好吃 + 菜品口感的情感是正的,論文代表這一trick是會比單句分類的效果更好。更具體的細節能夠參考論文:
Utilizing BERT for Aspect-Based Sentiment Analysis via Constructing Auxiliary Sentence》:https://www.aclweb.org/anthology/N19-1035

 

命名實體識別

命名實體識別也是NLP的一個基礎任務,以前在博客中也有過介紹:【論文筆記】命名實體識別論文https://blog.csdn.net/Kaiyuan_sjtu/article/details/89143573


關於NER的處理思路也是跟上面情感分類的大同小異,只不過NER是屬於序列標註任務,在運行腳本的時候注意使用源碼中的run_senquence_labeling.py

4、有趣的ISSUE

Github上比源碼更有價值的是對應的issue,一個好的開源項目會吸引不少人的關注,issue區裏會有不少有趣的思考,因此你們千萬不要錯過噢~下面就列幾個我以爲比較有意思的issue供你們參考。

  1. 關於batch_size

剛打開ERNIE腳本打算跑的同窗可能會發現,它的batch_size居然是8192,個人天哪(小嶽嶽臉),這不得炸!因而乎你很是機智地把batch_size改成了32,美滋滋地輸入bash script/pretrain.py,而後自信地敲下Enter鍵。嗯???報錯???

報的什麼錯你們感興趣的本身去復現吧~

對,在pretrain的時候這裏的batch_size指的是全部輸入token的總數,因此纔會那麼大~

  1. 關於Mask機制的邏輯

正如我開篇說的,ERNIE的最大創新就是它的mask機制,這一點的代碼實現也在issue區被熱烈討論

  1. 關於獲取輸入的中間向量表示

有時候咱們會須要獲取句子 Embedding 和 token Embeddings,可參照下面的方案

  1. 預測被masked的詞

將一個句子的某個詞語mask後,而後使用模型去預測這個詞語,獲得候選詞和詞語的機率

  1. ERNIE模型部署

飛槳(PaddlePaddle)模型的部署能夠在官方說明文檔中找到:https://www.paddlepaddle.org.cn/documentation/docs/zh/1.4/advanced_usage/deploy/inference/index_cn.html

 

5Some Tips

最後一部分打算說一下關於使用預訓練模型的一些小tips:

  • 學習率是第一種重要的參數,當你開始着手調參時優先從學習率開始。
  • 根據你的任務來選擇預訓練模型。每一個模型的訓練大規模語料是不同的,這就說明了有些模型天生就是更加適用於某個領域。
  • 全部的預訓練模型爲了在儘量多的下游任務上取得較好的效果,所使用的訓練語料的覆蓋範圍都是很是大的,但這也帶來了一個問題----過於general。也就是說若是你的任務所屬domain與訓練語料的相差較大,好比關於醫學材料學之類的領域,反而不容易取得好的效果。因此咱們能夠在特定領域下嘗試post-train預訓練模型
  • 目前來講,對於中文領域的NLP任務,能夠優先選擇ERNIE。聽小道消息說,ERNIE 2.0快出來了,聽說效果很猛。
  • 不要過度迷信預訓練模型!!!

 

關於ERNIE的更多信息,可點擊文末閱讀原文(連接:https://github.com/PaddlePaddle/ERNIE/tree/develop/ERNIE或查看如下連接:

https://github.com/PaddlePaddle/ERNIE/tree/develop/ERNIE

 

 

Reference:

 

 

 

 

 

原文連接地址:https://developer.baidu.com/topic/show/290242

相關文章
相關標籤/搜索