BERT模型


一、BERT介紹

論文:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding 

簡介:BERT是基於Transformer的深度雙向語言表征模型,基本結構如圖所示,本質上是利用Transformer結構構造了一個多層雙向的Encoder網絡。Transformer是Google在2017年提出的基於自注意力機制(Self-attention)的深層模型,在包括機器翻譯在內的多項NLP任務上效果顯著,超過RNN且訓練速度更快。

  從上圖可見,Bert其實和ELMO及GPT存在千絲萬縷的關系,比如如果我們把GPT預訓練階段換成雙向語言模型,那么就得到了Bert;而如果我們把ELMO的特征抽取器換成Transformer,那么我們也會得到Bert。與GPT不同之處:在預訓練階段采用了類似ELMO的雙向語言模型;另外一點是語言模型的數據規模要比GPT大。

  Bert最關鍵兩點:

  1. 特征抽取器采用Transformer;
  2. 預訓練的時候采用雙向語言模型。

二、BERT模型結構

  上圖中$E_i$是指的單個字或詞, $T_i$指的是最終計算得出的隱藏層, Transformer中的注意力矩陣和注意力加權, 經過這樣的操作之后, 序列里面的每一個字, 都含有這個字前面的信息和后面的信息, 這就是雙向的理解, 在這里, 一句話中每一個字, 經過注意力機制和加權之后, 當前這個字等於用這句話中其他所有字重新表達了一遍, 每個字含有了這句話中所有成分的信息.

  根據參數設置的不同,Google 論文中提出了Base和Large兩種BERT模型。

三、預訓練

  BERT預訓練過程包含兩個不同的預訓練任務,分別是Masked Language Model和Next Sentence Prediction任務。 

1.Masked Language Model(MLM)

  隨機把一些單詞變為[Mask],然后預測這些被遮蓋的詞來訓練雙向語言模型,並且使每個詞的表征參考上下文信息。假設輸入里面的第二個詞匯是被蓋住的,把其對應的embedding輸入到一個多分類模型中,來預測被蓋住的單詞。之后做Loss的時候只計算被遮蓋部分的Loss。

實際操作方式如下:

【1】隨機把一句話中15%的token替換成以下內容:

  1. 這些token中有80%的幾率被替換成[mask];
  2. 有10%的幾率被替換成任意一個其他的token;
  3. 有10%的幾率原封不動 

【2】之后讓模型預測和還原被遮蓋掉或替換掉的部分,模型最終輸出的隱藏層的計算結果的難度是:

$X_{hidden}$: [batch size, seq len, embedding dim]
我們初始化一個映射層的權重$W_{vocab}$:
$W_{vocab}$: [embedding dim, vocab size] 
我們用$W_{vocab}$完成隱藏維度到字向量數量的映射, 只要求$X_{hidden}$和$W_{vocab}$的矩陣乘(點積):
$X_{hidden}W_{vocab}$: [batch size, seq len, vocab size] 
之后把上面的計算結果在vocab size(最后一個)維度做$softmax$歸一化, 是每個字對應的vocab size的和為1, 我們就可以通過vocab size里概率最大的字來得到模型的預測結果, 就可以和我們准備好的$Label$做損失($Loss$)並反傳梯度了. 注意做損失的時候, 只計算在第1步里當句中隨機遮蓋或替換的部分, 其余部分不做損失, 對於其他部分, 模型輸出什么東西, 我們不在意.

這樣做會產生兩個缺點

  1. 會造成預訓練和微調時的不一致,因為在微調時[MASK]總是不可見的;
  2. 由於每個Batch中只有15%的詞會被預測,因此模型的收斂速度比起單向的語言模型會慢,訓練花費的時間會更長。

解決方法:

  1. 對於第一個缺點的解決辦法是,把80%需要被替換成[MASK]的詞進行替換,10%的隨機替換為其他詞,10%保留原詞。由於Transformer Encoder並不知道哪個詞需要被預測,哪個詞是被隨機替換的,這樣就強迫每個詞的表達需要參照上下文信息。
  2. 對於第二個缺點目前沒有有效的解決辦法,但是從提升收益的角度來看,付出的代價是值得的。

