NLP自然語言處理:文本表示總結 - 下篇(ELMo、Transformer、GPT、BERT)

上篇:https://blog.csdn.net/qq_35883464/article/details/100042899

再上篇中我們講解了從one-hotGloVe,都是2014年以前比較火的模型。那麼下篇就來探討最近幾年比較火的文本表示,不談具體推導公式(公式可以看一手論文),只談解決了問題和最後結果,按照時間順序和行業發展,詳細講述爲什麼會出現這個模型,這個模型又有什麼缺點,下個模型是如何克服這些缺點的。


文本表示分類(基於表示方法)

  • 離散表示
    • one-hot表示
    • 詞袋模型與TF-ID 
  • 分佈式表示
    • 基於矩陣的表示方法
      • 降維的方法
      • 聚類的方法
    • 基於神經網絡的表示方法
      • NNLM
      • CBOW
      • Skip-gram
      • GloVe
      • ELMo
      • C&W
      • GPT
      • BERT

目錄

一、預訓練

1.1 預訓練在圖像領域的應用

1.2 圖像與NLP的粗略對應關係

二、ELMO:基於上下文的word-embedding

2.1 ELMO感性認識

2.2 ELMO結構

2.2.1 ELMO第一個階段:預訓練

2.2.2 ELMO第二個階段:下游任務

2.2.3 ELMO效果分析

三、GPT: Transformer建模句子信息

3.1 Transformer/self-attention介紹

3.2 GPT介紹

3.2.1 GPT第一階段:預訓練pretrain

3.2.2 GPT第二階段:Fine-tuning

四、BERT:預訓練雙向Transformer

4.1 深層雙向的encoding

4.2 Masked LM

4.3 Encoder:Transformer

4.4 句子級表示

4.4.1 句子級負採樣

4.4.2 句子級表示方法

4.5 下游任務接口

4.6 實驗效果

參考文獻


再上篇我們談到了Word2vec,這個模型的缺點是缺乏了整體文本和當前詞的關係,負樣本採用sample的方式會缺失詞的關係信息。

從而出現了GloVe,增加了全局的信息(共線矩陣),解決了Word2vec的缺點。這就是GloVe出現的原因。

但是還有一個關鍵性問題沒有解決!

就是一次多意的情況,如果文章中出現了Apple,不知道是指科技公司還是水果,但是他們2個的詞向量是一樣的。

如何解決這個問題呢,就引出了下面的話題。


一、預訓練

 

1.1 預訓練在圖像領域的應用

預訓練過程就是做圖像或者視頻領域的一種比較常規的做法,能明顯促進應用的效果。

上圖展示了這個過程,設計好網絡結構以後,對於圖像來說一般是CNN的多層疊加網絡結構,可以先用某個訓練集合比如訓練集合A或者訓練集合B對這個網絡進行預先訓練,在A任務上或者B任務上學會網絡參數,然後存起來以備後用。

假設我們面臨第三個任務C,網絡結構採取相同的網絡結構,在比較淺的幾層CNN結構,網絡參數初始化的時候可以加載A任務或者B任務學習好的參數,其它CNN高層參數仍然隨機初始化。之後我們用C任務的訓練數據來訓練網絡,此時有兩種做法:

一種是淺層加載的參數在訓練C任務過程中不動,這種方法被稱爲“Frozen”;

另外一種是底層網絡參數儘管被初始化了,在C任務訓練過程中仍然隨着訓練的進程不斷改變,這種一般叫“Fine-Tuning”,顧名思義,就是更好地把參數進行調整使得更適應當前的C任務。一般圖像或者視頻領域要做預訓練一般都這麼做。

這麼做的好處:解決了數據量少而要訓練比較深的神經網絡的問題

如果手頭任務C的訓練集合數據量較少的話,現階段的好用的CNN等網絡結構層數很深,幾百萬上千萬參數量算起步價,訓練數據少很難很好地訓練這麼複雜的網絡,但是如果其中大量參數通過大的訓練集合預先訓練好直接拿來初始化大部分網絡結構參數,然後再用C任務手頭比較可憐的數據量上Fine-tuning過程去調整參數讓它們更適合解決C任務,那事情就好辦多了。

 

爲什麼這種預訓練的思路是可行的?

