Categories
程式開發

五問BERT:深入理解NLP領域爆紅的預訓練模型


BERT是NLP領域的一個重要里程碑,它是一個非常強大的語言模型,極大地提高了解決NLP任務的能力。本文由淺入深,通過理論與案例多角度介紹了BERT的理論與使用方法。如果你是一名NLP實踐者,可以根據本文的案例指導,學習BERT的使用。

假如你一直關注深度學習相關信息的話,你一定聽說過BERT,在過去的一年裡,它一直是非常熱門的焦點話題。

在2018年底,谷歌人工智能語言的研究人員開源了一種新的自然語言處理技術(NLP),被稱為BERT(Transformers的雙向編碼器表示)。這是一項重大突破,它以其令人難以置信的性能轟動了整個深度學習社區。在這篇博文中,我們將通過回答以下5個問題來了解和學習BERT:

  1. 為什麼需要BERT?
  2. BERT背後的核心思想是什麼?
  3. BERT的工作原理是什麼?
  4. 什麼場景下使用BERT,如何進行fine-tune?
  5. 如何使用BERT? BERT文本分類實踐指南

本文將首先講解BERT的理論,接著用實踐案例來加深對BERT的理解。

1. 為什麼需要BERT?

NLP面臨的最大挑戰之一是缺乏足夠的訓練數據。總的來說,有大量的文本數據可用,但是如果我們想要創建特定於某任務的數據集,我們需要將這些數據分成許多不同的字段。即便我們這樣做了之後,我們最終只能得到幾百或幾十萬個人類標記的訓練樣本。可是,為了達到更好的效果,基於深度學習的NLP模型需要更大的數據量,只有對數億甚至十億級的帶註釋的數據進行訓練,才能達到很好的效果。

為了幫助彌補這一數據量上的差距,研究人員開發了各種技術來訓練通用語言模型,這些模型使用網絡上的大量未加註釋的文本作為數據源(這稱為預訓練)。這些通用的預訓練模型可以在更小的特定任務數據集上進行微調,例如,當處理諸如問題回答和情緒分析等問題時,與從零開始在更小的任務特定數據集上訓練相比,這種方法可以極大地提高準確性。 BERT是NLP預訓練的新技術之一,它在深度學習社區引起了轟動,因為它在各種NLP任務中呈現出的結果是最準確的,比如問答場景。

BERT另一個優勢在於它可以免費下載和使用,我們可以使用BERT模型從文本中提取高質量的語言特性數據,或者我們可以調整這些模型用於某個特定的任務場景中,如情緒分析或問題回答,然後用我們自己的數據生產最優的預測結果。

2. BERT背後的核心思想是什麼?

語言模型的真正意義是什麼?語言模型試圖解決哪些問題?從本質上講,他們的任務是根據上下文“填空”。例如下面這個例子:

“那位女士去商店買了一雙 _____ 鞋子。”

語言模型在完成這個句子時會設置20%的權重使用單詞“cart”,80%的權重可能使用單詞“pair”。

在BERT出現之前,語言模型需要通過對文本序列從左至右或者再結合從右向左的掃描方式理解文本。這種單向的方法比較適合生成句子——它可以預測下一個單詞,將它添加到序列中,然後接著預測下一個單詞,直到形成一個完整的句子。

有了BERT之後,便可以創建一個雙向訓練的語言模型(這也是它的關鍵技術創新)。與單向語言模型相比,這意味著我們現在可以對語境和語言流有更深刻的理解了。

BERT並不是按順序預測下一個單詞的,而是使用了一種稱為Masked LM (MLM)的新技術:它隨機mask句子中的單詞,然後嘗試預測它們。 mask意味著模型將從兩個方向觀察,它使用句子的全部上下文,包括左邊和右邊的環境,來預測被mask的詞。與之前的語言模型不同,它會同時考慮前一個和下一個標記。現有的基於LSTM的從左到右和從右到左的組合模型缺少這個“相同時間的部分”。 (更準確地說,BERT是沒有方向性的。)

但為什麼這種無方向性的方法如此強大呢?

預訓練的語言模型可以是上下文無關的,也可以是基於上下文的。基於上下文的表示可以是單向的或雙向的。像word2vec這樣的上下文無關模型為詞彙表中的每個單詞生成單個單詞embedding 表示(數字向量)。例如,單詞“bank”在“bank account”和“bank of the river”中有相同的上下文無關表示。但在句子中,基於上下文的模型就會生成基於句子中其他單詞的表示形式。例如,在“I accessed the bank account,”這句話中,單向上下文模型將基於 “I accessed the“來表示“bank”,這時就不會考慮到”account” 了。然而,BERT用它的前一個和下一個上下文來表示“bank”——“ I accessed the … account”——從深度神經網絡的最底部開始,使其成為深度雙向的。