2.Next Sentence Prediction(NSP)

首先我們拿到屬於上下文的一對句子, 也就是兩個句子, 之后我們要在這兩段連續的句子里面加一些特殊$token$: $[cls]$上一句話,$[sep]$下一句話.$[sep]$ 
  也就是在句子開頭加一個$[cls]$, 在兩句話之中和句末加$[sep]$, 具體地就像下圖一樣:

  我們看到上圖中兩句話是[cls] my dog is cute [sep] he likes playing [sep], [cls]我的狗很可愛[sep]他喜歡玩耍[sep], 除此之外, 我們還要准備同樣格式的兩句話, 但他們不屬於上下文關系的情況; [cls]我的狗很可愛[sep]企鵝不擅長飛行[sep], 可見這屬於上下句不屬於上下文關系的情況;在實際的訓練中, 我們讓上面兩種情況出現的比例為1:1, 也就是一半的時間輸出的文本屬於上下文關系, 一半時間不是.

  我們進行完上述步驟之后, 還要隨機初始化一個可訓練的 segment embeddings , 見上圖中, 作用就是用 embeddings 的信息讓模型分開上下句, 我們一把給上句全 0 的 tokentoken , 下句啊全 1 的 token , 讓模型得以判斷上下句的起止位置, 例如:

[cls] 我的狗很可愛 [sep] 企鵝不擅長飛行 [sep]
  0   0 0 0 0 0 0  0   1 1 1 1 1 1 1   1

上面 0 和 1 就是 segment embeddings .

  注意力機制就是, 讓每句話中的每一個字對應的那一條向量里, 都融入這句話所有字的信息, 那么我們在最終隱藏層的計算結果里, 只要取出$[cls]token$所對應的一條向量, 里面就含有整個句子的信息, 因為我們期望這個句子里面所有信息都會往$[cls]token$所對應的一條向量里匯總: 
模型最終輸出的隱藏層的計算結果的維度是: 
$X_{hidden}$: [batch_size, seq_len, embedding_dim]$
我們要取出$[cls]token$所對應的一條向量, $[cls]$對應着seq len維度的第$0$條: 

$cls\_vector = X_{hidden}[:, 0, :]$,
$cls\_vector \in \mathbb{R}^{batch\_size, embedding\_dim} $

之后我們再初始化一個權重, 完成從embedding dim維度到1的映射, 也就是邏輯回歸, 之后用$sigmoid$函數激活, 就得到了而分類問題的推斷. 
我們用$\hat{y}$來表示模型的輸出的推斷, 他的值介於$(0, 1)$之間: 
$\hat{y} = sigmoid(Linear(cls vector)) \quad \hat{y} \in (0, 1)$

3.BERT訓練參數和技巧

  BERT論文中, 推薦的模型參數為: 基准模型transformer_block=12, embedding_dimension=768,  num_heads=12, Total Param eters=110M), 可見其中共有1.1億參數, 除此之外, 還有比基准模型還大的高性能模型, 參數量為3億, 要想訓練並使用這么大參數的模型, 需要充裕的計算資源。

訓練技巧:

  1. 因為我們是按單個字為單位訓練BERT, 所以在Masked LM里面, 把句子中的英文單詞分出來, 將英文單詞所在的區域一起遮蓋掉, 讓模型預測這個部分;
  2. 很多句子里含有數字, 顯然在Masked LM中, 讓模型准確地預測數據是不現實的, 所以我們把原文中的數字(包括整數和小數)都替換成一個特殊token, #NUM#, 這樣模型只要預測出這個地方應該是某些數字就可以來。

四、BERT完成下游任務

NLP四個任務:序列標注、分類任務、句子關系推斷、生成式任務

1.句子關系推斷

  對於句子關系類任務,和GPT類似,加上一個起始和終結符號,句子之間加個分隔符即可。對於輸出來說,把第一個起始符號對應的Transformer最后一層位置上面串接一個softmax分類層即可。