目前我們已經知道,對於層級的CNN結構來說,不同層級的神經元學習到了不同類型的圖像特徵,由底向上特徵形成層級結構。

如上圖所示,如果我們手頭是個人臉識別任務,訓練好網絡後,把每層神經元學習到的特徵可視化肉眼看一看每層學到了啥特徵。

第一個隱層學到的是線段等特徵,第二個隱層學到的是人臉五官的輪廓,第三層學到的是人臉的輪廓,通過三步形成了特徵的層級結構,越是底層的特徵越是所有不論什麼領域的圖像都會具備的(比如邊角線弧線等底層基礎特徵),越往上抽取出的特徵越與手頭任務相關

正因爲此,所以預訓練好的網絡參數,尤其是底層的網絡參數抽取出特徵跟具體任務越無關,越具備任務的通用性,所以這是爲何一般用底層預訓練好的參數初始化新任務網絡參數的原因。而高層特徵跟任務關聯較大,實際可以不用使用,或者採用Fine-tuning用新數據集合清洗掉高層無關的特徵抽取器。

 

1.2 圖像與NLP的粗略對應關係

將圖像和語言中的處理對象做一個不太嚴謹的對應。如下圖所示,大體上像素類似於語言中的字母;圖像中的對象類似於語言中的單詞/概念;圖像中對象組成的場景類似於語言中的句子表達的語義;視頻則類似於語言中的篇章(文章)。

在這種類比下看,NLP在單詞層面的處理要比CV中的圖像識別簡單得多,只需要做一下tokenization、lemmatization、stemming等(中文複雜一些需要額外做自動分詞),就可以利用關鍵詞匹配完成很多任務,例如信息檢索、文本分類、拼寫糾錯、情感分析、關鍵詞提取等等。

而由於圖像中對象的複雜性和多樣性,僅在對象識別層面,甚至特定的人臉識別,還有很多技術挑戰。只不過是近年來,由於深度學習對非結構數據的強大表示和學習能力,開始讓對象識別走向了實用化。而進入到更高層面,例如面向圖像的場景圖構建,面向文本的句法語義分析,都需要對複雜語境(上下文)的精準而強大的建模能力。

 

二、ELMO:基於上下文的word-embedding

剛剛說了預訓練在圖像領域的應用和圖像與NLP的粗略對應關係,既然預訓練可以在圖像領域的應用,也知道了cv和nlp的對應關係,那麼預訓練也可以在nlp領域應用。

 

2.1 ELMO感性認識

ELMO是“Embedding from Language Models”的簡稱,其實這個名字並沒有反應它的本質思想,提出ELMO的論文題目:“Deep contextualized word representation”更能體現其精髓。

在此之前的Word Embedding本質上是個靜態的方式,所謂靜態指的是訓練好之後每個單詞的表達就固定住了,以後使用的時候,不論新句子上下文單詞是什麼,這個單詞的Word Embedding不會跟着上下文場景的變化而改變,這是爲何說它是靜態的,這也是問題所在。

ELMO的本質思想是:我事先用語言模型學好一個單詞的Word Embedding,此時多義詞無法區分。在我實際使用Word Embedding的時候,單詞已經具備了特定的上下文了,這個時候我可以根據上下文單詞的語義去調整單詞的Word Embedding表示,這樣經過調整後的Word Embedding更能表達在這個上下文中的具體含義。

所以ELMO本身是個根據當前上下文對Word Embedding動態調整的思路。

 

2.2 ELMO結構

ELMO採用了典型的兩階段過程:

第一個階段是:利用語言模型進行預訓練。

第二個階段是:在做下游任務時,從預訓練網絡中提取對應單詞的網絡各層的Word Embedding作爲新特徵補充到下游任務中。

 

2.2.1 ELMO第一個階段:預訓練

 

上圖展示的是其預訓練過程,它的網絡結構採用了雙層雙向LSTM,目前語言模型訓練的任務目標:是根據單詞 W_i 的上下文去正確預測單詞 W_i 。

 圖中左端的前向雙層LSTM代表正方向編碼器,輸入的是從左到右順序的除了預測單詞外 W_i 的上文(Context-before);右端的逆向雙層LSTM代表反方向編碼器,輸入的是從右到左的逆序的句子下文(Context-after);每個編碼器的深度都是兩層LSTM疊加。

使用這個網絡結構利用大量語料做語言模型任務就能預先訓練好這個網絡,如果訓練好這個網絡後,輸入一個新句子 Snew ,句子中每個單詞都能得到對應的三個Embedding:

  • 最底層是單詞的Word Embedding,
  • 往上走是第一層雙向LSTM中對應單詞位置的Embedding,這層編碼單詞的句法信息更多一些;
  • 再往上走是第二層LSTM中對應單詞位置的Embedding,這層編碼單詞的語義信息更多一些。

也就是說,ELMO的預訓練過程不僅僅學會單詞的Word Embedding,還學會了一個雙層雙向的LSTM網絡結構,而這兩者後面都有用。

 

2.2.2 ELMO第二個階段:下游任務

上圖展示了下游任務的使用過程,比如我們的下游任務仍然是QA問題,此時對於問句X,步驟如下:

  1. 先將句子X作爲預訓練好的ELMO網絡的輸入,這樣句子X中每個單詞在ELMO網絡中都能獲得對應的三個Embedding,
  2. 給予這三個Embedding中的每一個Embedding一個權重a,這個權重可以學習得來,根據各自權重累加求和,將三個Embedding整合成一個。
  3. 將整合後的這個Embedding作爲X句在自己任務的那個網絡結構中對應單詞的輸入,以此作爲補充的新特徵給下游任務使用。

對於上圖所示下游任務QA中的回答句子Y來說也是如此處理。因爲ELMO給下游提供的是每個單詞的特徵形式,所以這一類預訓練的方法被稱爲“Feature-based Pre-Training”。

 

2.2.3 ELMO效果分析

上圖給了個例子,對於Glove訓練出的Word Embedding來說,多義詞比如play,根據它的embedding找出的最接近的其它單詞大多數集中在體育領域,這很明顯是因爲訓練數據中包含play的句子中體育領域的數量明顯佔優導致;而使用ELMO,根據上下文動態調整後的embedding不僅能夠找出對應的“演出”的相同語義的句子,而且還可以保證找出的句子中的play對應的詞性也是相同的,這是超出期待之處。之所以會這樣,是因爲我們上面提到過,第一層LSTM編碼了很多句法信息,這在這裏起到了重要作用。

ELMO經過這般操作,效果如何呢?實驗效果見上圖,6個NLP任務中性能都有幅度不同的提升,最高的提升達到25%左右,而且這6個任務的覆蓋範圍比較廣,包含句子語義關係判斷,分類任務,閱讀理解等多個領域,這說明其適用範圍是非常廣的,普適性強,這是一個非常好的優點。

 

三、GPT: Transformer建模句子信息

 

3.1 Transformer/self-attention介紹

這裏只是總結,如果你不收悉請看具體介紹:https://blog.csdn.net/qq_35883464/article/details/100181031

Transformer是個疊加的“自注意力機制(Self Attention)”構成的深度網絡。其關鍵是自注意力機制(Self Attention)。所以我們主要介紹self-attention。

當我們想對句子“The animal didn't cross the street because it was too tired”中“it”這個詞編碼時,注意力機制的基本思想是認爲這個句話中每個詞對it的語義均會有貢獻。

那怎麼綜合這些貢獻呢,就是直接將每個詞的embedding向量加權求和。 所以關鍵的問題是如何得到每個詞各自的權重,關係更近的詞的權重更大。比如這句話中"The Animal"的權重就應該更大,它們的信息應該更多地編碼到“it”中。

自注意力機制得到權重的方法非常簡單,就是兩個詞向量(查詢向量鍵向量值向量)的內積。最終通過一個softmax將各個權重歸一化。

在上圖中,顏色的粗細代表該詞的權重大小,權重由該詞與“it”的內積得到,最終通過一個softmax將各個權重歸一化。

自注意力機制其實是最原始意義的卷積的思想的推廣,因爲卷積本身就是一種“加權求和”。

 

3.2 GPT介紹

GPT是“Generative Pre-Training”的簡稱,從名字看其含義是指的生成式的預訓練