五問BERT:深入理解NLP領域爆紅的預訓練模型 1

將BERT的神經網絡結構與之前最先進的上下文預訓練方法進行比較。箭頭表示從一個層到下一個層的信息流。頂部的綠色方框表示每個輸入單詞的最終上下文表示。

BERT基於Transformer模型架構,而不是LSTMs。本文之後會介紹BERT的模型細節,但總的來說:

Transformer工作時力求執行一個少的、恆定數量的步驟。在每個步驟中,它應用一個標註機制來理解句子中所有單詞之間的關係,而不管它們的位置。例如,對於句子“ I arrived at the bank after crossing the river”,需要確定“bank”這個詞是指一條河的岸邊,而不是一個金融機構,Transformer可以很快根據“river”這個詞進行標註,只用一步就實現了目的。

以上我們已經介紹了BERT的關鍵理念,下面我們深入了解一下細節。

3.BERT的工作原理是什麼?

BERT依附於“Transformer”(一種標註機制,用來學習文本中單詞之間的上下文關係)。一個基本的Transformer包括一個編碼器,用來讀取文本輸入,一個解碼器,用來產生關於任務的預測。由於BERT的目標是生成語言表示模型,所以它只需要編碼器部分。 BERT的編碼器的輸入是一個tokens序列,它首先被轉換成向量,然後在神經網絡中進行處理。但是在開始處理之前,BERT需要對輸入進行處理並添加一些額外的元數據:

  1. Token embeddings:在第一個句子的開頭將[CLS]token添加到輸入單詞token中,並在每個句子的末尾插入[SEP]token。
  2. Segment embeddings:將表示句子A或句子B的標記添加到每個token中。這可以在不同的句子間區分編碼器。
  3. Positional embeddings:將positional embedding添加到每個token中,以標示其在句子中的位置。

五問BERT:深入理解NLP領域爆紅的預訓練模型 2

BERT的輸入示意圖:input embeddings是Token embeddings、Segment embeddings和Positional embeddings的總和。

實際上,Transformer堆疊了一個將序列映射到序列的層,因此輸出也是一個向量序列,在相同索引處的輸入和輸出標記之間具有1:1的對應關係。正如我們之前說過的,BERT不會試圖預測句子中的下一個單詞。它的訓練主要採用以下兩種策略:

1. Masked LM (MLM)

其指導思想是“簡單”:使用( MASK) token隨機mask 15%的單詞輸入,之後運行基於編碼器的BERT標註,然後基於所提供的上下文中的其他non-masked詞序列預測被mask的單詞含義。然而,這種原始的mask方法有一個問題——模型只在[ MASK]token出現在輸入中時才嘗試預測,而我們希望模型不管輸入中出現了什麼tokens都能夠嘗試預測正確的tokens 。為了解決這個問題,我們選擇mask15%的tokens:

  • 實際上80%的tokens被替換為token [MASK].。
  • 10%的token被替換為隨機token。
  • 10%的token保持不變。

訓練BERT損失函數時,只考慮mask token的預測,而忽略非mask token的預測。這會導致模型的收斂速度比從左到右或從右到左的模型慢得多。

2. 下一句話預測(NSP)

為了理解兩個句子之間的關係,BERT訓練過程中還使用了下一句預測。具有這種理解能力的預訓練模型可以處理問答相關的任務。在訓練過程中,該模型得到輸入的句子對,並學習預測第二個句子是否是原文本中的下一個句子。

正如我們前面看到的,BERT用一個特殊的(SEP)token來分隔句子。在訓練過程中,模型一次輸入兩個句子:

  • 有50%的可能性,第二句話在第一句之後。
  • 有50%的可能性,它是一個來自完整語料庫的隨機句子。

之後BERT就要預測第二個句子是否是隨機的,並假設這個隨機的句子與第一個句子是斷開的:

五問BERT:深入理解NLP領域爆紅的預訓練模型 3

預測第二句與第一句是否是連接的,基本上完整的輸入序列經過 Transformer模型,再用一個簡單的分類器層將(CLS)token的輸出轉換為2×1的向量,並使用softmax分配IsNext-Label。

該模型結合了 Masked LM神經網絡和下一句預測進行訓練。這是為了最小化兩種策略的組合損失函數——所謂的“合作共贏”。

模型架構

根據模型架構的規模,BERT有四種預訓練的版本:

BERT-Base: 12-layer, 768-hidden-nodes, 12-attention-heads, 110M parameters

BERT-Large: 24-layer, 1024-hidden-nodes, 16-attention-heads, 340M parameters

BERT-Base在4個TPUs上訓練了4天,BERT-Large在16個TPUs上訓練了4天!

有關超參數的詳細信息以及關於體系架構和結果分解的更多信息,建議你閱讀BERT論文原文。

4. 什麼場景下使用BERT,如何進行fine-tune?

BERT在自然語言推理、情感分析、問題問答、意譯檢測和語言可接受性等一般語言理解的各種任務場景中都表現出色。

那麼,針對特定的任務場景,我們如何進行fine-tune呢? BERT可以用於各種各樣的語言任務中。如果我們想要基於我們自己的數據集對原始模型進行微調,只需在核心模型上添加一個獨立層即可。

例如,假設我們正在創建一個問答應用程序。本質上,問題問答只是一個預測任務——在接收一個問題作為輸入時,應用程序的目標是從一些語料庫中識別正確的答案。因此,給定一個問題和一個上下文段落,該模型預測該段落中最有可能回答該問題的開始和結束標記。這意味著我們可以使用BERT模型通過學習兩個額外的向量來訓練我們的應用程序,這兩個向量分別表示答案的開頭和結尾。

五問BERT:深入理解NLP領域爆紅的預訓練模型 4

就像句子對任務一樣,問題變成了輸入序列中的第一個句子,段落變成了第二個句子。不過,在這裡fine-tune過程中加入了兩個新參數:開始向量和結束向量。

在fine-tune訓練中,超參數與BERT訓練保持一致;本文對需要調整的超參數給出了具體的指導。

注意,如果我們想進行fine-tune,我們需要轉換數據輸入的格式,以滿足預訓練核心BERT模型的特殊格式要求。例如:我們需要添加特殊token來標記開始((CLS))、分離/結束的句子([ SEP])以及segment IDs,以達到區分不同句子的目的,最終才能將數據轉換成BERT使用的特性。

5. 如何使用BERT? BERT文本分類實踐指南

從上文中我們已經了解了BERT的基本概念,下面我們就要來看一個實際的例子了。在本指南中,我將使用Yelp用戶評論數據集,你可以從這裡下載該數據集。這是一個簡單的二進製文本分類任務——目標是將短文本分為好的和差的評論。下面將介紹完整的工作流程:

1. 安裝

在python tensorflow環境中進行設置會比較簡單:

a. 將BERT Github庫克隆到你自己的電腦上。在你的終端上,輸入

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

b. 從官方的BERT Github頁面下載預先訓練好的BERT模型文件。裡麵包括權值、超參數和其他必要的文件,這些文件中包含了BERT在預訓練中學到的信息。將其保存到你git clone存儲庫並解壓到目錄中。下面是英文版的鏈接:

BERT-Base, Uncased: 12-layers, 768-hidden, 12-attention-heads, 110M parameters

BERT-Large, Uncased: 24-layers, 1024-hidden, 16-attention-heads, 340M parameters

BERT-Base, Cased: 12-layers, 768-hidden, 12-attention-heads , 110M parameters

BERT-Large, Cased: 24-layers, 1024-hidden, 16-attention-heads, 340M parameters

我們需要根據自身情況選擇BERT預訓練的版本。例如,如果我們用不了谷歌TPU,我們最好選擇使用基本模型。至於“ cased”和“ uncased”的選擇取決於字母大小寫是或否會對我們的任務產生影響。本教程下載使用的是BERT-Base-Cased模型。

2. 準備數據

為了使用BERT,我們需要將數據轉換成BERT使用的格式——我們有csv格式的評論文件,BERT對數據的要求比較特殊,它要求數據按如下所示的特定格式保存在tsv文件中(四列,沒有標題行):

  • 第0列:行ID
  • 第1列:行標籤(需要是int類型,如0、1、2、3等)
  • 第2列:這一列上,所有行的字母都相同——這是我們需要包含的比較多餘的一列,不過BERT需要用到它。
  • 第3列:我們要分類的文本示例

在你克隆BERT的目錄中創建一個文件夾,用於在其中添加三個獨立的文件,分別是train.tsv、dev.tsv、test.tsv (tsv為製表符分隔值)。在train.tsv和dev.tsv中會包含所有4列。而在test.tsv中我們只需要保留2列,即用於標識行的id和要分類的文本。

以下代碼演示了我們如何讀取Yelp的評論,並對BERT進行恰當的設置,代碼詳見:http://gist.github.com/samk3211/1d233b29ce5acc93f4a3e8c13db8ccd3

3.使用預先訓練好的BERT模型進行訓練

在進行下一步之前,我們先再確認以下是否準備妥當:

  • 所有的.tsv文件都應該放在BERT目錄下的data文件夾中。
  • 創建一個名為“bert_output”的文件夾,其中將保存調優後的模型。
  • 在BERT目錄下存在預訓練的BERT模型。
  • 命令中的路徑是相對路徑“./”

確認完後,就可以進入到你克隆BERT的目錄,並輸入以下命令:

python run_classifier.py 
--task_name=cola 
--do_train=true 
--do_eval=true 
--do_predict=true 
--data_dir=./data/ 
--vocab_file=./cased_L-12_H-768_A-12/vocab.txt 
--bert_config_file=./cased_L-12_H-768_A-12/bert_config.json 
--init_checkpoint=./cased_L-12_H-768_A-12/bert_model.ckpt 
--max_seq_length=128 
--train_batch_size=32 
--learning_rate=2e-5 
--num_train_epochs=3.0 
--output_dir=./bert_output/ 
--do_lower_case=False

如果我們觀察終端上的輸出,可以看到帶有額外標記的輸入文本的轉換,這個之前我們在討論BERT期望的各種輸入標記時已經有所了解:

五問BERT:深入理解NLP領域爆紅的預訓練模型 5

用BERT訓練可能會出現內存溢出的錯誤。這表明你需要更強大的硬件能力——GPU、更多的RAM甚至TPU。不過,我們也可以嘗試一些變通方法,然後再考慮提升硬件。例如,我們可以嘗試減少training_batch_size;雖然這樣做會使訓練速度變慢,但天下沒有免費的午餐,還是可以忍受的。

訓練可能需要很長時間。所以你運行完命令後就可以先將其放在一邊了,除非你的機器性能非常強勁。當然,在訓練過程中你也不太能用你的電腦做其它的事情了——至少我在訓練時就不能很好的用電腦工作。

我們可以在終端上看到進度日誌。一旦訓練完成,我們就會在bert_output目錄中得到一個關於模型效果的報告;test_results.tsv是根據對測試數據集的預測在輸出目錄中生成的,其中包含類標籤的預測概率值。

4. 對新數據進行預測

如果我們想對新的測試數據test.tsv進行預測,在模型訓練完成後,我們就可以進入bert_output目錄,並關注有最高數字值的model.ckpt文件。這些檢查點文件包含訓練模型的權重。一旦我們有了最高的檢查點編號,我們可以再次運行run_classifier.py,但這次init_checkpoint應該設置為最高的模型檢查點,如下所示:

export TRAINED_MODEL_CKPT=./bert_output/model.ckpt-[highest checkpoint number]

python run_classifier.py 
--task_name=cola 
--do_predict=true 
--data_dir=./data 
--vocab_file=./cased_L-12_H-768_A-12/vocab.txt 
--bert_config_file=/cased_L-12_H-768_A-12/bert_config.json 
--init_checkpoint=$TRAINED_MODEL_CKPT
--max_seq_length=128 
--output_dir=./bert_output

這將生成一個名為test_results.tsv的文件,其列的數目等於類標籤的數目。

注意,在訓練階段我們已經設置了-do_predict =true。實際上這個參數設置可以省略,測試結果可以使用上面的命令單獨生成。 )

5. 知識拓展

上面我們使用的是開箱即用的解決方案進行訓練。但是,我們也可以通過創建一個單獨的新層來進行自定義fine-tune,該層經過訓練可以使BERT適應我們的情緒分類任務(或任何其他任務)。不過這篇博文已經很長了,所以我不打算在此文中再擴展介紹自定義層的內容了,不過我可以提供兩個參考:

  • 這裡有一個用PyTorch實現的教程,也是基於相同的Yelp用戶數據集。
  • 谷歌的研究人員創造了一個很棒的colab筆記本,它詳細地展示瞭如何預測IMDB的電影評論是積極的還是消極的的過程,這個案例就是在Tensorflow中預先訓練的BERT模型的基礎上增加了一個新層。

總結

BERT是一個非常強大的語言模型,它是NLP領域的一個重要里程碑——它極大地提高了我們在NLP中進行遷移學習的能力;它可以為各種各樣的NLP任務提供解決方案。在這篇文章中,我嘗試給大家寫了一個完整的BERT入門指南,希望大家能從中學到一些NLP的妙處。

如果你想了解更多關於BERT的信息,推薦你參考原始論文和相關的開源Github repo。當然在PyTorch中也有一個BERT的實現可供你學習。

原文鏈接:

BERT Explained: A Complete Guide with Theory and Tutorial