本文(部分內容)翻譯自文章A Visual Guide to Using BERT for the First Time,其作者為Jay Alammar,訪問網址為:http://jalammar.github.io/a-visual-guide-to-using-bert-for-the-first-time/ ,可以作為那些不熟悉BERT的讀者首次閱讀。文章中如有翻譯不當之處,還請批評指正。
本文是關於如何使用BERT的變異版本來進行句子分類的簡單教程。該例子足夠簡單,因此可以作為首次使用BERT的介紹,當然,它也包含了一些關鍵性的概念。
數據集:SST2
本文中使用的數據集為SST2,它包含了電影評論的句子,每一句帶有一個標簽,或者標注為正面情感
(取值為1),或者標注為負面情感
(取值為0)。
模型:句子情感分類
我們的目標是創建一個模型,它能夠處理一個句子(就行我們數據集中的句子那樣)並且輸出1(表明該句子具有正面情感)或者0(表明該句子具有負面情感)。我們設想它長這樣:
事實上,該模型包含兩個模型:
DistillBERT
會處理句子並把它提取后的信息傳遞給下一個模型。DistillBERT
是BERT
的變異版本,由HuggingFace
小組開發和開源。它是BERT
的更輕量、更快速的版本,同時它的表現基本與BERT
相近。- 下一個模型,從scikit learn中導入的一個基本的
邏輯回歸模型
(Logistic Regression model),它會利用DistillBERT
的處理結果,然后將句子進行分類成正面情感
或者負面情感
(分別為1或者0)。
在兩個模型之間傳遞的數據為1個768維的向量。我們可以把這個向量理解為這個句子的嵌入向量(Embedding Vector),用於分類。
模型訓練
盡管我們用了兩個模型,但是我們只會訓練邏輯回歸模型
。對於DistillBERT
,我們會使用已經預訓練好的英語模型。該模型,既不會被訓練也不會做微調(fine-tuned)
,直接進行句子分類。這是因為,我們可以從BERT
中獲得句子分類的能力。這尤其適合BERT
輸出的第一個位置(跟[CLS]標志相關)。我相信這是由於BERT
的第二個訓練模型——下一句分類(Next sentence classification)
。該模型的目標在於封裝句子級別的語料進行訓練,並輸出第一個位置。transformers
庫已經提供了DistillBERT
的操作,作為其預訓練模型版本。
教程總覽
以下是該教程的計划安排。首先我們會使用DistillBERT
來產生2000個句子的句子向量。
這一步之后我們不會接觸DistillBERT
。接下去只是Scikit Learn的操作。我們將數據集分為訓練集和測試集。
接下來我們在訓練集上使用邏輯回歸模型
進行訓練。
單次預測如何計算
在我們講解代碼和解釋如何訓練模型之前,讓我們看一下已預訓練好的模型如何進行預測。
我們嘗試着預測句子“a visually stunning rumination on love”。第一步是使用BERT tokenizer 將句子划分成tokens。然后加上句子分類的特殊tokens([CLS]在開始位置,[SEP]在句子結尾)。
第三步是通過已預訓練好的模型的嵌入表(embedding table)將每一個tokens映射成各自的id。這一步可以參考word embedding
,參考閱讀文章The Illustrated Word2vec。
我們注意到,tokenizer僅需要一行代碼就能完成以上步驟。
tokenizer.encode("a visually stunning rumination on love", add_special_tokens=True)
我們的輸入句子現在已經處理成DistilBERT
可以處理的格式了。
如果你已經讀過Illustrated BERT,那么這一步的可視化如下:
DistilBERT處理流程
DistilBERT
處理輸入向量的流程類似於BERT
。輸出是每一個token對應一個向量。每個向量由768個浮點型數字組成。
因為這是一個句子分類任務,故我們忽略其他向量而只取第一個向量(跟[CLS]相關的那個)。這個向量我們會作為邏輯回歸模型
的輸入。
從這里開始,就是邏輯回歸模型
的事兒了,它負責將輸入的向量進行分類。我們設想一個預測的流程長這樣:
代碼
文章中用到的數據集下載網址為:https://github.com/clairett/pytorch-sentiment-classification/raw/master/data/SST2/train.tsv。下載DistillBERT
模型文件,網址為:https://www.kaggle.com/abhishek/distilbertbaseuncased 。
原文中這部分的代碼講解比較多,我這邊忽略過去了,筆者想按自己的思路來處理,因此這部分內容會有調整。完整的思路如下:
下載數據集和模型文件,與代碼放在同一目錄下。建立jupyter腳本,先載入必要的模塊:
接着我們利用pandas讀取訓練集數據,並統計標簽值的頻數:
讀取DistillBERT
模型文件並創建tokenizer:
通過tokenizer完成句子切分成tokens,並映射到id:
由於每個句子的長度可能會不同,因此需要對句子進行填充(Padding),保持每個句子的輸入維度一致,句子填充的長度為該數據集中句子長度的最大值。
對句子進行填充后,然后再進行Masking。這是因為如果我們直接將padded傳入BERT
,這會造成一定的困擾。我們需要創建另一個變量,來告訴模型去mask之前的填充結果。這就是attention_mask的作用:
我們的輸入已經准備完畢,接下來我們嘗試着用DistillBERT
來獲取向量,也就是之前說的第一步。這一步的處理結果會返回last_hidden_states
,而我們的分類模型只需要獲取[CLS]
這個token對應的輸出向量。
可視化的操作說明如下圖:
這樣,我們就把之前的每一個句子映射成了1個768維的句子向量,然后就利用邏輯回歸模型
直接進行訓練就可以了。
最后,我們來看一下這個模型在測試集上的效果:
總結
本文主要介紹了如何利用DistillBERT
和已經封裝好的transformers
模塊,結合邏輯回歸模型
對英文句子進行文本二分類。后續筆者還會研究在中文上的文本分類以及如何進行微調(Fine_tuning)。
本項目的Gitlab地址為:https://gitlab.com/jclian91/sentence_classify_using_distillBERT_LR,原文章作者的Github地址為https://github.com/jalammar/jalammar.github.io/blob/master/notebooks/bert/A_Visual_Notebook_to_Using_BERT_for_the_First_Time.ipynb 。
感謝大家閱讀~