深度學習之文本分類模型-基於transformer

1、transformer

transformer就是大名鼎鼎的論文《Attention Is All You Need》[1],其在一些翻譯任務上獲得了SOTA的效果。其模型整體結構如下圖所示

  • encoder和decoder
    其整體結構由encoder和decoder組成,其中encoder由6個相同的block組成,每個block由相同的結構組成,都包括一個muti_head self-attention結構和全連接組成,在這兩個子層的輸出,都含有一個BN標準化。在decoder階段,也是由相同的6個block組成,其在encoder結構的基礎上又加入了一個子層,目的是爲了和encoder的輸出做操作。
  • muti_head self-attention
    這裏多頭的意思就是將我們原本的輸入詞向量在維度上進行切分,假如我們的輸入的詞向量維度是[512,10,300],假設我們的頭的個數是10個,那麼將向量經過轉換,轉成[512,10,10,30]的向量,我們這裏以一個頭舉例,同時,只取一條數據,即向量爲[10,30]那麼這裏回通過一個全連接操作,得到Q,K,V向量,這裏Q,K,V向量的維度均爲[10,30],對於10個頭來說,我們會獲得10個這樣的Q,K,V。接下來進行如下操作

\[ Attention(Q,K,V) = softmax(\frac {QK^{T}}{\sqrt{d_{k}}}) V \]

這裏,d_{k}就是30,最終,我們會得到[10,30]的向量,首先,\(QK^{T}\)的乘積是爲了得到這10個單詞在自己的10個單詞的權重,所以維度爲[10,10],除以\(\sqrt{d_{k}}\),論文中說是猜測如果\(d_{k}\)過大,會導致在softmax求梯度的時候梯度過小,論文中還舉了個栗子,比如兩個以正太分佈均值=0,方差爲1的向量[10,30],[10,30],那麼再進行向量乘法操作後,得到的就是均值=0,方差爲30的向量。

最後得到輸出後,將向量進行拼接,再加上一個全連接操作,即可得到一個block的輸出。

  • Positional Encoding
    論文中介紹了一種假如positional encodeing的方法

    其中,pos爲單詞在句子中的位置,這裏pos取1-10,\(d_{model}\)表示向量的維度,以上面的栗子爲例,就是300,\(i\)表示第幾個位置,這裏i取值1-300

2、GPT

GPT是由openAI提出的一種算法思想[2],其主要思想是通過在大規模的預料上進行模型的訓練,然後在特定任務上進行爲調。所以其總體思想分爲無監督的訓練和有監督的微調。

  • 無監督的訓練
    無監督的訓練是指我們首先對模型用大規模的語料進行訓練,得到相應的參數。比如我們常用的word embedding,固定在輸入向量,然後隨着模型一起訓練的過程。在本論文中,用的是transformer模型作爲預訓練模型,其公式如下

    在第一個式子中,\(U\)代表輸入的單詞token,\(W_{e}\)代表單詞的詞向量,\(W_{p}\)代表位置向量。第二個式子中,我們將向量加和作爲輸入,經過transformer模型,最終得到輸出\(h_{l}\)。最後對於輸出層,加上一個全連接然後接一個softmax層,得到每個單詞在相應位置的概率,其中,對於一條輸入,均含有其對應的上下文單詞,我們在softmax最大化這個單詞所在節點的概率即可。

  • 有監督的微調
    當我們用大量的語料進行模型的訓練後,就會得到相應模型的參數,接着,我們可以用我們的特定任務在這個模型參數的基礎上進行訓練,以一些分類任務爲例,這裏我們將transfomer的輸出加上一個softmax層,最終輸出的節點個數即爲類別標籤的個數。在論文中微調損失函數既有分類標籤的的損失,也有預訓練中損失,所以最終的損失函數是兩者的加和。這裏分類的損失可以理解,但是預訓練中的損失是什麼?他的上下文輸出的單詞是什麼?這裏我的理解是對於一個句子依舊給他一個窗口,然後類似於word2vec,其中一個損失是預訓練的損失,另一個損失是對於標籤分類的損失。如下公式所示,\(L_{2}(C)\)是分類的損失,\(L_{1}(C)\)是預訓練的損失,在這裏,我們可以對預訓練的損失設定權值。

  • 總體架構圖
    總體架構圖如下所示,這裏我們看到,對於不同的任務的微調,有不同的處理方法,對於分類任務,我們直接輸入相應的句子,在輸出層加上一個softmax,對於一些句子對輸入的任務,我們利用一些相應的標記,進行拼接,最終輸出也是用softmax進行分類。

