於是我趕緊回顧了壹下18之後NLP的發展。基本上我在NLP領域更廣泛的使用了遷移學習,並在17的最後把《註意力就是妳需要的全部》中的思想發揚光大。ELMO彌補了傳統word2vec多義性表達的不足,GPT用更強大的特征提取器Transformer代替了LSTM,伯特用雙向Transformer進壹步完善了GPT。
從Bert模型給NLP帶來的裏程碑式的影響和成就來看,毫無疑問,Bert將是未來兩三年NLP應用開發的基石,所以需要仔細看看它的模型的結構,數據是如何流動的,是如何訓練和測試的。
不得不說現在的學習環境比幾年前好多了。本文主要參考以下文章,然後補充壹些理解:
剖析BERT第1部分:編碼器
圖示的變壓器
剖析BERT附錄:解碼器
它的整體框架具有與lstm時代的MNT或《註意力集中的變形金剛》相同的編碼器-解碼器結構:
先介紹編碼器部分。
為了理解這種架構,讓我們用壹個簡單具體的例子來看看輸入數據是如何通過編碼器壹步步變為輸出的。
伯特的單詞嵌入由三種嵌入組成:記號嵌入、片段嵌入和位置嵌入。
這個過程和以前的rnn沒什麽區別,比如給壹句話:
第壹步是標記它:
然後進行數字化,將每個標簽映射到語料庫詞匯表中的壹個唯壹整數:
接下來就是得到序列中每個單詞的單詞嵌入,也就是把整數映射成壹維向量。這個向量是模型在訓練時學習的,妳可以把它看成壹個查找過程。作為模型的參數,這些向量的元素像其他權重壹樣通過反向傳播來優化。
本文采用詞塊標記化將英文單詞轉換成768()維向量,轉換過程類似於這樣:
把每個單詞的向量放在壹起,就得到壹個句子長度x向量維數的矩陣Z():
為了清楚起見,我們通常使用填充來使輸入序列具有相同的長度,例如,通過添加“
如果設置為9,那麽我們將從5到9填充句子。
但是上面的嵌入並不包含單詞的位置信息。所以我們的目標是根據單詞在句子中的位置適當調整這個向量,使其攜帶位置信息。
作者選擇的方法是用壹個預定的(非學習的)正弦余弦函數將它們之間的數字加到之前的嵌入中,即通過正弦余弦函數將位置表示為彼此的線性組合,從而實現網絡學習中標記位置之間的相對關系。將位置矩陣添加到通過令牌嵌入獲得的矩陣中。
在數學上,標記在序列中的位置由表示,並且在令牌嵌入特征向量中的位置由表示:
具體來說,對於給定的句子,其位置嵌入矩陣為:
作者解釋說,使用這種確定性方法的結果類似於學習位置表征的結果(就像我們嵌入單詞壹樣),所以會有壹些優勢:
因此,添加位置信息後的矩陣為:
它是第壹個編碼器模塊的輸入,其大小為
* * *在生成編碼器的輸出之前,有n個編碼器模塊連接在壹起,特定模塊負責查找輸入表示之間的關系,並在其輸出中對其進行編碼。
直觀上,這些塊的叠代過程會幫助神經網絡捕捉到輸入序列中更復雜的詞與詞之間的關系,妳可以把它理解為壹個整體來捕捉輸入序列的語義。
編碼器使用了Transformer的多頭關註機制,這意味著它會計算不同權重矩陣的自我關註度,然後將結果連接在壹起。
這些並行註意力計算的結果被稱為頭部,我們使用下標來表示特定的頭部和相關的權重矩陣。
如上圖所示,計算完所有人頭後,將它們連接起來得到壹個尺寸矩陣,然後乘以壹個尺寸的權重矩陣進行線性變換,得到壹個最終的尺寸結果,用壹個數學公式表示:
其中壹個是通過乘以相應的權重矩陣獲得的。讓我們通過壹個簡單的例子直觀地看壹下這個過程。
該圖描述了輸入令牌通過令牌嵌入和位置編碼,然後被輸入到編碼器:
接下來,我們來看看編碼器中的操作流程,先看單頭自關註:
上圖描繪了壹個人頭是怎麽來的,其中維數是,因為Q和K需要計算相似度,所以維數應該是相同的,維數是,維數可以相同也可以不同,在論文中。
所謂的自關註,就是用縮放點積後通過softmax得到壹個概率權重,然後把這些權重乘以自己的:
為了加深理解,我們選擇其中壹個頭像,繼續通過圖形直觀地看這個變化過程:
然後計算自我關註度,
如果妳看多,上面提到的幾個計算過程同時在進行:
假設我們有八個頭,那麽我們得到八個:
然而,顯然前饋層只需要壹個矩陣。怎麽處理?類似於多重卷積核的處理,將這八個矩陣連接起來,乘以壹個權重矩陣,壓縮成壹個矩陣。
為了有更全面直觀的認識,我們把上面的整個過程放成壹張圖。
顯然,第二編碼器塊不需要嵌入過程,只需將第壹編碼器塊的輸出作為輸入。
經過上面的介紹,妳應該對這個過程有了很好的理解,但是為什麽可以用向量點積來計算註意概率呢?
所以讓我們進壹步了解原理。
這個結構體系的關鍵在於:
即每個單詞的q向量和每個單詞的k向量的點積,並且應用點積公式:
這意味著方向越相似,長度越長,點積越大。這個詞和它的關系越大,我們理解這個詞時得到的關註就越大,這和我們的初衷是壹樣的。
我們先來看看開頭的結構圖。每個編碼器模塊都經過壹個add & amp;進入下壹個區塊前的規範層。所以讓我們來看看這地板做了什麽。
Add其實是壹個殘差連接,把輸出加到輸入上,會在每個塊的自註意和FFN之後,再跟壹個層範數。
Norm是壹個層norm化,它將被正則化,即它將被縮放到壹個均值為0、方差為1的域。因為
但壹般在這壹層之前,會有壹個脫落層。
每個編碼器模塊由多頭加法器組成;標準前饋網絡加法和加法。規範就是這樣壹個過程。我們來介紹壹下這個前饋網絡。
這是壹個全連通層,包含兩個線性變化和壹個非線性函數(實際上壹般是ReLu)。
對於輸入(大小),通過權重矩陣(大小)和偏移線性變換變換到隱層(大小),然後激活**ReLu **,記錄下來再通過權重矩陣(大小)和偏移線性變換變換到輸出層(大小),用數學公式表示:
在最後壹個編碼器模塊輸出後連接到解碼器。
解碼器和編碼器結構相似,但視覺信息不同。
Transformer解決了翻譯的問題。要將壹個句子翻譯成另壹種語言,我們希望模型能夠捕捉輸入句子中單詞之間的關系,並將輸入句子中包含的信息與每壹步的翻譯內容結合起來。繼續上面的例子,我們的目標是將壹個句子從英語翻譯成西班牙語,這是我們獲得的序列標記:
讓我們像以前壹樣看看輸入和輸出數據是如何流動的。
這是我們解碼器的輸入標簽:
這是解碼器的預期輸出:
但是,這裏有壹個問題。比如在輸入端,我們看到過' como '後面跟著' estas ',然後用它來預測' estas ',這顯然是不合理的,因為模型在測試的時候是看不到後面的單詞的。
所以我們需要修改註意層,讓模型看不到預測詞右邊的信息,同時可以使用預測詞左邊的信息。
繼續上面的例子,我們將輸入標簽轉換成矩陣形式並添加位置信息:
像編碼器壹樣,解碼器塊的輸出將是大小的矩陣。激活逐行線性變換+softmax後,將生成壹個證明,其中每行中最大的元素代表下壹個單詞。也就是說,分配”
但是,當我們使用多頭註意力機制時,所有的線都會相互作用,所以我們需要在輸入時添加壹個遮罩,這將在註意力計算後完成:
這是自我關註的計算結果:
然後我們在此基礎上添加蒙版,即矩陣上所有三角形的位置都設置為:
然後,在softmax激活後,矩陣變成:
就為了滿足我們的要求,右邊需要在訓練中忽略的單詞的註意力全部變成0。
當這個註意力矩陣乘以,預測的詞是模型可以訪問右邊的元素。註意這裏的多頭註意力輸出會是多維的,因為它的序列長度是。
這是來自目標序列的解碼器的輸入,它是通過改變掩蔽的多頭註意力而獲得的。解碼器的部分輸入來自通過編碼器的源語句的最終輸出(大小為)。
接下來是和編碼器壹樣的多頭註意力添加和層範數->;FFN的過程。
然而,現在來自,而是來自:
在計算了每個查詢相對於關鍵字的關註度之後,我們得到了壹個新的矩陣,並繼續我們的例子。例如,註意力矩陣是:
從上圖可以看出,這個註意力是當前解碼器輸入和編碼器輸出的每個字之間的註意力。我們把這個矩陣相乘得到壹個新的矩陣,每壹行代表源句相對於當前輸入詞匯的特征:
h頭被連接,大小變成,並且它通過權重矩陣被線性地轉換成1的輸出。
經過多重解碼,最終輸出矩陣通過乘以權重矩陣()進行線性變換,然後變換每壹行的向量softmax,其中值最大的位置對應的詞庫索引的詞就是預測詞。
如果丟失,只需要用每個預測詞向量和真實詞的壹熱詞表示計算交叉熵。