論文解讀:Bert原理深入淺出
Bert 自 Google 于 2018 年發(fā)表至今,一直給人們帶來驚喜,期間也陸陸續(xù)續(xù)因為Bert出現(xiàn)的原因多了不少新的崗位,甚至公司 JD 上都明確表明必須懂 Bert。
它在 11 項自然語言處理任務中均表現(xiàn)出驚人的成績:包括將 GLUE 基準推至 80.4%(絕對改進率7.6%),MultiNLI 精度達到 86.7%(絕對改進 5.6%)和 SQuAD v1.1 問題回答測試 F1 到 93.2。
谷歌團隊的 Thang Luong 直接定義:BERT 模型開啟了 NLP 的新時代!
Bert 能有這么好的效果,深入其原理本身,又究竟好在哪里?
Bert是什么?
BERT,全稱是 Bidirectional Encoder Representation from Transformers,基于語義理解的深度雙向預訓練Transformer。
要理解 Bert,5 個關鍵詞幫你理解其思想,分別是 Pre-training、Deep、Bidirectional、Transformer、Language Understanding。
Deep
Bert 與 Transformer 不同,Bert 的神經(jīng)網(wǎng)絡層更深,意味著它能更準確表達語義的理解,提取更多特征。
Bidirectional
BERT 被設計成一個深度雙向模型,使得神經(jīng)網(wǎng)絡更有效地從第一層本身一直到最后一層捕獲來自目標詞的左右上下文的信息。
傳統(tǒng)上,我們要么訓練語言模型預測句子中的下一個單詞( GPT 中使用的從右到左的上下文),要么訓練語言模型預測從左到右的上下文。這使得我們的模型容易由于信息丟失而產生錯誤。
Transformer
Bert 是基于 Tranformer 的深度雙向語言表征模型,也就是利用 Transformer 結構構造了一個多層雙向的Encoder 網(wǎng)絡。它的特點之一就是所有層都聯(lián)合上下文語境進行預訓練。
Bert 的目標是生成預訓練語言模型,所以只需要 Encoder 機制。Transformer 的 Encoder 是一次性讀取整個文本序列,而不是從左到右或者從右到左按順序讀取。
Pre-training
pre-training 的意思是,作者認為,確實存在通用的語言模型,先用大量數(shù)據(jù)預訓練一個通用模型,然后再微調模型,使其適用于下游任務。為了區(qū)別于針對語言生成的 Language Model,作者給通用的語言模型,取了一個名字,叫語言表征模型 Language Representation Model。
深度學習就是表征學習,大多只在預訓練表征微調的基礎上加一個線性分類器作為輸出就可以完成下游任務。
Language Understanding
Bert 是一個語言表征模型,能實現(xiàn)語言表征目標訓練,通過深度雙向 Transformer 模型達到語義理解的目的。
整合以上特點,我們就可以很直觀的理解 Bert,Bert 是一個用 Transformer 作為特征抽取器的深度雙向預訓練語言理解模型。Bert 就是一個預訓練模型,利用雙向 Transformer,通過大量數(shù)據(jù)訓練一個語言表征模型,這是一個通用模型,通過對其微調來適用下游任務,包括分類,回歸,機器翻譯,問答系統(tǒng)等等任務。
深入理解Bert工作原理
Bert 的模型結構如圖左邊第一個,Bert 采用了 Transformer Encoder,也就是每時每刻的 Attention 計算都能夠得到全部時刻的輸入。
OpenAI GPT 采用 Transformer 的 Decoder,每個時刻的 Attention 計算只能依賴于該時刻前的所有時刻的輸入,因為 OpenAI GPT 是單向語言模型。
ELMO 則采用的是 LSTM,這個模型雖然可以學習到前后語義,但是輸出依賴于前面的輸入,決定了 EMLO 的網(wǎng)絡層數(shù)不會太多,會造成大量耗時,這就決定了 ELMO 提取的特征有限。
Bert的輸入有什么不同
Bert 的輸入相較其它模型,采用了三個 Embedding 相加的方式,通過加入 Token Embeddings,Segment Embeddings,Position Embeddings 三個向量,以此達到預訓練和預測下一句的目的。
如上圖,Bert 的輸入 Input 是兩個句子:"my dog is cute","he likes playing"。首先會在第一句開頭加上特殊Token [CLS] 用于標記句子開始,用 [SEP] 標記句子結束。
然后對每個 Token 進行 3 個 Embedding,詞的 Embedding (Token Embeddings),位置 Embedding (Position Embeddings),句子 Embedding (Segment Embeddings)。最終將三個 Embedding 求和的方式輸入到下一層。
下面詳細介紹下三個 Embedding。
Token Embeddings
通過建立字向量表將每個字轉換成一個一維向量,作為模型輸入。特別的,英文詞匯會做更細粒度的切分,比如playing 或切割成 play 和 ##ing,中文目前尚未對輸入文本進行分詞,直接對單子構成為本的輸入單位。將詞切割成更細粒度的 Word Piece 是為了解決未登錄詞的常見方法。
假如輸入文本 ”I like dog“。下圖則為 Token Embeddings 層實現(xiàn)過程。輸入文本在送入 Token Embeddings 層之前要先進性 tokenization 處理,且兩個特殊的 Token 會插入在文本開頭 [CLS] 和結尾 [SEP]。
Bert 在處理英文文本時只需要 30522 個詞,Token Embeddings 層會將每個詞轉換成 768 維向量,例子中 5 個Token 會被轉換成一個 (6, 768) 的矩陣或 (1, 6, 768) 的張量。
Segment Embedding
Bert 能夠處理句子對的分類任務,這類任務就是判斷兩個文本是否是語義相似的。句子對中的兩個句子被簡單的拼接在一起后送入模型中,Bert 如何區(qū)分一個句子對是兩個句子呢?答案就是 Segment Embeddings。
Segement Embeddings 層有兩種向量表示,前一個向量是把 0 賦值給第一個句子的各個 Token,后一個向量是把1賦值給各個 Token,問答系統(tǒng)等任務要預測下一句,因此輸入是有關聯(lián)的句子。而文本分類只有一個句子,那么 Segement embeddings 就全部是 0。
Position Embedding
由于出現(xiàn)在文本不同位置的字/詞所攜帶的語義信息存在差異(如 ”你愛我“ 和 ”我愛你“),你和我雖然都和愛字很接近,但是位置不同,表示的含義不同。
在 RNN 中,第二個 ”I“ 和 第一個 ”I“ 表達的意義不一樣,因為它們的隱狀態(tài)不一樣。對第二個 ”I“ 來說,隱狀態(tài)經(jīng)過 ”I think therefore“ 三個詞,包含了前面三個詞的信息,而第一個 ”I“ 只是一個初始值。因此,RNN 的隱狀態(tài)保證在不同位置上相同的詞有不同的輸出向量表示。
RNN 能夠讓模型隱式的編碼序列的順序信息,相比之下,Transformer 的自注意力層 (Self-Attention) 對不同位置出現(xiàn)相同詞給出的是同樣的輸出向量表示。盡管 Transformer 中兩個 ”I“ 在不同的位置上,但是表示的向量是相同的。
Transformer 中通過植入關于 Token 的相對位置或者絕對位置信息來表示序列的順序信息。作者測試用學習的方法來得到 Position Embeddings,最終發(fā)現(xiàn)固定位置和相對位置效果差不多,所以最后用的是固定位置的,而正弦可以處理更長的 Sequence,且可以用前面位置的值線性表示后面的位置。
偶數(shù)位置,使用正弦編碼,奇數(shù)位置,使用余弦編碼。
Bert 中處理的最長序列是 512 個 Token,長度超過 512 會被截取,Bert 在各個位置上學習一個向量來表示序列順序的信息編碼進來,這意味著 Position Embeddings 實際上是一個 (512, 768) 的 lookup 表,表第一行是代表第一個序列的每個位置,第二行代表序列第二個位置。
最后,Bert 模型將 Token Embeddings (1, n, 768) + Segment Embeddings(1, n, 768) + Position Embeddings(1, n, 768) 求和的方式得到一個 Embedding(1, n, 768) 作為模型的輸入。
任務1:Masked Language Model
Maked LM 是為了解決單向信息問題,現(xiàn)有的語言模型的問題在于,沒有同時利用雙向信息,如 ELMO 號稱是雙向LM,但實際上是兩個單向 RNN 構成的語言模型的拼接,由于時間序列的關系,RNN模型預測當前詞只依賴前面出現(xiàn)過的詞,對于后面的信息無從得知。
那么如何同時利用好前面的詞和后面的詞的語義呢?Bert 提出 Masked Language Model,也就是隨機遮住句子中部分 Token,模型再去通過上下文語義去預測 Masked 的詞,通過調整模型的參數(shù)使得模型預測正確率盡可能大。
怎么理解這一邏輯,Bert 預訓練過程就是模仿我們學習語言的過程,要準確的理解一個句子或一段文本的語義,就要學習上下文關系,從上下文語義來推測空缺單詞的含義。而 Bert 的做法模擬了英語中的完形填空,隨機將一些單詞遮住,讓 Bert 模型去預測這個單詞,以此達到學習整個文本語義的目的。
那么 Bert 如何做到”完形填空“的呢?
隨機 mask 預料中 15% 的 Token,然后預測 [MASK] Token,與 masked token 對應的最終隱藏向量被輸入到詞匯表上的 softmax 層中。這雖然確實能訓練一個雙向預訓練模型,但這種方法有個缺點,因為在預訓練過程中隨機 [MASK] Token 由于每次都是全部 mask,預訓練期間會記住這些 MASK 信息,但是在fine-tune期間從未看到過 [MASK] Token,導致預訓練和 fine-tune 信息不匹配。
而為了解決預訓練和 fine-tune 信息不匹配,Bert 并不總是用實際的 [MASK] Token 替換 masked 詞匯。
my dog is hairy → my dog is [MASK] 80%選中的詞用[MASK]代替
my dog is hairy → my dog is apple 10%將選中的詞用任意詞代替
my dog is hairy → my dog is hairy 10%選中的詞不發(fā)生變化
為什么 15% 的 Token 不完全 MASK?如果只有 MASK,這個預訓練模型是有偏置的,也就是只能學到一種方式,用上下文去預測一個詞,這導致 fine-tune 丟失一部分信息。
加上 10% 的隨機詞和 10% 的真實值是讓模型知道,每個詞都有意義,除了要學習上下文信息,還需要提防每個詞,因為每個詞都不一定是對的,對于 Bert 來說,每個詞都需要很好的理解和預測。
有些人會疑惑,加了隨機 Token,會讓模型產生疑惑,從而不能學到真實的語義嗎?對于人來說,完形填空都不一定能做對,而將文本中某些詞隨機替換,更是難以理解,從概率角度來說,隨機 Token 占比只有 15% * 10% = 1.5%,預料足夠的情況下,這并不會影響模型的性能。
因為 [MASK] Token 占比變小,且預測難度加大的原因,所以 MASK 會花更多時間。
任務2:Next Sentence Prediction
在許多下游任務中,如問答系統(tǒng) QA 和自然語言推理 NLI,都是建立在理解兩個文本句子之間的關系基礎上,這不是語言模型能直接捕捉到的。
為了訓練一個理解句子關系的模型,作者提出 Next Sentence Prediction,也即是預訓練一個下一句預測的二分類任務,這個任務就是每次訓練前都會從語料庫中隨機選擇句子 A 和句子 B,50% 是正確的相鄰的句子,50% 是隨機選取的一個句子,這個任務在預訓練中能達到 97%-98% 的準確率,并且能很顯著的提高 QA 和 NLI 的效果。
Input = [CLS] the man went to [MASK] store [SEP]
he bought a gallon [MASK] milk [SEP]
Label = IsNext
Input = [CLS] the man [MASK] to the store [SEP]
penguin [MASK] are flight ##less birds [SEP]
Label = NotNext
模型通過對 Masked LM 任務和 Next Sentence Prediction 任務進行聯(lián)合訓練,使模型輸出的每個字 / 詞的向量表示都能盡可能全面、準確地刻畫輸入文本(單句或語句對)的整體信息,為后續(xù)的微調任務提供更好的模型參數(shù)初始值。
Bert如何實現(xiàn)fine-tune
fine-tune 就是指在已經(jīng)訓練好的語言模型基礎上,使用有標簽的數(shù)據(jù)對參數(shù)進行調整,使其更好的適用于下游任務。如對于分類問題在語言模型基礎上加一層 softmax 網(wǎng)絡,然后再新的預料上重新訓練進行 fine-tune。
Bert的主要貢獻
Bert 采用深度雙向 Transformer 語言模型,通過 Mask LM 來達到訓練深度雙向預訓練模型,較之前使用單向語言模型訓練更準確,信息量更大,且語義理解更準確。
論文表明,預訓練模型能省去特定工程需要修改體系架構的麻煩,Bert 是第一個基于 fine-tune 的語言模型,它在大量句子級和 Token 級任務上展現(xiàn)了很好的性能。
Bert 的成功,一個重要原因就是數(shù)據(jù)量大,計算資源豐富。BERT 訓練數(shù)據(jù)采用了英文的開源語料 BooksCropus以及英文維基百科數(shù)據(jù),一共有 33 億個詞。同時 BERT 模型的標準版本有 1 億的參數(shù)量,與 GPT 持平,而 BERT的大號版本有 3 億多參數(shù)量,這應該是目前自然語言處理中最大的預訓練模型了。
當然,這么大的模型和這么多的數(shù)據(jù),訓練的代價也是不菲的。谷歌用了 16 個自己的 TPU 集群(一共 64 塊 TPU)來訓練大號版本的 BERT,一共花了 4 天的時間。
對于是否可以復現(xiàn)預訓練,作者在 Reddit 上有一個大致的回復,指出 OpenAI 當時訓練GPT用了將近 1 個月的時間,而如果用同等的硬件條件來訓練 BERT 估計需要 1 年的時間。不過他們會將已經(jīng)訓練好的模型和代碼開源,方便大家訓練好的模型上進行后續(xù)任務。