當前位置:
首頁 > 知識 > 小數據福音!BERT在極小數據下帶來顯著提升的開源實現

小數據福音!BERT在極小數據下帶來顯著提升的開源實現

機器之心專欄

作者:金立達

笨鳥社交 AI Lab

標註數據,可以說是 AI 模型訓練里最艱巨的一項工作了。自然語言處理的數據標註更是需要投入大量人力。相對計算機視覺的圖像標註,文本的標註通常沒有準確的標準答案,對句子理解也是因人而異,讓這項工作更是難上加難。

但是,谷歌最近發布的 BERT [1] 大大地解決了這個問題!根據我們的實驗,BERT 在文本多分類的任務中,能在極小的數據下帶來顯著的分類準確率提升。並且,實驗主要對比的是僅僅 5 個月前發布的 State-of-the-Art 語言模型遷移學習模型 – ULMFiT [2],結果有著明顯的提升。我們先看結果:

圖1. 實驗結果對比,BERT在極少的數據集上表現非常出色

從上圖我們可以看出,在不同的數據集中,BERT 都有非常出色的表現。我們用的實驗數據分為 1000、 6700 和 12000 條,並且各自包含了測試數據,訓練測試分割為 80%-20%。數據集從多個網頁來源獲得,並經過了一系列的分類映射。但 Noisy 數據集帶有較為顯著的噪音,抽樣統計顯示噪音比例在 20% 左右。

實驗對比了幾個模型,從最基礎的卷積網路作為 Baseline,到卷積網路加上傳統的詞向量 Glove embedding, 然後是 ULMFiT 和 BERT。為了防止過擬合,CNN 與 CNN+Glove 模型訓練時加入了 Early stopping。

值得注意的是,這裡用的 BERT 模型均為基礎版本,「BERT-Base, Uncased」,12 層,110M 參數,對比的是 ULMFiT 調整過的最優化參數。可見 BERT 在此任務中的強大。

然而,在 12000 條樣本的數據集上,BERT 的結果相對 6700 條並沒有顯著的提升。數據分類不平衡可能是導致此結果的一大因素。

BERT 開源的多個版本的模型:

圖2. 開源的多個版本的BERT模型

接下來,我們直奔主題 – 如何在自己的機器上實現 BERT 的文本 25 分類任務。教程分為以下幾部分:

運行環境

硬體配置

下載模型

輸入數據準備

實現細節


運行環境

TensorFlow 版本為 Windows 1.10.0 GPU,具體安裝教程可以參考此鏈接:

https://www.tensorflow.org/install/pip?lang=python3

Anaconda 版本為 1.9.2。


硬體配置

實驗用的機器顯卡為 NVIDIA GeoForce GTX 1080 Ti,BERT base 模型佔用顯存約為 9.5G。


下載模型

所有的運行環境設置好後,在這裡可以下載到我們實驗用的 BERT base:

https://storage.googleapis.com/bert_models/2018_10_18/uncased_L-12_H-768_A-12.zip

下載完後,放在 BERT_BASE_DIR 中。

輸入數據準備

我們需要將文本數據分為三部分:

Train: train.tsv

Evaluate: dev.tsv

Test: test.tsv

下面可以看到每個文件的格式,非常簡單,一列為需要做分類的文本數據,另一列則是對應的 Label。

圖3. 輸入文本格式樣板

並將這三個文件放入 DATA_DIR 中。


實現細節

首先我們 Clone 官方的 BERT Github repo:

https://github.com/google-research/bert

由於我們要做的是文本多分類任務,可以在 run_classifier.py 基礎上面做調整。

這裡簡單介紹一下這個腳本本來的任務,也就是 BERT 示範的其中一個任務。這個例子是在 Microsoft Research Paraphrase Corpus (MRPC) corpus 數據集上面做微調,數據集僅包含 3600 個樣本,在 GPU 上面幾分鐘就可完成微調。

此數據集可以用以下腳本下載:

https://gist.github.com/W4ngatang/60c2bdb54d156a41194446737ce03e2e

注意運行的時候要用 --tasks all 參數來下載。

