1. 程式人生 > >NLP(十九)首次使用BERT的視覺化指導

NLP(十九)首次使用BERT的視覺化指導

  本文(部分內容)翻譯自文章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會處理句子並把它提取後的資訊傳遞給下一個模型。DistillBERTBERT的變異版本,由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 。
  感謝大家閱