3、bert

bert是由Google的一些研究者們提出的一種算法[3],其沿用了GPT的用大規模的語料進行預訓練,然後在下游任務進行微調的方式,其中預訓練的基礎模型依然用的是transformer模型,bert在embedding層用了三種方式的embedding累加,並且提出了雙向的語言模型,這比GPT的單向語言模型更能學到語義的信息。並且加入了next sentence prediction方式作爲loss的一部分,最終在多個任務上達到了sota的效果。

  • input embedding
    輸入的embedding有三種方式組成,第一種就是我們的單詞embedding,假設輸入的句子序列,經過編碼是[3,5,7,8,4,5,4],詞典的大小爲N,向量的維度爲d,那麼第一個token embedding爲[7,d]的向量。第二個是sentence embedding,出現這個的原因是如果輸入的句子如果是兩個的話,那麼我們分別用0表示第一條句子,用1表示第二條句子,比如這兩條句子組合之後分別是[0,0,0,0,1,1,1],sentence embedding的維度是[2,d],最終,經過embedding,得到[7,d]的矩陣表示,其中前4條向量相同,後3條向量相同。第三個是position embedding,即位置的embedding,假設句子的最大長度爲128,那麼會生成一個[128,d]的矩陣,原始數據的位置表示爲[0,1,2,3,0,1,2],這樣我們得到各自位置上的句子表示,最終也爲[7,d]。最後,我們將這三個向量進行相加得到輸入的embedding。結構如下圖所示
  • 輸入的標記
    在bert種,爲了區分兩條句子,用[CLS]表示所有句子的開頭,用[SEP]來分隔兩個句子,則我們得到的輸入爲[[CLS],3,5,7,8,[SEP],4,5,4[SEP]]這樣的輸入形式。
  • Masked LM
    Masked LM是爲了解決語言模型單向訓練的問題,首先,將訓練數據中80%的單詞用mask表示,將10%的單詞用該句子中隨機的單詞來代替,另外10%保持不變。在輸出層的時候,我們用這些被mask和被替代的單詞來預測原始的單詞,最終算得損失函數。比如我們的輸入可能會變成
    [[CLS],[MASK],5,8,8,[SEP],4,[MASK],4[SEP]]
  • next sentence predition
    如上所述,在預訓練的時候,我們會輸入兩個句子,但正常情況下我們只有一個句子,那麼如何進行構造呢?我們會將一個完整的句子進行分割成2個部分,第二個部分以50%的概率隨機替換爲其他的句子,如果替換了,那麼is_next爲0,否則爲1。在最終的輸出層,我們會構造兩個輸出節點,類似於二分類,來預測這兩個句子是否是同一個句子中的句子。從而計算損失函數,最終的損失函數爲Masked LM損失函數兩者的和。
  • 微調
    當我們用大規模的語料訓練好bert模型後,可以根據自己下游的業務繼續進行訓練。

4、RoBERTa

該論文是由fb和華盛頓大學聯合提出的一種方法[4],這篇文章的創新點不多,更像是對BERT的進一步煉丹,通過調整一些參數,步長等,最終在多個任務中取得了SOTA的效果,所以說,如果丹煉的好,相同的模型,也可以超過之前的效果。RoBERTa主要實驗調優的方面有:1、增大訓練數據集,增大batch,增大epoch。2、將static masked LM 換成dynamic masked LM。3、去掉NSP。4、用字節代替字符。

  • 增大訓練數據集,增大batch,增大epoch
    RoBERTa使用更多的數據集,總計160G,其中包括BOOKCORPUS(16G),CC-NEWS(過濾後76G),OPENWEBTEXT(38G),STORIES(31G)。

    原始bert用的是batch_size爲256,steps爲1M,RoBERTa用了兩組,一組是batch_size爲2k,steps爲125k,另外一組是batch_size爲8k,steps爲31k

    增大之後的效果如下圖所示,可以看到,效果雖有提升,但是整體一般。
  • 將static masked LM 換成dynamic masked LM
    原始的MLM首先在線下用create pretraing腳本得到相應的訓練數據,RoBERTa是在輸入的時候對數據進行動態mask,效果如下。整體看來,效果也比較的一般,提升有限。因爲這裏其實動態的輸入和靜態數據其實基本上原理是一樣的,所以並沒有提升太多的效果。
  • 去掉NSP
    這裏的實驗結果表明,不使用NSP的效果要優於使用NSP(這裏倒還是挺令人意外的)
  • 用字節代替字符
    原始的bert是用字符作爲輸入,RoBERTa使用字節,這裏會使整體詞表的數量增大,但是提升效果一般,就不上圖了。

5、ALBERT

ALBERT依舊是Google提出的一種算法[5],其在原始Bert的基礎上進行了優化,主要是爲了解決Bert的參數量大,訓練時間長的問題,其主要有三點創新:1、對輸入的embedding進行因式分解。2、層間權重共享。3、損失函數將NSP替換爲SOP。

  • 輸入embedding因式分解
    輸入層embedding因式分解是這樣一種思想,通常的Bert的embedding向量E和隱藏層H是相等的,假設我們的單詞個數是V,則我們的embedding的參數量爲V * E,以bert_large爲例,V=30000,H=E=4096,那麼在優化時需要優化的參數量爲30000 * 4096 = 1.23億。在Albert中,將輸入的embeding分成兩個部分,V * E 和 E * H的向量,其中E遠遠小於H,這裏的E爲128,則H爲4096,則參數量爲30000 * 128 + 128 * 4096 = 436萬,原始Bert的參數量是Albert的28倍。

    下面依據論文中的描述,從模型角度和實際角度分析這種做法的可行性

    模型角度來看,V * E是詞向量的表示,其不涉及詞與詞之間的相關關係,也就是說每個單詞的embedding是相互獨立的,而E * H這個向量則含有了詞與詞之間的相關信息,所以可以將兩者分離開。

    實際角度來看,就是我們上文所說的參數量的減少,通過比較,的確可以有效的減少參數的數量。

  • 層間權重共享
    層間權重共享表示的是每個transformer模塊的參數是共享的,並且通過實驗的比較,發現層間權重共享可以有效的減少震盪,如下圖所示。其中藍線爲Albert的結果,紅色虛線爲Bert的實驗結果。

  • 損失函數將NSP替換爲SOP
    論文中講述了在單個任務中,NSP可以進行主題預測和連貫性預測,NSP的主題預測其實和MLM的效果有一定的衝突,所以作者用SOP代替NSP,NSP是進行兩個句子的構造,正例的構造方法是選擇一個句子,並將該句子所在句子的後一句作爲第二個句子。負例選擇的方法是選擇一個句子,並隨機選擇另一個文檔的一個句子。在輸出時判斷這兩個句子是否屬於同一個句子,類似於一個二分類。SOP的同樣是進行兩個句子的構造,正例的構造方法和NSP一樣,負例的構造方法是將正例中的兩個句子調換個位置。

6、spanBert

spanBert是由華盛頓大學,fb等聯合提出的一種改進bert的方法,其中它在三個方面進行的改進:1、將token mask改成span mask。2、損失函數加上SBO損失。3、去掉NSP。

  • 將token mask改成span mask
    我們知道,原生bert用的是單字進行輸入,但是有些情況下,一個單詞是最小單元,比如"Denver Broncos"是NFL的一個隊伍,所以正常來說將這個單詞全部mask會是比較合理的。如下圖所示,在這幅圖中,將"an American football game"作爲整體mask,這也是爲啥叫span的思想。
  • 損失函數加上SBO損失
    還如上圖所示,損失函數中除了原生bert中自帶的\(L_{MLM}(football | x_{7})\),還有SBO損失\(L_{SBO}(football | x_{4},x_{9},p_{3})\),這三個數是怎麼得來的呢,假定這個句子爲\(x_{1},x_{2}.....x_{n}\)這裏n=12,\((x_{s},x_{e})\)表示被mask的集合,這裏s=5,e=8,可以用以下公式得到結果。這裏i=7,所以根據公式計算得到\(x_{4},x_{9},P_{3}\)

\[ y_{i} = f(x_{s-1},x_{e+1},P_{i-s+1}) \]
  • 去掉NSP
    作者認爲NSP會使效果不好,所以去掉了,原文中的兩個句子也變成了單個句子。

7、xlnet

xlnet是由卡內基梅隆大學和Google大腦聯合提出的一種算法,其沿用了自迴歸的語言模型,並利用排列語言模型合併了bert的優點,同時集成transformer-xl對於長句子的處理,達到了SOTA的效果。

  • AR和AE
    AR表示自迴歸語言模型,自迴歸語言模型可以理解爲單向的語言模型,即通過上文或者是下文預測當前單詞,比較有代表性的是GPT,elmo等。AE是自編碼語言模型,其通過上下文來預測當前單詞,比較有代表性的是bert,利用masked LR,使得上下文單詞可以預測當前單詞,但是bert的這種方法有一個問題,就是在微調階段,文本沒有辦法進行masked,這樣會造成一定的性能損失。所以,xlnet就提出了一種排列語言模型,這種模型集成了AR和AE的優點。
  • 排列語言模型
    一個簡單和直觀的想法是,我們將輸入的token進行隨機排列,然後輸入到模型中,這樣模型不久可以學習到上下文的信息了麼,但是這種方法有兩個問題:1、選擇多少個排列組合進行輸入呢,要知道,對於輸入個數爲T的單詞,其排列組合T!,那我們如何取捨?2、對於微調階段來說,我們也不可能將輸入的序列進行多次排列吧,這個如何解決?第一個問題很好解決,乾脆隨機抽取一部分就行。第二個問題解決起來比較麻煩,那麼xlnet用了一種attention mask的方式,解決了這個問題,同時,還無需改變輸入序列的順序。

    上圖表示用兩種不同的輸入流,分別是query stream和content stream,其中有兩種不同的mask方式,既然我們無法改變輸入的順序,那麼我們可以通過相應的mask方式來達到相應的效果,對於上圖來說,原始的輸入是x1,x2,x3,x4,但是我們又想達到x3,x2,x4,x1的效果,怎麼辦呢?對於序列x3,x2,x4,x1來說,x3看不見任何東西,x2可以看到x3,x4可以看到x3,x2,x1可以看到x3,x2,x4,那麼寫成mask矩陣的形式就是如右上角的那個圖,我們可以對輸入的矩陣做一個處理,讓相應的單詞看不見其他的單詞的方式,就可以達到這種效果。
  • 集成Transformer-XL
    對於過長序列,如果分段來進行處理,往往會遺漏信息,且效果會下降,那麼xlnet借鑑了Transformer-XL的思想,設置一個保留上一個片段的信息,在訓練時進行更新。
參考文獻
[1]Ashish Vaswani(2017)Attention Is All You Need.
[2]Alec Radford(2018)Improving Language Understanding by Generative Pre-Training.
[3]Jacob Devlin(2019)BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding.
[4]Yinhan Liu(2019)RoBERTa: A Robustly Optimized BERT Pretraining Approach.
[5]Zhenzhong Lan(2020)ALBERT: A LITE BERT FOR SELF-SUPERVISED LEARNING OF LANGUAGE REPRESENTATIONS.
[6]Mandar Joshi(2020)panBERT: Improving Pre-training by Representing and Predicting Spans.
[7]Zhilin Yang(2019).XLNet: Generalized Autoregressive Pretraining for Language Understanding.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章