舉例:給定一個前提/假設,得到推論是否正確:

  為了訓練一個理解句子間關系的模型,引入一個下一句預測任務。這一任務的訓練語料可以從語料庫中抽取句子對包括兩個句子A和B來進行生成,其中50%的概率B是A的下一個句子,50%的概率B是語料中的一個隨機句子。NSP任務預測B是否是A的下一句。NSP的目的是獲取句子間的信息,這點是語言模型無法直接捕捉的。

  Google的論文結果表明,這個簡單的任務對問答和自然語言推理任務十分有益,但是后續一些新的研究[15]發現,去掉NSP任務之后模型效果沒有下降甚至還有提升。我們在預訓練過程中也發現NSP任務的准確率經過1-2個Epoch訓練后就能達到98%-99%,去掉NSP任務之后對模型效果並不會有太大的影響。

2.分類任務

  如果是分類任務,在句子前面加一個標志,將其經過Bert得到的embedding輸出到二分類模型中,得到分類結果。二分類模型從頭開始學,而Bert在預訓練的基礎上進行微調(fine-tuning)。

文中還有很多其他的應用,如單詞分類:

3.序列標注

  輸入部分和單句分類是一樣的,只需要輸出部分Transformer最后一層每個單詞對應位置都進行分類即可。

4.生成式任務

  對於機器翻譯或者文本摘要,聊天機器人這種生成式任務,同樣可以稍作改造即可引入Bert的預訓練成果。只需要附着在S2S結構上,encoder部分是個深度Transformer結構,decoder部分也是個深度Transformer結構。根據任務選擇不同的預訓練數據初始化encoder和decoder即可。這是相當直觀的一種改造方法。當然,也可以更簡單一點,比如直接在單個Transformer結構上加裝隱層產生輸出也是可以的。

  舉例:抽取式QA,抽取式的意思是輸入一個原文和問題,輸出兩個整數start和end,代表答案在原文中的起始位置和結束位置,兩個位置中間的結果就是答案。

  解決QA問題:把問題 - 分隔符 - 原文輸入到BERT中,每一個單詞輸出一個黃顏色的embedding,這里還需要學習兩個(一個橙色一個藍色)的向量,這兩個向量分別與原文中每個單詞對應的embedding進行點乘,經過softmax之后得到輸出最高的位置。正常情況下start <= end,但如果start > end的話,說明是矛盾的case,此題無解。

五、BERT總結

1.優點

  1. 考慮雙向信息(LM只考慮單向)
  2. 長距離依賴(long-term dependence)

2.缺點

  1. 測試數據沒有[mask],discrepancy,削弱了一定的泛化能力。
  2. 缺乏生成能力(LM具有生成能力)
  3. 針對每一個mask預測時,沒有考慮mask間的相關性(例:w1 w2 [mask] w4 w5 [mask] w7,第一個mask為w3,第二個mask為w6,理想情況是需要考慮w3和w6間相關性的,bert里面沒有考慮這點,二者是獨立的)

              類似於朴素貝葉斯,沒有考慮特征間的相關性。

 

 

 

 

六、應用

1.獲得句向量

 使用BERT模型生成句子序列向量 - 不著人間風雨門 - 博客園

 

 

 

參考文獻:

【1】美團BERT的探索和實踐

【2】【NLP】李宏毅-ELMO、BERT、GPT視頻筆記

【3】aespresso/a_journey_into_math_of_ml: 漢語自然語言處理視頻教程-開源學習資料

【4】https://www.bilibili.com/video/av70512497?t=1195&p=1&spm_id_from=333.788.b_62696c692d6865616465722d6d.18

【5】【BERT】如何訓練並使用Bert【持續更新】

【6】Dissecting BERT Part 1: The Encoder - Dissecting BERT - Medium

【7】使用BERT模型生成句子序列向量 - 不著人間風雨門 - 博客園

【8】NLP:自回歸(Autoregressive LM)與自編碼語言模型(Autoencoder LM)_人工智能_小馬哥的博客-CSDN博客

【9】台大《應用深度學習》國語課程(2020) by 陳蘊儂


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM