理解Bert

離開深度學習瞎折騰了一段時間后,我終于又回來了。

于是趕緊回顧了下18年之后NLP的發展,基本就是將遷移學習更廣泛的用于NLP領域,以及把17年年底的《Attention is all you need》里的思想給發揚光大了,ELMO彌補了傳統word2vec多義詞表示的不足,GPT使用更強大的特征提取器Transformer取代LSTM,Bert使用雙向Transformer進一步改進了GPT成為這兩年發展的集大成者。

從Bert模型所帶來的NLP界里程碑式的影響和所取得的成就來看,無疑Bert將會是未來兩三年NLP應用發展的基石,于是有必要仔細的看看其模型的結構,數據是如何流動的,訓練的和測試的。

不得不說現在的學習環境相對幾年前好太多了,本文主要參考了以下幾篇文章,然后加了點自己的理解:

Dissecting BERT Part 1: The Encoder

The Illustrated Transformer

Dissecting BERT Appendix: The Decoder

它的總體框架同lstm時代的MNT或者是attention is all you need中的transformer一樣的encoder-decoder結構:

b1.png

我們先來介紹一下Encoder部分。

Encoder

為了理解這個架構,我們使用一個簡單的具體的例子,來看一下輸入的數據是怎么通過encoder一步一步變化讓后到輸出的。

從詞到向量

bert的詞嵌入由三個嵌入token embedding、segment embedding,和position embedding疊加而成。

Token embedding

這個過程跟以往的RNNs沒什么區別,比如給定一個句子:

Hello, how are you?

第一步是先將其標記化:

“ Hello, how are you?” → [“Hello”, “,” , “how”, “are”, “you”, “?”]

然后是數字化,將每個標記映射到語料詞匯表中的唯一整數編號:

[“Hello”, “, “, “how”, “are”, “you”, “?”] → [34, 90, 15, 684, 55, 193]

接下來就是得到序列中每個詞的詞嵌入,也就是將整數映射到一個emb\_dim? 維的向量,這個向量是模型在訓練時學習的,你可以將其視為一個查表的過程,這些向量的元素作為模型的參數,像其他權重一樣通過反向傳播進行了優化。

在論文中是使用WordPiece tokenization 來將英文單詞轉換成768(emb\_dim)維的向量,轉化的過程類似這樣:

b2.png

把每個詞的向量放到一起,就得到了一個句子長度x向量維度(input\_length * emb\_dim?) 尺寸的矩陣Z:

b3.png

說明一點,我們通常使用填充的方式來讓輸入序列具有相同的長度,比如通過添加"<pad>" 標記來增加某些序列的長度,還是前面的例子,填充后可能變為:

[“<pad>”, “<pad>”, “<pad>”, “Hello”, “, “, “how”, “are”, “you”, “?”] →

[5, 5, 5, 34, 90, 15, 684, 55, 193]

如果設定input\_length ?設定為9,那我們就把句子從5填充到了9。

Positional Encoding

但是,上面的embedding并沒有包含詞的位置信息。于是,我們的目標是能夠根據詞在句子中的位置適當調整這個向量,使它帶上位置信息。

作者選擇的方法是使用預定的(非學習的)正余弦函數將[-1,1] ? 之間的數字加到前面的embedding中,即通過正余弦函數將位置表示為彼此的線性組合,從而實現網絡學習中標記位置之間的相對關系。在Token embedding 獲得的矩陣Z? 的基礎上加上位置矩陣P? 。

數學上,用i 表示序列中標記的位置,用j 表示token embedding特征向量中的位置:

b4.png

具體來說,對于給定的句子P ,其位置嵌入矩陣為:

b5.png

作者解釋說,使用這種確定性方法的結果和學習位置表示(就像我們對詞嵌入那樣)的結果差不多,因此這樣反而會有一些優勢:

  • input_length 可以無限長,因為函數可以計算任意位置
  • 需要學習的參數更好啊,訓練更快

因此,添加了位置信息之后的矩陣是:

X = Z + P

它是第一個encoder塊的輸入,尺寸是input\_length * emb\_dim ?

Encoder block

共有N個編碼器塊連接在一起直到生成編碼器的輸出,特定的塊負責查找輸入表示之間的關系并將編碼在其輸出中。

直觀地,通過這些塊的迭代過程將幫助神經網絡捕獲輸入序列中的詞之間的更加復雜的關系,你可以把它理解成一個整體用來捕捉輸入序列的語義。

Multi-Head Attention

encoder中使用Transformer的多頭注意力機制,這意味著它將計算h? 份不同權重矩陣的自注意力,然后將結果連接在一起。

這些并行注意力計算的結果稱之為Head,我們用下標i? 來表示一個特定的head和相關的權重矩陣。

