BERT模型引入及詳解
參考
-
視頻:
- ELMo 模型(雙向 LSTM 模型解決詞向量多義問題
-
博客:
- BERT模型
- BERT詳解:概念、原理與應用
- 一文讀懂BERT
ELMo模型
參考:
- 視頻:
- ELMo模型(雙向LSTM模型解決詞向量多義問題)
- 博客:
- 【自然語言處理】ELMo, GPT等經典模型的介紹與對比
引入
在Word Embedding
中,詞語都是由一個唯一的詞向量進行表示的,不根據句子改變而改變
也就是說,Word Embedding
表示詞的方法是靜態的,無法對多義詞進行處理
對于這個例子,盡管不同序列中的bank
的上下文不同,但經語言模型訓練時,無論什么序列經過Word2Vec
,都是對bank
這個詞進行預測,因此占用的是嵌入矩陣中的同一行參數;這樣會導致不同的語義被壓縮到同一個Word Embedding
空間,進而導致Word Embedding
無法區分多義詞
核心思想
事先用語言模型訓練好了一個單詞的Word Embedding
,但是它此時還無法區分多義詞語義,這沒關系
當使用Word Embedding
時,此時單詞已經具有特定的上下文,這個時候我可以根據上下文單詞的語義再去調整單詞的 Word Embedding
表示,這樣經過調整后的 Word Embedding
更能表達單詞在這個上下文中的具體含義
ELMo
模型的核心思想就是:根據當前上下文對Word Embedding
進行動態調整
注意:ELMo
是對Word2Vec
的改進,模型的主要任務還是在于詞向量而不是預測生成
不只是訓練一個嵌入矩陣Q,還要把當前詞的上下文信息融入到這個Q矩陣
兩階段過程
- 利用語言模型做預訓練
- 做下游任務時,從預訓練網絡中提取對應單詞的網絡各層的
Word Embedding
作為新特征補充到下游任務中
架構
預訓練過程
分為三部分:
- Embedding模塊 - 提取單詞特征
- 雙層雙向LSTM模塊
- 第一層:提取句法特征
- 第二層:提取語義特征
- 詞向量表征模塊
- 使用若干參數融合每一層提取到的特征信息
Embedding模塊
使用CNN
去提取輸入序列的文字特征,得到一個靜態的Word Embedding
作為整個網絡的底層輸入
雙層雙向LSTM模塊
當前預訓練語言模型的任務是:
根據當前詞wiw_iwi?的上下文去正確預測單詞wiw_iwi?,wiw_iwi?之前的單詞序列Context-before稱為上文,wiw_iwi?之后的單詞序列Context-after稱為下文
圖中左側的雙層LSTM
稱為前向LSTM
網絡,輸入順序從左至右,輸入除了wi以外的上文除了w_i以外的上文除了wi?以外的上文
對于n個w,語言模型通過前k?1個w來計算第k個w出現的概率,構成雙層前向LSTMP(w1,w2,?,wn)=∏k=1nP(wk∣w1,?,wk?1)\begin{align} 對于n個w,語言模型通過前k-1個w來計算第k個w出現的概率,構成雙層前向LSTM\\ P(w_1,w_2,\cdots,w_n) = \prod_{k=1}^{n}P(w_k | w_1,\cdots,w_{k-1}) \end{align} 對于n個w,語言模型通過前k?1個w來計算第k個w出現的概率,構成雙層前向LSTMP(w1?,w2?,?,wn?)=k=1∏n?P(wk?∣w1?,?,wk?1?)??
圖中右側的雙層LSTM
稱為反向LSTM
網絡,輸入順序從右至左,輸入除了wi以外的逆序下文除了w_i以外的逆序下文除了wi?以外的逆序下文
語言模型通過后n?k個w來計算第k個w出現的概率,構成雙層反向LSTMP(w1,w2,?,wn)=∏k=1nP(wk∣wk+1,?,wn)\begin{align} 語言模型通過后n-k個w來計算第k個w出現的概率,構成雙層反向LSTM\\ P(w_1,w_2,\cdots,w_n) = \prod_{k=1}^{n}P(w_k | w_{k+1},\cdots,w_{n}) \end{align} 語言模型通過后n?k個w來計算第k個w出現的概率,構成雙層反向LSTMP(w1?,w2?,?,wn?)=k=1∏n?P(wk?∣wk+1?,?,wn?)??
ELMo
的訓練目標是最大化下面這個函數
∑k=1n(P(wk∣w1,?,wk?1;Θx,Θ→LSTM,Θs)+P(wk∣wk+1,?,wn;Θx,Θ←LSTM,Θs))Θx:詞的輸入表示參數(CNN中的參數)Θ→LSTM:雙層前向LSTM的參數Θ←LSTM:雙層反向LSTM的參數Θs:輸出層參數\begin{align} \sum_{k=1}^{n}(P(w_k|w_1,\cdots,w_{k-1};\Theta_{x},{\overrightarrow{\Theta}_{LSTM}},\Theta_{s})+P(w_k|w_{k+1},\cdots,w_{n};\Theta_{x},{{\overleftarrow{\Theta}}_{LSTM}},\Theta_{s}))\\ \Theta_{x}:詞的輸入表示參數(CNN中的參數)\\ \overrightarrow{\Theta}_{LSTM}:雙層前向LSTM的參數\\ \overleftarrow{\Theta}_{LSTM}:雙層反向LSTM的參數\\ \Theta_{s}:輸出層參數\\ \end{align} k=1∑n?(P(wk?∣w1?,?,wk?1?;Θx?,ΘLSTM?,Θs?)+P(wk?∣wk+1?,?,wn?;Θx?,ΘLSTM?,Θs?))Θx?:詞的輸入表示參數(CNN中的參數)ΘLSTM?:雙層前向LSTM的參數ΘLSTM?:雙層反向LSTM的參數Θs?:輸出層參數??
詞向量表征模塊
對于每個w,通過一個L層的雙向LSTM網絡,可以計算出2L+1個表示向量對于第k個詞wk,第j層的雙向LSTM網絡Rk={xkLM,hk,jLM→,hk,jLM←∣j=1,?,L}={hk,j∣j=1,2,?,L}hk,jLM→:第j層正向LSTM對wk的隱藏狀態hk,jLM←:第j層反向LSTM對wk的隱藏狀態\begin{align} 對于每個w,通過一個L層的雙向LSTM網絡,可以計算出2L+1個表示向量\\ 對于第k個詞w_k,第j層的雙向LSTM網絡\\ R_k = \{{x_k^{LM},\overrightarrow{h_{k,j}^{LM}},\overleftarrow{h_{k,j}^{LM}}}\ \ |\ \ j=1,\cdots,L\} = \{h_{k,j}\ \ |\ \ j=1,2,\cdots,L\}\\ \overrightarrow{h_{k,j}^{LM}}:第j層正向LSTM對w_k的隱藏狀態\\ \overleftarrow{h_{k,j}^{LM}}:第j層反向LSTM對w_k的隱藏狀態 \end{align} 對于每個w,通過一個L層的雙向LSTM網絡,可以計算出2L+1個表示向量對于第k個詞wk?,第j層的雙向LSTM網絡Rk?={xkLM?,hk,jLM??,hk,jLM????∣??j=1,?,L}={hk,j???∣??j=1,2,?,L}hk,jLM??:第j層正向LSTM對wk?的隱藏狀態hk,jLM??:第j層反向LSTM對wk?的隱藏狀態??
Feature-based Pre-Training
上圖展示了下游任務的使用過程
比如我們的下游任務是QA,此時對于問句X:
- 將這個X作為預訓練好的
ELMo
網絡的輸入,這樣X中的每個單詞在ELMo
網絡中都能獲取對應的3個embedding
- 分別給予這3個
embedding
權重a,這個權重可以學習得來; - 根據各自權重累加求和,將三個
embedding
整合成一個 - 將整合后的
embedding
作為X句在自己任務中的對應單詞的輸入,以此作為補充的新特征給下游任務使用
因為 ELMo 給下游提供的是每個單詞的特征形式,所以這一類預訓練的方法被稱為 “Feature-based Pre-Training”
GPT模型
GPT(Generative Pre-Training)
是指生成式的預訓練模型
不同于ELMo模型
的基于特征融合的預訓練方法,GPT
采用了一種叫 Fine-tuning(微調)
的預訓練方法
GPT
也采用兩階段過程:
- 階段1:利用語言模型進行預訓練
- 階段2:通過
Fine-tuning
模型解決下游任務
預訓練
這個結構乍一看,和ELMo模型
很像,但是有以下不同:
- 特征抽取器使用了雙層
Transfomer
,而不是雙層LSTM
,有利于學習長序列和并行運行 GPT
使用單向語言模型;特征抽取時不同時使用上文下文,僅使用上文預測;而ELMo
的雙層雙向LSTM
則是同時使用上文和下文進行預測
缺點:從現在來看,使用單向語言模型,沒有融合單詞的下文,在一些應用場景受限,比如完成閱讀理解任務,這個任務允許同時看到上文和下文來進行決策
Fine-tuning解決下游任務
- 對于下游網絡來說,要將網絡結構改造成與
GPT
一樣的網絡結構 - 做下游任務時,利用第一步預訓練好的參數去初始化下游任務網絡(與
GPT
結構一樣)的網絡結構,這樣一來,預訓練學到的語言學知識就被引入到當前任務中了 - 用當前任務再去訓練這個網絡,對參數進行
Fine-tuning
,使這個網絡更適合解決當前問題
那么到底什么是Fine-tuning
呢?
Fine-tuning
其實上面解決下游任務的過程已經對Fine-tuning
簡單地描述了一遍
Fine-tuning
其實就是在已經訓練好的模型的基礎上,針對特定任務,再對模型的部分/全部參數進行訓練,以使模型更適應當前任務(很像遷移學習)
優點
- 解決小規模數據集的訓練問題
- 節省訓練時間和成本
- 提升模型在目標任務上的性能
BERT模型
參考
定義
BERT模型(Bidirectional Encoder Representations from Transformers)
是一種基于 Transformer
架構的預訓練語言模型
它的特殊之處并不是說它有什么很突出的創新點,而是集大成者
所謂集大成者:
- 借鑒了
ELMo
模型雙向雙層LSTM
同時使用上文下文預測的思路 - 與
GPT
類似,使用Transformer
作為特征提取器 - 采用了
Word2Vec
的CBOW
模型
結構 & 對比
ELMo
使用從左向右和從右向左的兩個LSTM
網絡,分別以 P(wi∣w1,?,wi?1)和?P(wi∣wi+1,?,wn)P(w_i|w_1,\cdots,w_{i-1})\ 和\ P(w_i|w_{i+1},\cdots,w_{n})P(wi?∣w1?,?,wi?1?)?和?P(wi?∣wi+1?,?,wn?)作為目標函數獨立訓練,將訓練得到的特征向量用拼接實現雙向編碼,其實本質上還是相當于單向編碼GPT
使用Transformer Decoder
作為Transformer Block
,以P(wi∣w1,?,wi?1)P(w_i|w_1,\cdots,w_{i-1})P(wi?∣w1?,?,wi?1?)為目標函數,使用Transformer Block
代替LSTM
進行特征提取,實現了單向編碼,是一個標準的預訓練語言模型BERT
也是一個標準的預訓練語言模型,以P(wi∣w1,?,wn)P(w_i|w_1,\cdots,w_n)P(wi?∣w1?,?,wn?)作為目標函數進行訓練;使用Transformer Encoder
作為Transformer Block
,將GPT的單向編碼改為雙向編碼;也就是說,BERT
舍棄了文本生成能力,換來了更強的語義理解能力
BERT的模型其實就是Transformer Encoder
的堆疊,在模型參數上,官方一開始提供了兩個版本:
BERTBASE:L=12,H=768,A=12BERTLARGE:L=24,H=1024,A=16L:TransformerBlock的層數H:特征向量的維度A:多頭自注意力機制的頭數\begin{align} BERT_{BASE}:L=12,H=768,A=12\\ BERT_{LARGE}:L=24,H=1024,A=16\\ L:Transformer\ Block的層數\\ H:特征向量的維度\\ A:多頭自注意力機制的頭數\\ \end{align} BERTBASE?:L=12,H=768,A=12BERTLARGE?:L=24,H=1024,A=16L:Transformer?Block的層數H:特征向量的維度A:多頭自注意力機制的頭數??
無監督訓練
方法
BERT
也采用二階段預訓練方法:
- 第一階段:使用易獲取的大規模無標簽語料,訓練基礎語言模型
- 第二階段:使用指定任務的少量帶標簽數據進行
Fine-tuning
任務
- 使用語言掩碼模型(MLM)方法訓練詞的語義理解能力
- 用下句預測(NSP)方法訓練句子之間的理解能力,從而更好支持下游任務
語言掩碼模型MLM
由來
BERT
作者認為自左向右和自右向左的單向編碼器拼成的雙向編碼器,在性能,參數規模,效率等方面都不如深度雙向編碼器
這就是為什么BERT
使用Transformer Encoder
作為特征提取器,而不是使用從左至右編碼和從右至左編碼的兩個Transformer Decoder
由于無法使用標準語言模型的訓練模式(?),BERT
使用MLM
進行訓練模型,MLM借鑒了完形填空
和CBOW
的思想
回答:傳統的語言模型(基于循環神經網絡構建的語言模型)都是單向的,比如ELMo(兩個單向拼接成一個雙向);而BERT是雙向語言模型,所以需要使用全新的訓練方式
- AR模型(自回歸模型)
- 根據上文預測下一個單詞,或根據下文預測前一個單詞,只能考慮單側信息
- AE模型(自編碼模型)
- 從損壞的輸入數據中預測重構原始數據,可以使用上下文信息,
BERT
采用的就是AE模型
- 從損壞的輸入數據中預測重構原始數據,可以使用上下文信息,
做法
在原始句子中,隨機抽取15%的token
進行掩蓋,用其上下文去判斷[mask]
位置被掩蓋的token
原本應該是什么
由于BERT
使用AE模型,MLM
的做法會有個問題,15%的掩蓋率其實很高了,會導致掩碼詞在下游任務Fine-tuning
階段從未被見過,導致了預訓練和Fine-tuning
的不一致
簡單理解就是:在預訓練學習階段,模型已經習慣了[mask]
,那么MLM學到的一些表達就可能依賴于[mask]
;但是在下游任務中[mask]
可能從未出現,這就導致了一些表達無法很好的遷移
為了解決這個問題,對于被選取的作為掩碼詞的15%的token
,不是全用[mask]
代替,而是采取以下做法來解決上述弊端:
- 對于80%的訓練樣本:
- 將選取的
token
直接替換成[mask]
- 將選取的
用[]表示選取中的token比如:我好餓啊,我想吃[飯]↓我好餓啊,我想吃[mask]
- 對于10%的訓練樣本:
- 選中的詞原封不動,為了緩解訓練文本和預測文本的偏差帶來的性能損失
- 對于最后10%的訓練樣本:
- 將選中的詞隨機替換成一個新詞,這樣是為了讓
BERT
學會根據上下文糾錯
- 將選中的詞隨機替換成一個新詞,這樣是為了讓
用[]表示選取中的token比如:我好餓啊,我想吃[飯]↓我好餓啊,我想吃電腦
這樣的好處是:編碼器不知道哪些詞是需要預測的,哪些詞是錯誤的,因此被迫學習每一個token
的表示向量
下句預測NSP
在很多自然語言處理的下游任務(如問答,自然語言推斷)中,都基于兩個句子做邏輯推理,但模型本身并不具備直接捕獲句
子之間語義聯系的能力,或者說,單詞預測的訓練(比如GPT,ELMo,都是基于上下文對單詞預測)達不到句子關系這個層級
為了學會捕捉句子之間的語義聯系,BERT 采用了下句預測(NSP)作為無監督預訓練的一部分。
NSP的具體做法是:BERT的輸入由兩個句子(A,B)組成,其中:
- 50%的概率為這兩個句子是連續的,即B是真實文本中A的下一句話
- 另外50%的概率為這兩個句子是隨機抽取的
句子的形式:
[CLS] A [SEP] B [SEP]
[SEP]標簽表示分隔符
[CLS]標簽用于類別預測,結果為1時,表示輸入連續句對(isNext),為0時表示隨機句對(notNext)
通過訓練[CLS]
編碼后的輸出標簽,BERT可以學會捕捉兩個輸入句對的文本語義
eg:
Input: [CLS]The man went to [MASK] [SEP] He bought a bottle of Coke[SEP]
Label: isNextInput: [CLS]The man [MASK] to store[SEP] I'm going to sleep[SEP]
Label: notNext
輸入表示
BERT的預訓練方法有以上兩種,但是實際使用中通常是兩種方法混合使用
由于BERT模型通過Transformer Encoder
堆疊組成,因此BERT的輸入需要兩套embedding
操作:
- Token Embeddings
- 將各個詞轉換為固定維度的向量表示;
- 在BERT中,每個單詞會先進行
Tokenization
后再輸入Token Embeddings
層中 - 插入兩個特殊的
Token
,在Tokenization
的結果開頭加上[CLS]
,結尾加上[SEP]
- 最終轉換為768維的向量
- 在BERT中,每個單詞會先進行
- 將各個詞轉換為固定維度的向量表示;
- Position Embeddings
- 不同于
Transformer
中用三角函數固定表示每個位置的位置編碼,BERT中的位置編碼是預訓練過程中通過學習得來的,訓練思想類似于Word2Vec
中嵌入矩陣Q
- 不同于
- Segment Embeddings
- 用于區分一個單詞屬于句子對中的哪個句子
- 賦0:第一個句子中的各個
Token
- 賦1:第二個句子中的各個
Token
- 賦0:第一個句子中的各個
- 用于區分一個單詞屬于句子對中的哪個句子
這3個向量都是768維的,最后將其按元素相加,得到最終的Input Embedding