GPT也採用兩階段過程:

  • 第一階段是利用語言模型進行預訓練。
  • 第二階段通過Fine-tuning的模式解決下游任務。

 

3.2.1 GPT第一階段:預訓練pretrain

上圖展示了GPT的預訓練過程,其實和ELMO是類似的,主要不同在於兩點:

  1. 特徵抽取器不是用的雙層雙向LSTM,而是用的Transformer,上面提到過它的特徵抽取能力要強於雙層雙向LSTM。
  2. GPT的預訓練雖然仍然是以語言模型作爲目標任務,但是採用的是單向的語言模型,GPT則只採用這個單詞的上文Context-before來進行預測

所謂“單向”是指:語言模型訓練的任務目標是根據 W_i 單詞的上下文去正確預測單詞 W_i , W_i 之前的單詞序列Context-before稱爲上文,之後的單詞序列Context-after稱爲下文。ELMO在做語言模型預訓練的時候,預測單詞 W_i 同時使用了上文和下文,而GPT則只採用這個單詞的上文Context-before來進行預測,而拋開了下文。這個選擇現在看不是個太好的選擇,原因很簡單,它沒有把單詞的下文融合進來,這限制了其在更多應用場景的效果,比如閱讀理解這種任務,在做任務的時候是可以允許同時看到上文和下文一起做決策的。如果預訓練時候不把單詞的下文嵌入到Word Embedding中,是很吃虧的,白白丟掉了很多信息。

 

3.2.2 GPT第二階段:Fine-tuning

上圖展示了GPT在第二階段如何使用。首先,對於不同的下游任務來說,要把任務的網絡結構改造成和GPT的網絡結構是一樣的。

然後,在做下游任務的時候,利用第一步預訓練好的參數初始化GPT的網絡結構,你可以用手頭的任務去訓練這個網絡,對網絡參數進行Fine-tuning,使得這個網絡更適合解決手頭的問題。這有沒有讓你想起最開始提到的圖像領域如何做預訓練的過程對,這跟那個模式是一模一樣的。

這裏引入了一個新問題:對於NLP各種花樣的不同任務,怎麼改造才能靠近GPT的網絡結構呢?

GPT論文給了一個改造施工(Fine-tuning)圖如上,其實也很簡單:

  • 對於分類問題,不用怎麼動,加上一個起始和終結符號即可;
  • 對於句子關係判斷問題,比如Entailment(關係),兩個句子中間再加個分隔符即可;
  • 對於文本相似性判斷問題,把兩個句子順序顛倒下做出兩個輸入即可,這是爲了告訴模型句子順序不重要;
  • 對於多項選擇問題,則多路輸入,每一路把文章和答案選項拼接作爲輸入即可。

從上圖可看出,這種改造還是很方便的,不同任務只需要在輸入部分施工即可。

GPT的效果是非常令人驚豔的,在12個任務裏,9個達到了最好的效果,有些任務性能提升非常明顯。

 

四、BERT:預訓練雙向Transformer

BERT的全稱是Bidirectional Encoder Representation from Transformers。

這篇paper的最重要意義不在於用了什麼模型,也不在於怎麼訓練的,而是它提出一種全新的遊戲規則。

像之前說的,爲每個NLP任務去深度定製泛化能力極差的複雜模型結構其實是非常不明智的,走偏了方向的。既然ELMo相比word2vec會有這麼大的提升,這就說明預訓練模型的潛力遠不止爲下游任務提供一份精準的詞向量,所以我們可不可以直接預訓練一個龍骨級的模型呢?如果它裏面已經充分的描述了字符級、詞級、句子級甚至句間關係的特徵,那麼在不同的NLP任務中,只需要去爲任務定製一個非常輕量級的輸出層(比如一個單層MLP)就好了,畢竟模型骨架都已經做好了嘛。

而BERT正是做了這件事情,或者說,它真的把這件事情做成了,它作爲一個general的龍骨級模型輕鬆的挑戰了11個任務上的深度定製的模型。。。

 

4.1 深層雙向的encoding

首先,它指出,對上下文相關的詞向量的學習上,先前的預訓練模型還不夠!雖然在下游有監督任務中,encoding的方式已經是花裏胡哨非常充分了,深度雙向encoding基本成了許多複雜下游任務的標配(比如MRC, dialogue)。

但是在預訓練模型上,先前的最先進模型也只是基於傳統的語言模型來做,而傳統的語言模型是單向的(數學上已經定義了),即

𝑝(𝑠)=𝑝(𝑤0)⋅𝑝(𝑤1|𝑤0)⋅𝑝(𝑤2|𝑤1,𝑤0)⋅𝑝(𝑤3|𝑤2,𝑤1,𝑤0)…𝑝(𝑤𝑛|𝑐𝑜𝑛𝑡𝑒𝑥𝑡)

而且往往都很淺(想象一下LSTM堆三層就train不動了,就要上各種trick了),比如ELMo。

另外,雖然ELMo有用雙向LSTM來做encoding,但是ELMo兩個方向的LSTM其實是分開訓練的,只是在最後在loss層做了個簡單相加。這樣就導致對於每個方向上的單詞來說,在被encoding的時候始終是看不到它另一側的單詞的。而顯然句子中有的單詞的語義會同時依賴於它左右兩側的某些詞,僅僅從單方向做encoding是不能描述清楚的

 

4.2 Masked LM

顧名思義,Masked LM就是說,我們不是像傳統LM那樣給定已經出現過的詞,去預測下一個詞,而是直接把整個句子的一部分詞(隨機選擇)蓋住(make it masked),這樣模型不就可以放心的去做雙向encoding了嘛,然後就可以放心的讓模型去預測這些蓋住的詞是啥。這個任務其實最開始叫做cloze test(大概翻譯成“完形填空測試”)。

這樣顯然會導致一些小問題。這樣雖然可以放心的雙向encoding了,但是這樣在encoding時把這些蓋住的標記也給encoding進去了,而這些mask標記在下游任務中是不存在的呀。。。那怎麼辦呢?對此,爲了儘可能的把模型調教的忽略這些標記的影響,作者通過如下方式來告訴模型“這些是噪聲是噪聲!靠不住的!忽略它們吧!”,對於一個被蓋住的單詞:

  • 有80%的概率用“[mask]”標記來替換
  • 有10%的概率用隨機採樣的一個單詞來替換
  • 有10%的概率不做替換(雖然不做替換,但是還是要預測哈)

 

4.3 Encoder:Transformer

在encoder的選擇上,作者並沒有用爛大街的雙向LSTM,而是使用了可以做的更深、具有更好並行性的Transformer encoder來做。這樣每個詞位的詞都可以無視方向和距離的直接把句子中的每個詞都有機會encoding進來。

另一方面我主觀的感覺Transformer相比lstm更容易免受mask標記的影響,畢竟self-attention的過程完全可以把mask標記針對性的削弱匹配權重,但是lstm中的輸入門是如何看待mask標記的那就不得而知了。

等下,之前的文章中也說過了,直接用Transformer encoder顯然不就丟失位置信息了嘛?難道作者這裏也像Transformer原論文中那樣搞了個讓人怕怕的sin、cos函數編碼位置?並木有,作者這裏很簡單粗暴的直接去訓練了一個position embedding 這裏就是說,比如我把句子截斷到50的長度,那麼我們就有50個位置嘛,所以就有50個表徵位置的單詞,即從位置0一直到位置49。。。然後給每個位置詞一個隨機初始化的詞向量,再隨他們訓練去吧(很想說這特喵的也能work?太簡單粗暴了吧。。。)。另外,position embedding和word embedding的結合方式上,BERT裏選擇了直接相加。

最後,在深度方面,最終BERT完全版的encoder喪心病狂的疊加了24層的multi-head attention block(要知道對話裏的SOTA模型DAM也才用了5層…)。。。而且每個block包含16抽頭、1024隱單元。

 

4.4 句子級表示

像之前說的,在很多任務中,僅僅靠encoding是不足以完成任務的(這個只是學到了一堆token級的特徵),還需要捕捉一些句子級的模式,來完成SLI、QA、dialogue等需要句子表示、句間交互與匹配的任務。對此,BERT又引入了另一個極其重要卻又極其輕量級的任務,來試圖把這種模式也學習到。

 

4.4.1 句子級負採樣

word2vec的一個精髓是引入了一個優雅的負採樣任務來學習詞向量(word-level representation)。那麼如果我們把這個負採樣的過程給generalize到sentence-level呢?這便是BERT學習sentence-level representation的關鍵啦。

BERT這裏跟word2vec做法類似,不過構造的是一個句子級的分類任務。即首先給定的一個句子(相當於word2vec中給定context),它下一個句子即爲正例(相當於word2vec中的正確詞),隨機採樣一個句子作爲負例(相當於word2vec中隨機採樣的詞),然後在該sentence-level上來做二分類(即判斷句子是當前句子的下一句還是噪聲)。通過這個簡單的句子級負採樣任務,BERT就可以像word2vec學習詞表示那樣輕鬆學到句子表示啦。

 

4.4.2 句子級表示方法

BERT這裏並沒有像下游監督任務中的普遍做法一樣,在encoding的基礎上再搞個全局池化之類的,它首先在每個sequence(對於句子對任務來說是兩個拼起來的句子,對於其他任務來說是一個句子)前面加了一個特殊的token,記爲[CLS],如圖

ps:這裏的[sep]是句子之間的分隔符,BERT同時支持學習句對的表示,這裏是[SEP]便是爲了區分句對的切割點。

然後讓encoder對[CLS]進行深度encoding,深度encoding的最高隱層即爲整個句子/句對的表示啦。這個做法乍一看有點費解,不過別忘了,Transformer是可以無視空間和距離的把全局信息encoding進每個位置的,而[CLS]作爲句子/句對的表示是直接跟分類器的輸出層連接的,因此其作爲梯度反傳路徑上的“關卡”,當然會想辦法學習到分類相關的上層特徵啦。

另外,爲了讓模型能夠區分裏面的每個詞是屬於“左句子”還是“右句子”,作者這裏引入了“segment embedding”的概念來區分句子。對於句對來說,就用embedding A和embedding B來分別代表左句子和右句子;而對於句子來說,就只有embedding A啦。這個embedding A和B也是隨模型訓練出來的。

ps: 這做法跟position embedding一樣感覺簡單粗暴,實在很費解爲什麼BERT用在“quora question pairs”這種理論上需要網絡保持對稱的任務上依然能work,心情複雜

所以最終BERT每個token的表示由token原始的詞向量token embedding、前文提到的position embedding和這裏的segment embedding三部分相加而成,如圖:

 

4.5 下游任務接口

真正體現出BERT這個模型是龍骨級模型而不再是詞向量的,就是其到各個下游任務的接口設計了,或者換個更洋氣的詞叫遷移策略。 首先,既然句子和句子對的上層表示都得到了,那麼當然對於文本分類任務和文本匹配任務(文本匹配其實也是一種文本分類任務,只不過輸入是文本對)來說,只需要用得到的表示(即encoder在[CLS]詞位的頂層輸出)加上一層MLP就好了呀~

既然文本都被深度雙向encoding了,那麼做序列標註任務就只需要加softmax輸出層就好了呀,連CRF都不用了呀~

讓小夕更木有想到的是,在span抽取式任務如SQuAD上,把深度encoding和深度attention這倆大禮包省掉就算了,甚至都敢直接把輸出層的pointer net給丟掉了?直接像DrQA那樣傲嬌的用兩個線性分類器分別輸出span的起點和終點?

 

4.6 實驗效果

嗯,這很Google。

 

參考文獻

[1] 2018 | BERT- Pre-training of Deep Bidirectional Transformers for Language Understanding
[2] 2018NAACL | Deep contextualized word representations
[3] 2018 ACL | Multi-Turn Response Selection for Chatbots with Deep Attention Matching Network
[4] 2018ICLR | Fast and Accurate Reading Comprehension by Combining Self-Attention and Convolution
[5] 2017TACL | Enriching Word Vectors with Subword Information
[6] 2017ACL | Deep Pyramid Convolutional Neural Networks for Text Categorization
[7] 2017 | Convolutional Sequence to Sequence Learning
[8] 2017 | Do Convolutional Networks need to be Deep for Text Classification ?
[9] 2016 | Convolutional Neural Networks for Text Categorization/ Shallow Word-level vs. Deep Character-level
[10] 2013NIPS | Distributed-representations-of-words-and-phrases-and-their-compositionality

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章