b6.png

如上圖所示,一旦計算了所有head,它們將被連接起來,得到一個尺寸為input\_length *(h *d_v) 的矩陣,然后將它乘以一個尺寸為(h * d_v) * emb\_dim 的權重矩陣W^0 進行線性變換,就得到了一個尺寸為(input\_length) * emb\_dim? 的最終結果,用數學公式表示就是:

MultiHead(Q,K,V) = Concat(head_1,...,head_h)W^0 \\ where ~~head_i = Attention(XW_i^Q,XW_i^K,XW_i^V)

其中的Q, K, V 通過X? 乘以相應權重矩陣W_i^Q獲得,我們通過一個簡單的例子來可視化的看一下這個過程。

這圖描繪了輸入標記通過 token embedding 和 positional encoding ,再輸入到Encoder:

b7.png

接下來,我們再來看下Encoder中的操作過程,先看一下單頭的self-attention:

b8.png

上圖描繪了一個Head的Q (Querys), K(Keys) , V(Values)? 是怎么來的,其中的W_i^K , W^Q_i? 的尺寸是 d_{emb\_dim} * d_k? , 因為Q和K需要計算相似性,所以維度應當是相同的,W_i^V? 的尺寸是d_{emb\_dim} * d_v? ,V? 的維度可以相同也可以不同,在論文中d_k = d_v = emb\_dim /h? .

XW_i^K = K_i \\ XW_i^Q = Q_i \\ XW_i^V = V_i

所謂的自注意力,就是Q_iK_i^T 的點積進行\sqrt {d_k} 的縮放之后通過softmax獲得一個概率權重,然后用這些權重分別乘以各自的V_i? 即可:

Attention(Q_i,K_i,V_i) = softmax(\frac{Q_iK_i^T}{\sqrt{d_k}}) V_i

為了加深理解,我們選擇其中一個頭,通過圖形繼續可視化的看一下這個變化過程:

b9.png

然后計算self-attention,

b10.png

多頭的話就是同時有多個上述計算過程在進行:

b11.png

假設我們有8個Head,那么我們就獲得8個Z? :

b12.png

但是,顯然前饋層只需要一個矩陣Z ,怎么處理呢?類似多卷積核的處理,把這8個矩陣連起來,乘以一個權重矩陣W^0 ?壓縮到一個矩陣。

b13.png

為了有一個更加全面直觀的認識,我們把上面整個過程放到一個圖里,

b14.png

顯然,第二個encoder塊是不需要embedding過程的,只要把第一個encoder塊的輸出作為輸入即可。

經過上面的介紹,你應該對這個過程已經有了足夠的了解,但是,為什么可以利用向量點積來計算注意力概率呢?

于是讓我們進一步深入來了解其中的原理。

這個結構體系的關鍵在于:

Q_iK_i^T

也就是每個詞的q向量與每個詞的k向量的點積,套用點積公式:

qk = cos(q,k)\left \| q \right \|\left \| k \right \|

這意味著qk 的方向越相似,長度越大,點積就越大。詞與此之間關聯越大,對于理解這個詞時得到的關注越大,跟我們的本意是相同的。

Add & Norm

我們再看一下最開頭的結構示意圖,每個encoder塊在Multi-Head Attention之后經過一個 Add & Norm層才進入下一個塊。于是我們來看一下這一層做了些什么。

Add實際就是一個殘差連接,將輸出加上輸入,這個在每一塊的self-attenton以及FFN之后都會有,然后跟隨一個Layer Norm 。

Norm 是一個Layer Normlization,將Z + X? 正則化,就是把它縮放到一個均值為0方差為1的域里。因為

不過一般在這一層之前,就會有一個dropout層。

Position-wise Feed-Forward Network

每個encoder塊都由 mulit-head atteion \to? add & Norm \to? feed forword network \to? add & Norm 這樣一個過程,下面來介紹一下這個Feed-Forward Network。

這是一個全連接層,包含兩個線性變化和一個非線性函數(實際一般就是ReLu),

b15.png

對于輸入的x? (尺寸為input\_length * emb\_dim?) ,通過權重矩陣W_1? (尺寸為emb\_dim * d_F ?)和偏置b_1? 線性變換到隱藏層 (尺寸為input\_length * d_F? ) ,然后**ReLu **激活 ,記下來再用權重矩陣W_2? (尺寸為d_F * emb\_dim?) 和偏置 b_2? 的線性變換到輸出層(尺寸為input\_length * emb\_dim ? ) ,表示成數學公式就是:

FFN(x) = max(0, xW_1+b_1)W_2 +b_2

在最后一個encoder塊輸出之后連接到decoder。

Decoder

Decoder和Encoder的結構是類似的,但是因為可視信息的不同,又有所差別。

Transformer解決的是翻譯的問題,將一個句子翻譯成另一種語言,我們希望模型能夠捕捉到輸入句子中詞之間的關系,并且將輸入句子中包含的信息與每一步已翻譯的內容結合起來。繼續上面的例子,我們的目標是把一個句子從英文翻譯為西班牙文,這是我們獲得的序列標記:

X = [‘Hello’, ‘,’, ‘how’, ‘are’, ‘you’, ‘?’] (Input sequence)
Y = [‘Hola’, ‘,’, ‘como’, ‘estas’, ‘?’] (Target sequence)

我們同之前一樣來看看輸入到輸出數據是如何流動的。

這是我們的解碼器的輸入標記:

[‘<SS>’, ’Hola’, ‘,’, ‘ como’, ‘estas’, ‘?’]

然后這是解碼器的期望輸出:

[’Hola’, ‘,’, ‘ como’, ‘estas’, ‘?’,’<EOS>’]

但是,這里存在一個問題,比如輸入這邊我們已經看到了'como' 的后面是'estas', 然后再用它來預測'estas' ,這顯然是不合理的,因為模型在測試的時候是看不到后面的詞的。

因此,我們需要修改注意力層,防止模型可以看到預測詞右邊的信息,與此同時,它能利用已經預測的詞,即左邊的信息。

繼續上面的例子,我們將輸入標記轉換成矩陣的形式,并添加位置信息:

b16.png

和encoder一樣,decoder塊的輸出也將是大小為target\_length * emb\_dim? 的矩陣,在逐行線性變換+softmax激活后,將生成一個舉證,其中每行的最大元素表示下一個單詞。也就是說,分配"<SS>" 的行負責預測“Hola”, 分配"Hola"的行負責預測"," ...以此類推。比如,為了預測"estas", 我們將允許該行直接和下圖中綠色區域互動,而不能和紅色區域互動:

b17.png

但是,在我們使用多頭注意力機制的時候,所有的行都會產生交互,因此需要在輸入的時候添加遮罩,這個遮罩會在注意力計算之后進行:

\frac{Q_iK_i^T}{\sqrt{d_k}}

這是self-attention的計算結果:

b18.png

然后我們在此基礎上添加遮掩,就是把矩陣上三角的位置全部設置為- \infin

b19.png

于是,在進行softmax激活之后,矩陣就變成了:

b20.png

恰好達到了我們的要求,那些需要在訓練時忽略的右側的詞的注意力全部變成了0。

當將這個注意力矩陣與V_i? 相乘時,預測的詞就是模型可以訪問元素右邊的元素。注意,這里的多頭注意力輸出將是target\_length * emb\_dim? 維的,因為它的序列長度是target\_length? 。

這個就是Decodertarget序列的輸入,并經過Masked Multi-Head Attention 的一個變化得到了D,decoder的還有一部分輸入來自于源語句經過Encoder的最終輸出E (尺寸是 input\_length * emb\_dim )。

接下來,就是與encoder一樣的 Multi-Head Attention \to Add and Layer Norm -> FFN 的過程。

只不過,現在的Q 來自于 D ,而K , V 來自于E:

DW_i^Q = Q_i ~~~~(size:target\_length * d_k) \\ EW_i^K = K_i ~~~~(size:input\_length * d_k) \\ EW_i^V = V_i ~~~~(size:input\_length * d_v)

計算每個query相對于key的注意力之后,得到的是一個target\_length * input\_length? 的矩陣, 繼續咱們的例子,比如注意力矩陣為:

b21.png

如上圖所見,這個注意力是當前Decoder輸入與Encoder輸出的每個詞之間的注意力,咱們用這個矩陣再乘以V? ,就得到了一個target\_length * d_v? 的矩陣,每一行代表了源語句相對于當前輸入詞匯的特征:

b22.png
b23.png

h個Head連接起來,尺寸變為 target\_length * d_v * h ? ,它通過d_v * h * emb\_dim ?的權重矩陣W_0? 線性變換到一個target\_length * emb\_dim ? 的輸出。

這在多個Decoder之后,最后輸出的矩陣通過乘以權重矩陣W_1 (emb\_dim * vocab\_size) 進行線性變換,變換之后再對每一行的向量softmax, 其中選擇值最大位置對應詞表索引的詞就是預測的詞。

損失的話只需要用預測的每個詞向量與真實的詞的one-hot詞表示計算交叉熵即可。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,501評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,673評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,610評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,939評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,668評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,004評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,173評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,705評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,426評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,656評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,833評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,247評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,580評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,371評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,621評論 2 380

推薦閱讀更多精彩內容