本篇文章共 15326 個詞,一個字一個字手碼的不容易,轉載請標明出處:
BERT 模型詳解 - 二十三歲的有德html
BERT 在天然語言處理(NLP)領域刷新了 11 個任務的記錄,萬衆矚目,成爲異常火熱的一個預訓練語言模型。python
今天咱們就來詳細講解下 BERT 這個預訓練語言模型,雖然 BERT 刷新了各個任務的記錄,可是 BERT 並非一個具備極大創新的算法,更多的是一個集大成者,把 BERT 以前各個語言模型的優勢集於一身,並做出了適當的改進,而擁有了現在無與倫比的能力。git
BERT 既然是集大成者,那麼集了哪些大成呢?github
既然是集大成者,那麼咱們只要把上述五點大成一一解釋清楚,相信再帶你看 BERT 時,你必定會豁然開朗:「BERT 不過如此」。算法
在敘述圖像領域的預訓練以前,咱們經過下圖來看看 CNN 是如何對圖片作特徵提取的:一張圖片放入到 CNN 中,由淺層到深層api
經過上述分析,也就是說,CNN 淺層提取的特徵對於各個任務而言都是通用的。網絡
圖 1 - CNN 提取圖片特徵架構
聰明的讀者應該想到了,什麼是 「預訓練」,但很懵懵懂懂,下面咱們來詳細解釋。app
圖 2 - 預訓練在圖像領域的應用框架
假設咱們擁有兩個儘可能類似的任務 A 和 B(能夠都爲圖像處理任務),任務 A 是咱們目標任務,任務 B 是能夠提早訓練好的一個任務:
上述兩個步驟便是預訓練的思想,那麼預訓練有什麼好處呢?
在講解 CBOW 思想以前,咱們不得不講解下詞向量的發展史,這算是預訓練語言模型的始祖,語言模型的預訓練的思想最先來源於此,而且 CBOW 模型就是爲了生成單詞的詞向量應運而生。
One-hot 編碼相信你們都很熟悉了,一個很簡單的小知識,讓計算機認識現實世界中的單詞。
因爲計算機並不認識單詞 「time、fruit……」,爲此,人們構建一個詞典 \(V\) ,以下圖所示詞典包含 8 個單詞,對於詞典中的每一個單詞,都有之對應的 \(|V|\)(詞典大小的)維度的向量表示,以下圖的 「time」 對應的向量爲 8 維的 「1000 0000」。
圖 3 - 詞的 One-hot 編碼
One-hot 編碼雖然解決了計算機不認識單詞的這一缺陷,可是 One-hot 編碼自己也是有問題的,對於上圖 「fruit」 和 「banana」 的 One-hot 編碼,能夠經過餘弦類似度計算二者的類似性,能夠發現結果爲 0,也就是二者絕不相關,然而實際上二者是相關的,由此,詞向量應運而生。
圖 4 - 神經網絡語言模型架構
如今讓咱們看看詞向量究竟是個什麼玩意兒,對於上述的 3 層神經網絡語言模型(NNLM),它的學習任務是輸入某個句中單詞 \(w_t = banana\) 前的 \(t-1\) 個單詞,要求網絡正確預測單詞 「banana」,即最大化:
其中 \(\theta\) 是 NNLM 的參數。
首先輸入前 \(t-1\) 個單詞的 One-hot 編碼
單詞的 One-hot 編碼通過第一層,輸入層,One-hot 編碼左乘矩陣 Q 獲得詞向量 \(C(w_i)\)
詞向量 \(C(w_i)\) 通過第二層,隱層(至關於全鏈接層),隱層的輸出爲 \(\tanh(Wx+d)\),其中 \(x\) 爲輸入的詞向量,\(W\) 爲權重矩陣,\(d\) 爲偏置,\(\tanh\) 爲激活函數。
[11, 22, 55, 44, 87, 84, 88]
第二層輸出的向量通過第三層,輸出層,通過 Softmax 函數歸一化。
假設輸入爲一個輸出爲一個 8 維的向量 [11, 22, 55, 44, 87, 84, 88]
,則該層輸出爲 [0.000, 0.000, 0.000, 0.000, 0.265, 0.013, 0.721]
,對應圖三,則該層輸出的對應的詞爲 「banana」
y = torch.FloatTensor([11, 22, 55, 44, 87, 84, 88]) print(functional.softmax(y, dim=0)) # 輸出: [0.000, 0.000, 0.000, 0.000, 0.265, 0.013, 0.721]
在講解 NNLM 的過程當中,能夠看到該模型的一個副產品詞向量 \(C(w_i)\),這就是大名鼎鼎的詞向量。
這個詞向量是如何解決 One-hot 編碼對於本應該類似的單詞而不類似的問題的呢?假設矩陣 Q 己經被成功訓練,下面咱們來計算 「banana」 的詞向量:
同理 「fruit」 的詞向量爲 [23,5,7]
,二者的餘弦類似度爲 「0.638」,能夠發現詞向量順利的解決了詞類似的問題。
y1 = torch.FloatTensor([7, 6, 18]) y2 = torch.FloatTensor([23, 5, 7, ]) print(torch.cosine_similarity(y1, y2, dim=0)) # 輸出:0.638
上過構建詞向量的過程被稱做 Word Embedding,並且細心地讀者應該發現訓練矩陣 Q 並獲得詞向量的過程其實就是一個預訓練的過程,對於將來的 NLP 的任務,直接使用訓練獲得的矩陣 Q 和詞向量便可。
下圖給出網上找的幾個例子,能夠看出有些效果仍是蠻不錯的:
圖 5 - Word Embedding 例子
NNLM 的學習任務是輸入某個句中單詞 \(w_t = banana\) 前的 \(t-1\) 個單詞,要求網絡正確預測單詞 「banana」,矩陣 Q 和詞向量都只是它的副產品。
爲此,2013 年出現了一個最火的用語言模型專門作 Word Embedding 的工具 Word2Vec ,它的架構以下圖所示:
圖 6 - Word2Vec 模型
因爲 Word2Vec 專門用來作 Word Embedding,它再也不是利用前 \(t-1\) 個單詞,而是利用了上下文信息,這個也是很好理解的,對於一個單詞的解釋,利用上下文的信息做出的解釋會更合理。
其實 Word2Vec 和 NNLM 很是相似,都是三層架構,除了利用了上下文信息,Word2Vec 還提供了 2 種訓練方法:
當你看到 CBOW 的時候,想必你也想到了爲何要在這裏講講 Word2Vec 的緣由,由於將來的 BERT 將會用到 CBOW 的思想:利用單詞 \(w_t\) 上下文的信息,預測單詞 \(w_t\)
Attention 機制來源於人類的視覺注意力機制:人類視覺經過快速掃描全局圖像,得到須要重點關注的目標區域,也就是通常所說的注意力焦點,然後對這一區域投入更多注意力資源,以獲取更多所須要關注目標的細節信息,而抑制其餘無用信息。
對於下圖,若是隻關心顏色,咱們可能第一眼就會把重心放在顯眼的紅色上,而後再觀察其餘地方。
圖 7 - 嬰兒圖像
經過對人類視覺注意力機制的描述,Attention 機制簡單點講就是:經過一個 Query(查詢變量)從一堆信息(Key-Value 表示的信息,能夠把 Key 看做信息的地址,Value 表示信息的內容)中找到對於 Query 而言重要的信息,以此獲取更多對於 Query 而言更重要的細節信息,進而抑制其餘無用信息。
Attention 的具體作法以下圖所示:
圖 8 - Attention 計算圖
計算 Q 和 K 的類似度,用 f 來表示:\(f(Q,K_i)\quad i=1,2,\cdots,m\),Self-Attention 模型中 \(f(Q,K_i) = Q^TK_i\)
第二步:將獲得的類似度進行 softmax 操做,進行歸一化:\(\alpha_i = softmax(\frac{f(Q,K_i)}{\sqrt d_k})\)
這裏簡單講解除以 \(\sqrt d_k\) 的做用:假設 \(Q\) , \(K\) 裏的元素的均值爲0,方差爲 1,那麼 \(A^T=Q^TK\) 中元素的均值爲 0,方差爲 d。當 d 變得很大時, \(A\) 中的元素的方差也會變得很大,若是 \(A\) 中的元素方差很大(分佈的方差大,分佈集中在絕對值大的區域),在數量級較大時, softmax 將幾乎所有的機率分佈都分配給了最大值對應的標籤,因爲某一維度的數量級較大,進而會致使 softmax 將來求梯度時會消失。總結一下就是 \(\operatorname{softmax}\left(A\right)\) 的分佈會和d有關。所以 \(A\) 中每個元素乘上 \(\frac{1}{\sqrt{d_k}}\) 後,方差又變爲 1,而且 \(A\) 的數量級也將會變小。
y1 = torch.FloatTensor([11, 22, 55, 44, 87, 84, 88]) y2 = torch.FloatTensor([11, 22, 55, 44, 80, 80, 88]) print(functional.softmax(y1, dim=0)) # 輸出: [0.000, 0.000, 0.000, 0.000, 0.265, 0.013, 0.721] print(functional.softmax(y2, dim=0)) # 輸出:[0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.999]
針對計算出來的權重 \(\alpha_i\),對 \(V\) 中的全部 values 進行加權求和計算,獲得 Attention 向量:\(Attention = \sum_{i=1}^m \alpha_i V_i\)
Self-Attention 模型是 Attention 機制的具體應用,下面咱們給出 Self-Attention 的架構圖:
圖 9 - Self-Attention 模型架構圖
經過上圖能夠看到 Self Attention 有三個輸入 Q、K、V:對於 Self Attention,Q、K、V 來自輸入句子 X 的 詞向量 x 的線性轉化,即對於詞向量 x,給定三個可學習的矩陣參數 \(W_Q,W_k,W_v\),x 分別右乘上述矩陣獲得 Q、K、V。這也是Self-Attention 名字的來源:Q、K、V 三個矩陣由同一個詞向量線性轉化而得。
下面咱們來詳細瞭解下 Self-Attention 的具體計算流程:
第一步,Q、K、V 的獲取
、
圖 10 - Q、K、V 矩陣的獲取
上圖操做:兩個單詞 Thinking 和 Machines。經過線性變換,即 \(x_i\) 和 \(x_2\) 兩個向量分別與\(W_q,W_k,W_v\) 三個矩陣點乘獲得 ${q_1,q_2},{k_1,k_2},{v_1,v_2} $ 共 6 個向量。矩陣 Q 則是向量 \(q_1,q_2\) 的拼接,K、V 同理。
第二步,MatMul
圖 11 - \(q_1\) 和 \(k一、k_2\) 的計算
上圖操做:向量 \({q_1,k_1}\) 作點乘獲得得分 112, \({q_1,k_2}\) 作點乘獲得得分96。注意:這裏是經過 \(q_1\) 這個信息找到 \(x_1,x_2\) 中的重要信息。
第三步和第四步,Scale + Softmax
圖 12 - \(q_1\) 和 \(k一、k_2\) 的計算作 Softmax
上圖操做:對該得分進行規範,除以 \(\sqrt {d_k} = 8\)
第五步,MatMul
圖 13 - \(z_1\) 的計算
用得分比例 [0.88,0.12] 乘以 \([v_1,v_2]\) 值獲得一個加權後的值,將這些值加起來獲得 \(z_1\)。
上述所說就是 Self Attention 模型所作的事,仔細感覺一下,用 \(q_1\)、\(K=[k_1,k_2]\) 去計算一個 Thinking 相對於 Thinking 和 Machine 的權重,再用權重乘以 Thinking 和 Machine 的 \(V=[v_1,v_2]\) 獲得加權後的 Thinking 和 Machine 的 \(V=[v_1,v_2]\),最後求和獲得針對各單詞的輸出 \(z_1\)。
同理能夠計算出 Machine 相對於 Thinking 和 Machine 的加權輸出 \(z_2\)。
上述所計算的結果 \(z_1\) 就能夠看做是查詢變量 Thinking 的詞向量,而且是 Thinking 從 Thinking Machine 這句話中找到了對於 Thinking 而言更爲重要的信息,而且抑制了不重要的信息。這樣講,可能沒法理解 Self-Attention 機制的好處,咱們能夠經過下圖來了解 Self-Attention 機制的優勢到底在哪裏:
圖 14 - attention 獲取句法特徵
圖 15 - attention 獲取語義特徵
從圖 14 能夠看出,Self-Attention 捕獲了同一個句子中單詞之間的一些句法特徵(有必定距離的短語結構);從圖 15 能夠看出,Self-Attention 捕獲了同一個句子中單詞之間的語義特徵(「its」 的指代對象 「Law」)。
而且從上面的計算步驟和圖片能夠看出,不管句子序列多長,均可以很好的提取句子特徵,而且既能夠提取句法特徵還能夠提取語義特徵,這很好的解決了 RNN 序列長距離依賴的問題,並且對於一個句子而言,每一個單詞的計算是能夠並行處理的。
圖 16 - RNN 結構圖
上述例子是 Self-Attention 單個向量運算的例子。下圖展現的是 Self-Attention 的矩陣運算的例子,輸入是一個 [2x4] 的矩陣(句子中每一個單詞的詞向量的拼接),每一個運算是 [4x3] 的矩陣,求得 Q、K、V。
Q 對 K 轉製作點乘,除以 \(\sqrt d_k\),作一個 softmax 獲得合爲 1 的比例,對 V 作點乘獲得輸出 Z。那麼這個 Z 就是一個考慮過 Thinking 周圍單詞 Machine 的輸出。
注意看這個公式,\(QK^T\) 其實就會組成一個 word2word 的 attention map!(加了 softmax 以後就是一個合爲 1 的權重了)。好比說你的輸入是一句話 "i have a dream" 總共 4 個單詞,這裏就會造成一張 4x4 的注意力機制的圖:
這樣一來,每個單詞對應每個單詞都會有一個權重,這也是 Self Attention 名字的來源,即 Attention 的計算來源於 Source(源句) 和 Source 自己,通俗點講就是 Q、K、V 都來源於輸入 X 自己。
趁熱打鐵,咱們講講 Transformer 將來會用到的 Masked Self Attention 模型,這裏的 Masked 就是要在作語言模型(或者像翻譯)的時候,不給模型看到將來的信息,它的結構以下圖所示:
上圖中和 Self Attention 重複的部分此處就不講了,主要講講 Mask 這一塊。
假設在此以前咱們已經經過 scale 以前的步驟獲得了一個 attention map,而 mask 就是沿着對角線把灰色的區域用0覆蓋掉,不給模型看到將來的信息,以下圖所示:
詳細來講:
而且在作完 softmax 以後,橫軸結果合爲 1。以下圖所示:
具體爲何 在 Transformer 中要用到 Masked Self Attention,將來在講解 Transformer 的時候會詳細解釋。
因爲 Transformer 使用的都是 Self Attention 的進階版 Multi-head Self Attention,咱們簡單講講 Multi-head Self Attention 的架構,而且在該小節結尾處講講它的優勢。
Multi-Head Attention 就是把 Self Attention的過程作 H 次,而後把輸出 Z 合起來。論文中,它的結構圖以下:
咱們仍是以上面的形式來解釋,首先,咱們使用 8 組不一樣的 \(W_Q^i,W_k^i,W_V^i\quad i=1,2,\cdots,8\) ,重複 8 次和 Self Attention 類似的操做,獲得 8 個 \(Z_i\) 矩陣:
爲了使得輸出與輸入結構相同,拼接矩陣 \(Z_i\) 後乘以一個線性 \(W_0\) 獲得最終的Z:
看完了 Multi-head Self Attention 的架構,發現它與 Self Attention 的區別,在於用了 \(n\) 組 \(W_Q^i,W_k^i,W_V^i\quad i=1,2,\cdots,n\) 獲得 \(n\) 組 \(Q_i,K_i,V_i \quad i=1,2,\cdots,n\)。
能夠經過下圖看看 multi-head attention 的整個流程:
上述操做有什麼好處呢?使用多套參數,多套參數至關於把原始信息 Source 放入了多個子空間中,也就是捕捉了多個信息,對於使用 multi-head(多頭) attention 的簡單回答就是,多頭保證了 attention 能夠注意到不一樣子空間的信息,捕捉到更加豐富的特徵信息。其實本質上是論文原做者發現這樣效果確實好。
在 Attention 和 RNN 的對比中,咱們說到 Attention 解決了長距離依賴問題,而且能夠支持並行化,可是它就真的百利而無一害了嗎?
其實否則,咱們往前回顧,Self Attention 的 Q、K、V 三個矩陣是由同一個輸入 \(X_1=(x_1,x_2,\cdots,x_n)\) 線性轉換而來,也就是說對於這樣的一個被打亂序列順序的 \(X_2=(x_2,x_1,\cdots,x_n)\) 而言,因爲 Attention 值的計算最終會被加權求和,也就是說二者最終計算的 Attention 值都是同樣的,進而也就代表了 Attention 丟掉了 \(X_1\) 的序列順序信息。
如上圖所示,爲了解決 Attention 丟失的序列順序信息,Transformer 的提出者提出了 Position Embedding,也就是對於輸入 \(X\) 進行 Attention 計算以前,在 \(X\) 的詞向量中加上位置信息,也就是說 \(X\) 的詞向量爲 \(X_{final\_embedding} = Embedding + Positional\, Embedding\)
可是如何獲得 \(X\) 的位置向量呢?
其中位置編碼公式以下圖所示:
其中 pos 表示位置、i 表示維度、\(d_{model}\)表示位置向量的向量維度 、\(2i、2i+1\) 表示的是奇偶數(奇偶維度),上圖所示就是偶數位置使用 \(\sin\) 函數,奇數位置使用 \(\cos\) 函數。
有了位置編碼,咱們再來看看位置編碼是如何嵌入單詞編碼的(其中 512 表示編碼維度),經過把單詞的詞向量和位置向量進行疊加,這種方式就稱做位置嵌入,以下圖所示:
Position Embedding 自己是一個絕對位置的信息,但在語言模型中,相對位置也很重要。那麼爲何位置嵌入機制有用呢?
咱們不要去關心三角函數公式,能夠看看下圖公式(3)中的第一行,咱們作以下的解釋,對於 「我愛吃蘋果」 這一句話,有 5 個單詞,假設序號分別爲 一、二、三、四、5。
假設 \(pos=1=我、k=2=愛、pos+k=3=吃\),也就是說 \(pos+k=3\) 位置的位置向量的某一維能夠經過 \(pos=1\) 位置的位置向量的某一維線性組合加以線性表示,經過該線性表示能夠得出 「吃」 的位置編碼信息蘊含了相對於前兩個字 「我」 的位置編碼信息。
總而言之就是,某個單詞的位置信息是其餘單詞位置信息的線性組合,這種線性組合就意味着位置向量中蘊含了相對位置信息。
萬事俱備,只欠東風,下面咱們來說講咱們的重點之一,Transformer,你能夠先記住這一句話:Transformer 簡單點看其實就是 self-attention 模型的疊加,首先咱們來看看 Transformer 的總體框架。
Transformer 的總體框架以下圖所示:
上圖所示的總體框架乍一眼一看很是複雜,因爲 Transformer 起初是做爲翻譯模型,所以咱們以翻譯舉例,簡化一下上述的總體框架:
從上圖能夠看出 Transformer 至關於一個黑箱,左邊輸入 「Je suis etudiant」,右邊會獲得一個翻譯結果 「I am a student」。
再往細裏講,Transformer 也是一個 Seq2Seq 模型(Encoder-Decoder 框架的模型),左邊一個 Encoders 把輸入讀進去,右邊一個 Decoders 獲得輸出,以下所示:
在這裏,咱們穿插描述下 Encoder-Decoder 框架的模型是如何進行文本翻譯的:
- 將序列 \((x_1,x_2,\cdots,x_n)\) 做爲 Encoders 的輸入,獲得輸出序列 \((z_1,z_2,\cdots,z_n)\)
- 把 Encoders 的輸出序列 \((z_1,z_2,\cdots,z_n)\) 做爲 Decoders 的輸入,生成一個輸出序列 \((y_1,y_2,\cdots,y_m)\)。注:Decoders 每一個時刻輸出一個結果
第一眼看到上述的 Encodes-Decoders 框架圖,隨之產生問題就是 Transformer 中 左邊 Encoders 的輸出是怎麼和右邊 Decoders 結合的。由於decoders 裏面是有N層的,再畫張圖直觀的看就是這樣:
也就是說,Encoders 的輸出,會和每一層的 Decoder 進行結合。
如今咱們取其中一層進行詳細的展現:
經過上述分析,發現咱們想要詳細瞭解 Transformer,只要瞭解 Transformer 中的 Encoder 和 Decoder 單元便可,接下來咱們將詳細闡述這兩個單元。
有了上述那麼多知識的鋪墊,咱們知道 Eecoders 是 N=6 層,經過上圖咱們能夠看到每層 Encoder 包括兩個 sub-layers:
注意:在每一個 sub-layer 咱們都模擬了殘差網絡(在下面的數據流示意圖中會細講),每一個sub-layer的輸出都是 \(LayerNorm(x+Sub\_layer(x))\),其中 \(sub\_layer\) 表示的是該層的上一層的輸出
如今咱們給出 Encoder 的數據流示意圖,一步一步去剖析
須要注意的是,上述的 \(x、z、r\) 都具備相同的維數,論文中爲 512 維。
Decoders 也是 N=6 層,經過上圖咱們能夠看到每層 Decoder 包括 3 個 sub-layers:
以上,就講完了 Transformer 編碼和解碼兩大模塊,那麼咱們迴歸最初的問題,將 「機器學習」 翻譯成 「machine learing」,解碼器的輸出是一個浮點型的向量,怎麼轉化成 「machine learing」 這兩個詞呢?讓咱們來看看 Encoders 和 Decoders 交互的過程尋找答案:
從上圖能夠看出,Transformer 最後的工做是讓解碼器的輸出經過線性層 Linear 後接上一個 softmax
假設詞彙表維度是 6,那麼輸出最大機率詞彙的過程以下:
首先咱們來看看拿 Transformer 做翻譯時,如何生成翻譯結果的:
繼續進行:
假設上圖是訓練模型的某一個階段,咱們來結合 Transformer 的完整框架描述下這個動態的流程圖:
如今咱們來解釋咱們以前遺留的兩個問題。
訓練階段:咱們知道 「je suis etudiant」 的翻譯結果爲 「I am a student」,咱們把 「I am a student」 的 Embedding 輸入到 Decoders 裏面,翻譯第一個詞 「I」 時
測試階段:咱們不知道 「我愛中國」 的翻譯結果爲 「I love China」,咱們只能隨機初始化一個 Embedding 輸入到 Decoders 裏面,翻譯第一個詞 「I」 時:
總結下就是:Decoder 作 Mask,是爲了讓訓練階段和測試階段行爲一致,不會出現間隙,避免過擬合
咱們在講解 Attention 機制中曾提到,Query 的目的是藉助它從一堆信息中找到重要的信息。
如今 Encoder 提供了 \(K_e、V_e\) 矩陣,Decoder 提供了 \(Q_d\) 矩陣,經過 「我愛中國」 翻譯爲 「I love China」 這句話詳細解釋下。
當咱們翻譯 「I」 的時候,因爲 Decoder 提供了 \(Q_d\) 矩陣,經過與 \(K_e、V_e\) 矩陣的計算,它能夠在 「我愛中國」 這四個字中找到對 「I」 翻譯最有用的單詞是哪幾個,並以此爲依據翻譯出 「I」 這個單詞,這就很好的體現了注意力機制想要達到的目的,把焦點放在對本身而言更爲重要的信息上。
BERT 模型能夠做爲公認的里程碑式的模型,可是它最大的優勢不是創新,而是集大成者,而且這個集大成者有了各項突破,下面讓咱們看看 BERT 是怎麼集大成者的。
以下圖所示,咱們來看看 ELMo、GPT 和 BERT 三者的區別
BERT 的模型結構以下圖所示:
從上圖能夠發現,BERT 的模型結構其實就是 Transformer Encoder 模塊的堆疊。在模型參數選擇上,論文給出了兩套大小不一致的模型。
\(BERT_{BASE}\) :L = 12,H = 768,A = 12,總參數量爲 1.1 億
\(BERT_{LARGE}\):L = 24,H = 1024,A = 16,總參數量爲 3.4 億
其中 L 表明 Transformer Block 的層數;H 表明特徵向量的維數(此處默認 Feed Forward 層中的中間隱層的維數爲 4H);A 表示 Self-Attention 的頭數,使用這三個參數基本能夠定義 BERT的量級。
BERT 參數量級的計算公式:
訓練過程也是很花費計算資源和時間的,總之表示膜拜,普通人即使有 idea 沒有算力也只能跪着。
BERT 採用二段式訓練方法:
不一樣於 GPT 等標準語言模型使用 \(P(w_i|w_1,\cdots,w_{i-1})\) 爲目標函數進行訓練,能看到全局信息的 BERT 使用 \(P(w_i|w_1,\cdots,w_{i-1},w_{i+1},\cdots,w_n)\) 爲目標函數進行訓練。
而且 BERT 用語言掩碼模型(MLM)方法訓練詞的語義理解能力;用下句預測(NSP)方法訓練句子之間的理解能力,從而更好地支持下游任務。
BERT 做者認爲,使用自左向右編碼和自右向左編碼的單向編碼器拼接而成的雙向編碼器,在性能、參數規模和效率等方面,都不如直接使用深度雙向編碼器強大,這也是爲何 BERT 使用 Transformer Encoder 做爲特徵提取器,而不使用自左向右編碼和自右向左編碼的兩個 Transformer Decoder做爲特徵提取器的緣由。
因爲沒法使用標準語言模型的訓練模式,BERT 借鑑完形填空任務和 CBOW 的思想,使用語言掩碼模型(MLM )方法訓練模型。
MLM 方法也就是隨機去掉句子中的部分 token(單詞),而後模型來預測被去掉的 token 是什麼。這樣實際上已經不是傳統的神經網絡語言模型(相似於生成模型)了,而是單純做爲分類問題,根據這個時刻的 hidden state 來預測這個時刻的 token 應該是什麼,而不是預測下一個時刻的詞的機率分佈了。
隨機去掉的 token 被稱做掩碼詞,在訓練中,掩碼詞將以 15% 的機率被替換成 [MASK],也就是說隨機 mask 語料中 15% 的 token,這個操做則稱爲掩碼操做。注意:在CBOW 模型中,每一個詞都會被預測一遍。
可是這樣設計 MLM 的訓練方法會引入弊端:在模型微調訓練階段或模型推理(測試)階段,輸入的文本中將沒有 [MASK],進而致使產生由訓練和預測數據誤差致使的性能損失。
考慮到上述的弊端,BERT 並無總用 [MASK] 替換掩碼詞,而是按照必定比例選取替換詞。在選擇 15% 的詞做爲掩碼詞後這些掩碼詞有三類替換選項:
「地球是[MASK]八大行星之一」
「地球是太陽系八大行星之一」
「地球是蘋果八大行星之一」
做者在論文中提到這樣作的好處是,編碼器不知道哪些詞須要預測的,哪些詞是錯誤的,所以被迫須要學習每個 token 的表示向量,另外做者也表示雙向編碼器比單項編碼器訓練要慢,進而致使BERT 的訓練效率低了不少,可是實驗也證實 MLM 訓練方法可讓 BERT 得到超出同期全部預訓練語言模型的語義理解能力,犧牲訓練效率是值得的。
在不少天然語言處理的下游任務中,如問答和天然語言推斷,都基於兩個句子作邏輯推理,而語言模型並不具有直接捕獲句子之間的語義聯繫的能力,或者能夠說成單詞預測粒度的訓練到不了句子關係這個層級,爲了學會捕捉句子之間的語義聯繫,BERT 採用了下句預測(NSP )做爲無監督預訓練的一部分。
NSP 的具體作法是,BERT 輸入的語句將由兩個句子構成,其中,50% 的機率將語義連貫的兩個連續句子做爲訓練文本(連續句對通常選自篇章級別的語料,以此確保先後語句的語義強相關),另外 50% 的機率將徹底隨機抽取兩個句子做爲訓練文本。
連續句對:[CLS]今每天氣很糟糕[SEP]下午的體育課取消了[SEP]
隨機句對:[CLS]今每天氣很糟糕[SEP]魚快被烤焦啦[SEP]
其中 [SEP] 標籤表示分隔符。 [CLS] 表示標籤用於類別預測,結果爲 1,表示輸入爲連續句對;結果爲 0,表示輸入爲隨機句對。
經過訓練 [CLS] 編碼後的輸出標籤,BERT 能夠學會捕捉兩個輸入句對的文本語義,在連續句對的預測任務中,BERT 的正確率能夠達到 97%-98%。
BERT 在預訓練階段使用了前文所述的兩種訓練方法,在真實訓練中通常是兩種方法混合使用。
因爲 BERT 經過 Transformer 模型堆疊而成,因此 BERT 的輸入須要兩套 Embedding 操做:
對於分割編碼,Segment Embeddings 層只有兩種向量表示。前一個向量是把 0 賦給第一個句子中的各個 token,後一個向量是把 1 賦給第二個句子中的各個 token ;若是輸入僅僅只有一個句子,那麼它的 segment embedding 就是全 0,下面咱們簡單舉個例子描述下:
[CLS]I like dogs[SEP]I like cats[SEP] 對應編碼 0 0 0 0 0 1 1 1 1
[SEP]I Iike dogs and cats[SEP] 對應編碼 0 0 0 0 0 0 0
BERT 根據天然語言處理下游任務的輸入和輸出的形式,將微調訓練支持的任務分爲四類,分別是句對分類、單句分類、文本問答和單句標註,接下來咱們將簡要的介紹下 BERT 如何經過微調訓練適應這四類任務的要求。
給定兩個句子,判斷它們的關係,稱爲句對分類,例如判斷句對是否類似、判斷後者是否爲前者的答案。
針對句對分類任務,BERT 在預訓練過程當中就使用了 NSP 訓練方法得到了直接捕獲句對語義關係的能力。
以下圖所示,句對用 [SEP] 分隔符拼接成文本序列,在句首加入標籤 [CLS],將句首標籤所對應的輸出值做爲分類標籤,計算預測分類標籤與真實分類標籤的交叉熵,將其做爲優化目標,在任務數據上進行微調訓練。
針對二分類任務,BERT 不須要對輸入數據和輸出數據的結構作任何改動,直接使用與 NSP 訓練方法同樣的輸入和輸出結構就行。
針對多分類任務,須要在句首標籤 [CLS] 的輸出特徵向量後接一個全鏈接層和 Softmax 層,保證輸出維數與類別數目一致,最後經過 arg max 操做(取最大值時對應的索引序號)獲得相對應的類別結果。
下面給出句對分類似性任務的實例:
任務:判斷句子 「我很喜歡你」 和句子 「我很中意你」 是否類似
輸入改寫:「[CLS]我很喜歡你[SEP]我很中意你」
取 「[CLS]」 標籤對應輸出:[0.02, 0.98]
經過 arg max 操做獲得類似類別爲 1(類別索引從 0 開始),即兩個句子類似
給定一個句子,判斷該句子的類別,統稱爲單句分類,例如判斷情感類別、判斷是否爲語義連貫的句子。
針對單句二分類任務,也無須對 BERT 的輸入數據和輸出數據的結構作任何改動。
以下圖所示,單句分類在句首加入標籤 [CLS],將句首標籤所對應的輸出值做爲分類標籤,計算預測分類標籤與真實分類標籤的交叉熵,將其做爲優化目標,在任務數據上進行微調訓練。
一樣,針對多分類任務,須要在句首標籤 [CLS] 的輸出特徵向量後接一個全鏈接層和 Softmax 層,保證輸出維數與類別數目一致,最後經過 argmax 操做獲得相對應的類別結果。
下面給出語義連貫性判斷任務的實例:
任務:判斷句子「海大球星飯茶吃」 是否爲一句話
輸入改寫:「[CLS]海大球星飯茶吃」
取 「[CLS]」 標籤對應輸出:[0.99, 0.01]
經過 arg max 操做獲得類似類別爲 0,即這個句子不是一個語義連貫的句子
給定一個問句和一個蘊含答案的句子,找出答案在後這種的位置,稱爲文本問答,例如給定一個問題(句子 A),在給定的段落(句子 B)中標註答案的其實位置和終止位置。
文本問答任何和前面講的其餘任務有較大的差異,不管是在優化目標上,仍是在輸入數據和輸出數據的形式上,都須要作一些特殊的處理。
爲了標註答案的起始位置和終止位置,BERT 引入兩個輔助向量 s(start,判斷答案的起始位置) 和 e(end,判斷答案的終止位置)。
以下圖所示,BERT 判斷句子 B 中答案位置的作法是,將句子 B 中的每個次獲得的最終特徵向量 \(T_i'\) 通過全鏈接層(利用全鏈接層將詞的抽象語義特徵轉化爲任務指向的特徵)後,分別與向量 s 和 e 求內積,對全部內積分別進行 softmax 操做,便可獲得詞 Tok m(\(m\in [1,M]\))做爲答案其實位置和終止位置的機率。最後,去機率最大的片斷做爲最終的答案。
文本回答任務的微調訓練使用了兩個技巧:
下面給出文本問答任務的實例:
任務:給定問句 「今天的最高溫度是多少」,在文本 「天氣預報顯示今天最高溫度 37 攝氏度」 中標註答案的起始位置和終止位置
輸入改寫:「[CLS]今天的最高溫度是多少[SEP]天氣預報顯示今天最高溫度 37 攝氏度」
BERT Softmax 結果:
篇章文本 天氣 預報 顯示 今天 最高溫 37 攝氏度 起始位置機率 0.01 0.01 0.01 0.04 0.10 0.80 0.03 終止位置機率 0.01 0.01 0.01 0.03 0.04 0.10 0.80 對 Softmax 的結果取 arg max,獲得答案的起始位置爲 6,終止位置爲 7,即答案爲 「37 攝氏度」
給定一個句子,標註每一個次的標籤,稱爲單句標註。例如給定一個句子,標註句子中的人名、地名和機構名。
單句標註任務和 BERT 預訓練任務具備較大差別,但與文本問答任務較爲類似。
以下圖所示,在進行單句標註任務時,須要在每一個詞的最終語義特徵向量以後添加全鏈接層,將語義特徵轉化爲序列標註任務所需的特徵,單句標註任務須要對每一個詞都作標註,所以不須要引入輔助向量,直接對通過全鏈接層後的結果作 Softmax 操做,便可獲得各種標籤的機率分佈。
因爲 BERT 須要對輸入文本進行分詞操做,獨立詞將會被分紅若干子詞,所以 BERT 預測的結果將會是 5 類(細分爲 13 小類):
將 5 大類的首字母結合,可得 IOBES,這是序列標註最經常使用的標註方法。
下面給出命名實體識別(NER)任務的示例:
任務:給定句子 「愛因斯坦在柏林發表演講」,根據 IOBES 標註 NER 結果
輸入改寫:「[CLS]愛 因 斯坦 在 柏林 發表 演講」
BERT Softmax 結果:
BOBES 愛 因 斯坦 在 柏林 發表 演講 O 0.01 0.01 0.01 0.90 0.01 0.90 0.90 B-PER 0.90 0.01 0.01 0.01 0.01 0.01 0.01 I-PER 0.01 0.90 0.01 0.01 0.01 0.01 0.01 E-PER 0.01 0.01 0.90 0.01 0.01 0.01 0.01 S-LOC 0.01 0.01 0.01 0.01 0.01 0.01 0.01 對 Softmax 的結果取 arg max,獲得最終地 NER 標註結果爲:「愛因斯坦」 是人名;「柏林」 是地名
不管如何,從上述講解能夠看出,NLP 四大類任務均可以比較方便地改形成 Bert 可以接受的方式,總之不一樣類型的任務須要對模型作不一樣的修改,可是修改都是很是簡單的,最多加一層神經網絡便可。這實際上是 Bert 的很是大的優勢,這意味着它幾乎能夠作任何NLP的下游任務,具有普適性,這是很強的。
可是講了這麼多,一個新模型好很差,效果纔是王道。那麼Bert 採用這種兩階段方式解決各類 NLP 任務效果如何?
在 11 個各類類型的 NLP 任務中達到目前最好的效果,某些任務性能有極大的提高。
最後,我講講我對Bert的評價和見解,我以爲 Bert 是 NLP 裏裏程碑式的工做,對於後面 NLP 的研究和工業應用會產生長久的影響,這點毫無疑問。可是從上文介紹也能夠看出,從模型或者方法角度看,Bert 借鑑了 ELMO,GPT 及 CBOW,主要提出了 Masked 語言模型及 Next Sentence Prediction,可是這裏 Next Sentence Prediction 基本不影響大局,而 Masked LM 明顯借鑑了 CBOW 的思想。因此說 Bert 的模型沒什麼大的創新,更像最近幾年 NLP 重要進展的集大成者,這點若是你看懂了上文估計也沒有太大異議,若是你有大的異議,槓精這個大帽子我隨時準備戴給你。
若是概括一下這些進展就是:首先是兩階段模型,第一階段雙向語言模型預訓練,這裏注意要用雙向而不是單向,第二階段採用具體任務 Fine-tuning 或者作特徵集成;第二是特徵抽取要用Transformer 做爲特徵提取器而不是 RNN 或者 CNN;第三,雙向語言模型能夠採起 CBOW 的方法去作(固然我以爲這個是個細節問題,不算太關鍵,前兩個因素比較關鍵)。Bert 最大的亮點在於效果好及普適性強,幾乎全部 NLP 任務均可以套用 Bert 這種兩階段解決思路,並且效果應該會有明顯提高。能夠預見的是,將來一段時間在 NLP 應用領域,Transformer 將佔據主導地位,並且這種兩階段預訓練方法也會主導各類應用。
另外,咱們應該弄清楚預訓練這個過程本質上是在作什麼事情,本質上預訓練是經過設計好一個網絡結構來作語言模型任務,而後把大量甚至是無窮盡的無標註的天然語言文本利用起來,預訓練任務把大量語言學知識抽取出來編碼到網絡結構中,當手頭任務帶有標註信息的數據有限時,這些先驗的語言學特徵固然會對手頭任務有極大的特徵補充做用,由於當數據有限的時候,不少語言學現象是覆蓋不到的,泛化能力就弱,集成儘可能通用的語言學知識天然會增強模型的泛化能力。如何引入先驗的語言學知識其實一直是 NLP 尤爲是深度學習場景下的 NLP 的主要目標之一,不過一直沒有太好的解決辦法,而 ELMO/GPT/Bert 的這種兩階段模式看起來無疑是解決這個問題天然又簡潔的方法,這也是這些方法的主要價值所在。
對於當前 NLP 的發展方向,我我的以爲有兩點很是重要:
目前看預訓練這種兩階段方法仍是頗有效的,也很是簡潔,固然後面確定還會有更好的模型出現。
完了,這就是預訓練語言模型的前世此生。
因爲我的剛入門 NLP 方向,就不妄自總結,上述總結所有來自知乎文章:從Word Embedding到Bert模型—天然語言處理中的預訓練技術發展史-張俊林
我只是知識的搬運工,想詳細瞭解各個知識點的讀者能夠自行選擇參考下列資料。
參考書籍:
《預訓練語言模型》- 卲浩、劉一烽
《基於 BERT 模型的天然語言處理實戰》- 李金洪
參考論文:
參考博客: