編者按git
深度遷移學習是基於深度神經網絡的遷移學習方法,BERT經過預訓練模型達到深度遷移學習的效果,自從2018年末BERT橫空出世以來,就以勢不可擋的姿態橫掃了衆多榜單,甚至在閱讀理解任務SQuAD 中超越人類水平。BERT在公檢法、媒體出版、軍工、快消零售等工業界也迅速落地,如百分點智能對話系統、百分點智能審校系統和百分點智能翻譯系統等。BERT幾乎在全部的下游任務中效果都得到了明顯提高,BERT自此開創了一個NLP的新時代,那就是pre-train + fine-tuning的時代。github
基於BERT的各類改進版預訓練模型層出不窮,使人眼花繚亂,彷佛一不當心就會落伍。可是萬變不離其宗,只要掌握了一些最基本的的思想、技術,就能讓本身緊跟大神們的腳步,讓更優秀的算法模型在工業界持續落地。百分點認知智能實驗室梳理了以BERT爲表明的基於fine-tuning模式的深度遷移學習中一些疑難問題,整理出18個典型的問題,對理解BERT論文和源代碼有明顯的幫助,所以分享給你們。算法
本文做者:崔丙劍 蘇海波api
基本概念網絡
1.如何正確理解深度遷移學習?機器學習
答:遷移學習是機器學習的一個重要分支,是指利用數據、任務、或模型之間的類似性,將在源領域學習過的模型,應用於新領域的一種學習過程。ide
圖1: 遷移學習示意圖函數
遷移學習主要有幾種形式:基於樣本的遷移、基於特徵的遷移、基於模型的遷移和基於關係的遷移。重點說下基於模型的遷移,其基本思想是指從源域和目標域中找到他們之間共享的參數信息,以實現遷移。性能
圖2: 基於模型的遷移學習學習
深度遷移學習主要就是模型的遷移,一個最簡單最經常使用的方法就是fine-tuning,就是利用別人已經訓練好的網絡,針對目標任務再進行調整。近年來大火的BERT、GPT、XLNET等都是首先在大量語料上進行預訓練,而後在目標任務上進行fine-tuning。
答:特徵提取(Feature-extract):特徵提取是使用以前訓練好的模型對新的樣本生成特徵向量,而後將這些特徵做爲task-specific模型的輸入,訓練新的模型參數。好比BERT就是以前學好的模型,把一個句子輸入到BERT,能夠獲得這個句子的向量表示,而後將這個向量做爲後續的好比分類模型的輸入,在訓練的過程當中只訓練後面的分類模型,BERT的輸出僅僅是做爲分類模型的輸入特徵。
模型微調(Fine-tuning):不一樣於特徵提取的方式要另起竈爐針對具體任務設計新的模型,模型微調是直接使用已訓練好的模型,針對當前的任務對輸出層簡單修改,而後在當前任務的數據上進行訓練,對部分網絡層的參數進行微調,讓模型更適合當前的任務。這種模型微調的方式能充分利用深度神經網絡強大的泛化能力,還避免了設計新的的模型,無需從頭開始訓練,能達到更快的收斂速度和更好的效果。
模型輸入
答:BERT embedding layer有三個輸入,分別是token-embedding、segment-embedding和position-embedding。
Token-embedding:將單詞轉換爲固定維的向量表示形式,在BERT-base中,每一個單詞都表示爲一個768維的向量。
Segment-embedding:BERT在解決雙句分類任務(如判斷兩段文本在語義上是否類似)時是直接把這兩段文本拼接起來輸入到模型中,那麼模型是如何區分這兩段文本呢,答案就是經過segment-embedding。對於兩個句子,第一個句子的segment-embedding部分全是0,第二個句子的segment-embedding部分全是1。
Position-embedding:BERT使用transformer編碼器,經過self-attention機制學習句子的表徵,self-attention不關注token的位置信息,因此爲了能讓transformer學習到token的位置信息,在輸入時增長了position-embedding。
答:三個向量是相加後做爲第一層transformer的輸入,三個向量的維度都是768。Pytorch版BERT-embedding具體實現代碼以下,從中咱們能夠明顯看出是相加的關係。
圖3: BERT embedding層源碼
答:BERT論文中做者對此沒有說明緣由,不過能夠從如下幾點進行分析:
a) 用於機器翻譯的平行語料有限,transformer那篇論文在作機器翻譯任務時沒有像如今訓練BERT⼀樣海量的訓練數據,因此即便⽤了learned-position-embedding也未必可以學到⼀個好的表⽰。⽽BERT訓練的數據⽐transformer⼤的多,所以可讓模型⾃⼰去學習位置特徵。
b) 對於翻譯任務,encoder的核⼼任務是提取完整的句⼦語義信息,無需特別關注某個詞的具體位置。而BERT在作下游的序列標註類任務時須要確切的位置信息,模型須要給出每一個位置的預測結果,所以BERT在預訓練過程當中須要建模完整的詞序信息。
答:先說爲何這麼作,若是以傳統的方式進行分詞,因爲單詞存在時態、單複數等多種變化會致使詞表很是大,嚴重影響訓練速度,而且即便一個很是大的詞表仍沒法處理未登陸詞(OOV, Out Of Vocabulary),影響訓練效果。而若是以character級別進行文本表示粒度又太細。Subword粒度在word與character之間,可以較好的解決上述分詞方式面臨的問題,已成爲了一個重要的NLP模型性能提高方法。Subword的實現方式主要有wordpiece和BPE(Byte Pair Encoding),BERT使用了wordpiece方式。
Wordpiece的功能:Wordpiece能夠理解爲把⼀個單詞再拆分紅subword,好比"loved","loving", "loves"這三個單詞,其實本⾝的語義都是「愛」,可是若是以單詞爲單位,那這些詞就算是不⼀樣的詞。Wordpiece算法可以把這3個單詞拆分紅"lov", "#ed", "#ing", "#es"幾部分,這些單詞都有一個共同的subword「lov」,這樣能夠把詞的本⾝的意思和前綴、後綴分開,使最終的詞表變得精簡,而且寓意也能更清晰。
答:可能不少人沒思考過這個問題,雖然在上一個問題中咱們已經知道wordpiece會把單詞拆分紅subword,可是能拆分的前提是有一個subword詞彙表。這個問題中咱們就來詳細看下這個subword詞彙表的生成方法。
將wordpiece詞彙表生成以前咱們仍是先看下BPE詞彙表是怎麼生成的,由於二者很是類似。
BPE詞彙表生成算法以下:
a) 準備訓練語料用於生成subword詞表,須要量足夠大;
b) 預設定好指望的subword詞表的大小;
c) 將單詞拆分爲字符序列並在末尾添加後綴「 </ w>」,統計單詞頻率,例如「 low」的頻率爲5,那麼咱們將其改寫爲「 l o w </ w>」: 5。這一階段的subword的粒度是單字符;
d) 統計連續字節對出現的頻率,選擇頻率最高的合併成新的subword;
e) 重複第4步,直到subword詞表大小達到第2步設定的值,或下一個最高頻的字節對出現頻率爲1。
下邊來看一個例子:假設咱們的訓練語料爲:
lower出現2次,newest出現6次,widest出現3次,low出現5次
根據上述第3步的操做能夠處理成以下格式:
{'l o w e r </w>': 2, 'n e w e s t</w>': 6, 'w i d e s t </w>': 3, 'l o w </w>': 5}
其中的key是詞表中的單詞拆分紅字母,末尾添加後綴「</w>」,value表明單詞出現的頻率。此時初始的詞表中是訓練語料中全部單詞的字母集合,大小爲10,以下表:
[l, o, w, e, r, n, s, t, i, d]
咱們設定最終的詞表大小爲18,而後開始整個算法中最重要的是第4步,過程以下:
原始詞表: {'l o w e r </w>': 2, 'n e w e s t </w>': 6, 'w i d e s t </w>': 3, 'l o w </w>': 5}
出現最頻繁的序列: ('s', 't') 9
將」st」加入詞表,第1次循環結束,此時詞表大小爲11;
合併最頻繁的序列後的詞表: {'n e w e st </w>': 6, 'l o w e r </w>': 2, 'w i d e st </w>': 3, 'l o w </w>': 5}
出現最頻繁的序列: ('e', 'st') 9
將」est」加入詞表,第2次循環結束,此時詞表大小爲12;
合併最頻繁的序列後的詞表: {'l o w e r </w>': 2, 'l o w </w>': 5, 'w i d est </w>': 3, 'n e w est </w>': 6}
出現最頻繁的序列: ('est', '</w>') 9
將「est</w>」加入詞表,第3次循環結束,此時詞表大小爲13;
合併最頻繁的序列後的詞表: {'w i d est</w>': 3, 'l o w e r </w>': 2, 'n e w est</w>': 6, 'l o w </w>': 5}
出現最頻繁的序列: ('l', 'o') 7
將「lo」加入詞表,第4次循環結束,此時詞表大小爲14;
合併最頻繁的序列後的詞表: {'w i d est</w>': 3, 'lo w e r </w>': 2, 'n e w est</w>': 6, 'lo w </w>': 5}
出現最頻繁的序列: ('lo', 'w') 7
將「low」加入詞表,第5次循環結束,此時詞表大小爲15;
合併最頻繁的序列後的詞表: {'w i d est</w>': 3, 'low e r </w>': 2, 'n e w est</w>': 6, 'low </w>': 5}
出現最頻繁的序列: ('n', 'e') 6
將「ne」加入詞表,第6次循環結束,此時詞表大小爲16;
合併最頻繁的序列後的詞表: {'w i d est</w>': 3, 'low e r </w>': 2, 'ne w est</w>': 6, 'low </w>': 5}
出現最頻繁的序列: ('w', 'est</w>') 6
將「west</w>」加入詞表,第7次循環結束,此時詞表大小爲17;
合併最頻繁的序列後的詞表: {'w i d est</w>': 3, 'low e r </w>': 2, 'ne west</w>': 6, 'low </w>': 5}
出現最頻繁的序列: ('ne', 'west</w>') 6
將「newest</w>」加入詞表,第8次循環結束,此時詞表大小爲18,整個循環結束。
最終咱們獲得的詞表爲:
[l, o, w, e, r, n, s, t, i, d, st, est,est</w>, lo, low, ne, west</w>, newest</w>]
Wordpiece與BPE稍有不一樣,主要區別在於BPE是經過最高頻率來肯定下一個subword,而wordpiece是基於機率生成新的subword,另外一個小的區別是wordpiece後綴添加的是「##」而不是「<\w>」,整個算法過程以下:
a)準備訓練語料用於生成subword詞表,須要量足夠大;
b)預設定好指望的subword詞表大小;
c)將單詞拆分爲字符序列並在末尾添加後綴「##」;
d)從全部可能的subword單元中選擇加入語言模型後能最大程度地增長訓練數據機率的組合做爲新的單元;
e)重複第4步,直到subword詞表大小達到第2步中設定的值,或機率增量低於某一閾值。
答:CLS是classification的縮寫,添加該標誌主要用於句子級別的分類任務。BERT借鑑了GPT的作法,在句子首部增長一個特殊的token「[CLS]」,在NSP預訓練任務中,就取的是「[CLS]」位置對應的最後的隱狀態,而後接一個MLP輸出兩個句子是不是上下句關係。能夠認爲「[CLS]」位置的信息包含了句子類別的重要特徵。同理能夠取「[MASK]」位置的向量用於預測這個位置的詞是什麼。
答:BERT因爲position-embedding的限制只能處理最長512個詞的句子。若是文本長度超過512,有如下幾種方式進行處理:
a)直接截斷:從長文本中截取一部分,具體截取哪些片斷須要觀察數據,如新聞數據通常第一段比較重要就能夠截取前邊部分;
b)抽取重要片斷:抽取長文本的關鍵句子做爲摘要,而後進入BERT;
c)分段:把長文本分紅幾段,每段通過BERT以後再進行拼接或求平均或者接入其餘網絡如lstm。
模型原理
答:在傳統的seq2seq模型中,咱們通常使用RNN或CNN對序列進行編碼,而後採用pooling操做或者直接取RNN的終態做爲輸入部分的語義編碼C,而後把C輸入到解碼模塊中,在解碼過程當中,C對每一個位置的輸出重要程度是一致的,以下圖所示:
圖4: 普通的seq2seq
然而在天然語言中,一個句子中不一樣部分的重要性也是不同的,用RNN或CNN進行句子編碼,並不能學習到這樣的信息。所以出現了attention,顧名思義就是在解碼時能對序列中不一樣位置分配一個不一樣的注意力權重,抽取出更加關鍵和重要的信息,從而使模型作出更好的判斷,就像咱們人在看一個句子時,重點關注的是其中的重要信息,對不重要的信息根本不關心或基本不關心。
圖5: 基於attention的seq2seq
答:mutli-head attention的計算過程以下圖所示:
圖6: Multi-head attention計算過程
輸入向量維度爲768維,通過每一個self-attention後獲得隱層輸出爲64維,而後把12個輸出拼接起來獲得768維的向量。
答:要弄明白爲何這樣構造MLM的訓練數據,咱們須要首先搞明白什麼是MLM、爲何要使用MLM,以及MLM存在哪些問題。
a)爲何使用MLM:傳統的語言模型通常都是單向的,要同時獲取上下文信息的常見作法是分別訓練正向與反向的語言模型,而後再作ensemble,但這種作法並不能充分利用上下文信息。MLM 的意義在於可以真正利用雙向的信息,使模型學習到上下文相關的表徵。具體作法就是隨機屏蔽(mask)輸入文本中的部分token,相似於完形填空,這樣在預測被mask部分的token時就可以同時利用上下文信息。
b)MLM存在問題:因爲預訓練數據中存在「[MASK]」這個token,而在實際的下游任務中對BERT進行fine-tuning時,數據中沒有「[MASK]」,這樣就致使預訓練模型使用的數據和fine-tuning任務使用的數據不一致,會影響fine-tuning的效果。
爲了讓MLM可以學習上下文相關特徵,同時又儘可能避免pre-train和fine-tuning數據不一致的問題,數據處理時就採起題目中策略,具體處理策略和緣由解釋以下:
答:要計算BERT的參數量,首先須要對BERT的結構瞭解的很是清楚,下面咱們就來看下base版BERT 110M的參數究竟是怎麼計算出來的。
圖7: BERT結構圖
a) embedding層的參數
BERT的輸入有三種embedding,以下源碼中所示:
圖8: BERT embedding層源碼
vocab_size=30522,hidden_size爲768,最大位置長度爲512,type_vocab_size=2,所以能夠計算出:
embedding層的參數量 =(30522+512+2)*768=23,835,648
b) multi-headattention的參數
圖9: Self attention計算過程
先來看下multi-head attention的計算過程:embedding層的輸出x分別與三個矩陣WQ、Wk、Wv相乘獲得Q、K、V,再通過右上圖的計算獲得一個self-attention的輸出,12個self-attention的輸出拼接起來獲得,再通過一個線性變換獲得multi-head attention的輸出。
WQ、Wk、Wv的維度均爲76864,head數爲12,線性變換矩陣爲768768,所以能夠計算出:
multi-head的參數量 =76864312+768768=2,359,296
c) 全鏈接層(FeedForward)的參數量
全鏈接層把multi-head attention輸出的維度從768映射到3072又映射到768,公式以下圖所示:
其中W1維度爲7683072,W2維度爲3072768,所以能夠計算出:
全鏈接層的參數量 = 76830722=4,718,592
Base版BERT使用了12層transformer的encoder,所以能夠計算出:
總參數量 = embedding參數量+12(multi-headattention參數量+全鏈接參數量)
=23,835,648+12*(2,359,296+4,718,592)=108,770,304≈110M
答:⾸先這些預訓練任務的訓練數據要能從⽆監督的數據中獲取,這樣才能獲取到海量的訓練數據,符合這⼀條件的任務均可以進⾏嘗試,如百度的ERNIE增長了不少個預訓練任務,相比於原始BERT有了明顯的提高。幾個有表明性的預訓練任務以下:
Knowledge Masking Task:BERT的MLM任務中是對句⼦中單個的token進⾏mask,能夠對於句⼦中的短語和命名實體進⾏mask。
Capitalization Prediction Task:預測單詞是否⼤寫,與其餘詞語相⽐,⼤寫詞語一般具備特定的語義價值。
Token-Document Relation Prediction Task:預測⼀個段落中的某個token是否出如今原始⽂檔的其餘段落中。根據經驗,在⽂檔不一樣部分都出現的單詞一般是⽂檔的關鍵詞,所以這⼀任務能夠在⼀定程度上使模型可以捕獲文檔的關鍵字。
Sentence Distance Task:⼀個學習句⼦間距離的任務,該任務被建模爲⼀個3類分類問題,「0」表示兩個句⼦在同⼀個文檔中相鄰,「1」表示兩個句⼦在同⼀個文檔中,但不相鄰,「2」表示兩個句子來自兩個不一樣的文檔。
模型的進化
15.自迴歸語言模型(AR, Autoregressive LM)與自編碼語言模型(AE, Autoencoder LM)的區別?
答:自迴歸語言模型:根據上文內容預測下一個單詞或者根據下文內容預測上一個單詞,這樣單向的語言模型就是自迴歸語言模型。LSTM、GPT、ELMO都是自迴歸語言模型。自迴歸語言模型的缺點,是不能同時利用上下文信息。
自編碼語言模型:自編碼器是一種經過無監督方式學習特徵的方法,用神經網絡把輸入變成一個低維的特徵,這就是編碼部分,而後再用一個解碼器把特徵恢復成原始的信號,這就是解碼部分。具體到語言模型中,BERT使用的MLM就是自編碼語言模型,對一些token進行mask,而後拿被mask位置的向量(包含了上下文的信息)來預測該位置真正的token。
自編碼語言模型的優勢就是能夠同時利用上下文信息,缺點就是預訓練階段和fine-tuning階段使用的訓練數據不一致,由於fine-tuning階段的數據是不會被mask的。
16.XLNET相對於BERT作了哪些重要改進?
答:BERT的AE語言模型雖然能同時學習上下文信息可是會致使預訓練數據和fine-tuning階段的數據不一致從而影響fine-tuning的效果。而XLNET的思路就是使用AR語言模型,根據上文預測下文,可是在上文中添加了下文信息,這樣既解決了BERT面臨的問題也同時利用了上下文信息。
XLNET改進後的語言模型叫作PermutationLanguage Model(PLM),其重點就是permutation,用一個例子來解釋:對於一個輸入句子X=[x1, x2, x3, x4],咱們但願預測x3,在正常的輸入中經過AR語言模型只能看到x1和x2。爲了在預測x3時能看到x4,XLNET的操做是固定x3的位置,而後把其它的詞進行隨機排列,獲得如:[x4, x1, x3, x2],[x1, x4, x3, x2]等數據,這樣就可使用單向的AR語言模型來學習雙向信息。
這時有人可能就會有疑問:就算訓練時能夠對輸入句子進行排列組合,可是fine-tuning時無法這樣作啊。沒錯,fine-tuning階段確實不能對輸入作排列,只能輸入原始句子,因此XLNET在預訓練階段也是不能顯示地對輸入進行排列的。爲了解決這個問題,XLNET的輸入仍是原始的句子,只不過是在transformer內部利用attention mask來實現的,而無需真正修改句子中詞語的順序。例如原來的句子是X=[x1, x2, x3, x4],若是隨機生成的序列是[x3, x2, x4,x1],但輸入到 XLNET 的句子仍然是[x1, x2,x3, x4],此時設置attention mask以下圖:
圖10: Attention mask示意圖
圖中的掩碼矩陣,白色表示不遮掩,黑色表示遮掩。第 1 行表示 x1 的掩碼,由於x1是句子的最後一個 token,所以能夠看到以前的全部 token [x3,x2,x4];第2行是x2的掩碼,由於x2是句子的第二個token,因此能看到前一個token x3;第3行、第4行同理。這樣就實現了儘管當前輸入看上去仍然是[x1, x2, x3, x4],可是已經改爲排列組合的另一個順序[x3, x2,x4, x1]了。若是用這個例子用來從左到右訓練LM,意味着當預測x2的時候,它只能看到上文x3;當預測x4的時候,只能看到上文x3和x2,……
17.RoBERTa相對於BERT作了哪些重要改進?
答:RoBERTa相對於BERT在模型結構上並無改變,改進的是預訓練方法,主要改進有如下幾點:
a) 靜態mask變爲動態mask
BERT MLM任務中,有15%的樣本在預處理階段會進行一次隨機mask,具體的mask方式參考問題12,而後在整個訓練過程當中,這15%的被mask的樣本其mask方式就再也不變化,也不會有新的被mask樣本,這就是靜態mask。
RoBERTa採用了一種動態mask的方式,它並無在預處理的時候對樣本進行mask,而是在每次向模型提供輸入時動態生成mask,因此訓練樣本是時刻變化的,而且實驗代表這種動態mask的方式要比BERT原始的靜態mask效果要好。
b) 去除NSP任務
不少實驗代表NSP任務的沒多大意義,RoBERTa中去除了該任務,不過在生成數據時也作了一些改進,原始的BERT中是選擇同一篇文章中連續的兩個句子或不一樣文章中的兩個句子,而RoBERTa的輸入是連續的多個句子(總長度不超過512)。
c) 更多的數據、更大的mini-batch、更長的訓練時間
BERT base的訓練語料爲13G,batch-size爲256,而RoBERTa的訓練語料擴大了10到130G,訓練中batch-size爲8000,實爲大力出奇跡的傑出表明。
18.ALBERT相對於BERT作了哪些重要改進?
答:ALBERT是一個精簡的BERT,參數量獲得了明顯的下降,使得BERT的大規模應用成爲可能。相對於BERT,ALBERT主要有三點改進:
a) Embedding matrix因式分解
在BERT、XLNET等模型中,embedding的維度 E 和隱藏層維度 H 是相等的,都是768,V是詞表的大小通常的3萬左右。從建模的角度來講,embedding層的目標是學習上下文無關的表示,而隱藏層的目標是學習上下文相關的表示,理論上來講隱藏層的表述包含的信息應該更多一些,所以應該讓H>>E。若是像BERT那樣讓E=H,那增大H以後,embedding matrix大小V*H會變的很大。
ALBERT採起因式分解的方式來下降參數量,先將單詞映射到一個低維的embedding空間,而後再將其映射到高維的隱藏空間,讓H>>E,這樣就能夠把embedding matrix的維度從O(VH)減少到O(VE+E*H),參數量減小很是明顯。
b) 跨層權重共享
Transformer參數共享能夠只共享全鏈接層、只共享attention層,ALBERT結合了這兩種方式,讓全鏈接層與attention層都進行參數共享,也就是說共享encoder內的全部參數,採用該方案後效果降低的並很少,可是參數量減小了不少,訓練速度也提高了不少。此外實驗還代表ALBERT每一層的輸出embedding相比於BERT來講震盪幅度更小一些,能夠增長模型的魯棒性。
c) 修改預訓練任務NSP爲SOP
一些研究代表BERT的NSP並不適合用於預訓練任務,緣由多是負樣原本源於不一樣的文檔,模型在判斷兩個句子的關係時不只考慮了兩個句子之間的連貫性,還會考慮兩個句子的話題,而兩篇文檔的話題一般不一樣,模型可能更多的經過話題去分析兩個句子的關係,而不是連貫性,這使得NSP任務變的相對簡單。
ALBERT中設計了SOP(Sentence-orderprediction)任務,其正樣本選取方式與BERT一致(來自同一文檔的兩個連續句子),而負樣本也一樣是選自同一文檔的兩個連續句子,但交換了兩個句子的順序,從而使模型能夠更多地建模句子之間的連貫性而不是句子的話題。
參考文獻:br/>1.http://jd92.wang/assets/files/transfer_learning_tutorial_wjd.pdf
2.https://jalammar.github.io/illustrated-transformer/
3.https://medium.com/@_init_/why-BERT-has-3-embedding-layers-and-their-implementation-details-9c261108e28a
4.https://medium.com/@makcedward/how-subword-helps-on-your-nlp-model-83dd1b836f46
5.BERT Explained: State ofthe art language model for NLP.
https://towardsdatascience.com/BERT-explained-state-of-the-art-language-model-for-nlp-f8b21a9b6270
6.https://zhuanlan.zhihu.com/p/70257427
7.https://arxiv.org/pdf/1706.03762
8.https://arxiv.org/pdf/1906.08237
9.https://arxiv.org/pdf/1907.11692
10.https://arxiv.org/pdf/1909.11942
11.https://arxiv.org/pdf/1905.07129