圖4. 運行腳本下載MRPC數據集

可以打開看一下輸入數據的結構,都是以 tsv 的形式保存:

圖5. MRPC數據集輸入數據樣本

圖6. MRPC數據集結構樣本

這裡 MRPC 的任務是 Paraphrase Identification,輸入為兩個句子,然後判斷二者是否表示相同的意思,輸出為二分類:是和不是。我們的分類任務只需要一個輸入,而不是一對句子,這個在讀取的過程中可以自動識別,並調整相應的 Sentence Embedding 如下圖所示:

圖7. BERT Sentence Embedding自動調整過程

run_classifier.py 的腳本中,由於輸入格式和之前有少許不同,我們需要更改 _create_examples 函數裡面的讀取順序,原本的讀取位置為:

圖8. MRPC數據集輸入文本讀取方式

我們需要讓 text_a 讀取被分類的文本,而 label 讀取我們的標註:

圖9. 在文本多分類的任務中,讀取輸入的方式

同時由於沒有 text_b,我們需要在後面製作 example 的時候將他賦值為 None:

圖10. 由於沒有Sentence Pair輸入,在這裡需要將text_b定義為None

接下來,相對於原本的二分類,我們需要針對多分類做出一些調整。代碼中原本將標籤列表手動設置為 0 和 1:

圖11. 原本直接將標註列表定義為0和1

這裡我們加入一個新的輸入,然後將輸出調整如下:

圖12. 調整get_labels的輸入和輸出

這裡 labels 輸入為新添加的所有訓練樣本的 Label,然後通過 set() 返回所有 25 個標籤的列表。調整之後,代碼可以自動根據分類數量定義標籤列表,可以適配多種多分類任務。

同時,在 _create_examples 中,我們增加兩個返回值,labels 和 labels_test:

圖13. _create_examples函數增加兩個返回值,labels和label_test

labels 返回的是所有訓練樣本的 label,用來輸入到之前提到的 get_labels()。Labels 的定義如下圖所示:

圖14. 新添加的變數labels

接下來我們需要調整 main() function 裡面的一些順序,因為現在的 get_labels() 需要額外的輸入(讀取的完整 label list),我們需要把讀取訓練集的步驟放到前面。原來的順序:

1. 獲取 label_list;

圖15. 第一步

2. 如果在訓練模式,再讀取訓練集。

圖16. 第二步

現在需要調整為:

1. 無論什麼模式都讀取訓練集,因為需要用到訓練標籤,注意新添加的輸出變數 train_labels;

圖17. 第一步

2. 然後再獲取 label_list,用前面的 train_labels。

圖18. 第二步

最後,我們在開頭設置好參數,可以直接輸入默認值來運行。下面拿 DATA_DIR 來舉例:

圖19. 原始參數

調整後的輸入參數:

圖20. 調整後的參數

1000 條樣本數據 10 分類,BERT 運行結果如下:

圖21. 1000條樣本數據10分類BERT結果


總結

本文介紹了如何實現 BERT 的文本多分類任務,並對比了 Baseline 以及不久前的 State-of-the-Art 模型 ULMFiT。實驗結果可以看出 BERT 在此任務中,可以輕鬆打敗先前的 SOTA。

這裡附上本教程的開源代碼:

https://github.com/Socialbird-AILab/BERT-Classification-Tutorial

我們依然會在 BERT 的基礎上不斷嘗試,繼續努力研究,也歡迎大家積極交流。


參考文獻

[1] Devlin, Jacob and Chang, Ming-Wei and Lee, Kenton and Toutanova, Kristina. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. arXiv preprint arXiv:1810.04805.

[2] Jeremy Howard and Sebastian Ruder. 2018. Universal language model fine-tuning for text classification. In ACL. Association for Computational Linguistics.

本文為機器之心專欄,轉載請聯繫原公眾號獲得授權。

------------------------------------------------

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 機器之心 的精彩文章:

別再使用pip安裝TensorFlow了!用conda吧~
Recurrent AI:呼叫系統的「變廢為寶」

TAG:機器之心 |