1. 程式人生 > >[NLP自然語言處理]谷歌BERT模型深度解析

[NLP自然語言處理]谷歌BERT模型深度解析

BERT模型程式碼已經發布,可以在我的github: NLP-BERT--Python3.6-pytorch 中下載,請記得start哦
目錄

一、前言

二、如何理解BERT模型

三、BERT模型解析

      論文的核心:詳解BERT模型架構

      關鍵創新:預訓練任務

      實驗結果

四、BERT模型的影響

對BERT模型的觀點

參考文獻
一、前言

 

最近谷歌搞了個大新聞,公司AI團隊新發布的BERT模型,在機器閱讀理解頂級水平測試SQuAD1.1中表現出驚人的成績:全部兩個衡量指標上全面超越人類,並且還在11種不同NLP測試中創出最佳成績,包括將GLUE基準推至80.4%(絕對改進7.6%),MultiNLI準確度達到86.7% (絕對改進率5.6%)等。可以預見的是,BERT將為NLP帶來里程碑式的改變,也是NLP領域近期最重要的進展。

Rank

谷歌團隊的Thang Luong直接定義:BERT模型開啟了NLP的新時代!

從現在的大趨勢來看,使用某種模型預訓練一個語言模型看起來是一種比較靠譜的方法。從之前AI2的 ELMo,到 OpenAI的fine-tune transformer,再到Google的這個BERT,全都是對預訓練的語言模型的應用。

BERT這個模型與其它兩個不同的是

    它在訓練雙向語言模型時以減小的概率把少量的詞替成了Mask或者另一個隨機的詞。我個人感覺這個目的在於使模型被迫增加對上下文的記憶。至於這個概率,我猜是Jacob拍腦袋隨便設的。
    增加了一個預測下一句的loss。這個看起來就比較新奇了。

BERT模型具有以下兩個特點:

第一,是這個模型非常的深,12層,並不寬(wide),中間層只有1024,而之前的Transformer模型中間層有2048。這似乎又印證了計算機影象處理的一個觀點——深而窄 比 淺而寬 的模型更好。

第二,MLM(Masked Language Model),同時利用左側和右側的詞語,這個在ELMo上已經出現了,絕對不是原創。其次,對於Mask(遮擋)在語言模型上的應用,已經被Ziang Xie提出了(我很有幸的也參與到了這篇論文中):[1703.02573] Data Noising as Smoothing in Neural Network Language Models。這也是篇巨星雲集的論文:Sida Wang,Jiwei Li(香儂科技的創始人兼CEO兼史上發文最多的NLP學者),Andrew Ng,Dan Jurafsky都是Coauthor。但很可惜的是他們沒有關注到這篇論文。用這篇論文的方法去做Masking,相信BRET的能力說不定還會有提升。

 
二、如何理解BERT模型

[1] BERT 要解決什麼問題?

通常情況 transformer 模型有很多引數需要訓練。譬如 BERT BASE 模型: L=12, H=768, A=12, 需要訓練的模型引數總數是 12 * 768 * 12 = 110M。這麼多引數需要訓練,自然需要海量的訓練語料。如果全部用人力標註的辦法,來製作訓練資料,人力成本太大。

受《A Neural Probabilistic Language Model》論文的啟發,BERT 也用 unsupervised 的辦法,來訓練 transformer 模型。神經概率語言模型這篇論文,主要講了兩件事兒,1. 能否用數值向量(word vector)來表達自然語言詞彙的語義?2. 如何給每個詞彙,找到恰當的數值向量?

Transformer

這篇論文寫得非常精彩,深入淺出,要言不煩,而且面面俱到。經典論文,值得反覆咀嚼。很多同行朋友都熟悉這篇論文,內容不重複說了。常用的中文漢字有 3500 個,這些字組合成詞彙,中文詞彙數量高達 50 萬個。假如詞向量的維度是 512,那麼語言模型的引數數量,至少是 512 * 50萬 = 256M

模型引數數量這麼大,必然需要海量的訓練語料。從哪裡收集這些海量的訓練語料?《A Neural Probabilistic Language Model》這篇論文說,每一篇文章,天生是訓練語料。難道不需要人工標註嗎?回答,不需要。

我們經常說,“說話不要顛三倒四,要通順,要連貫”,意思是上下文的詞彙,應該具有語義的連貫性。基於自然語言的連貫性,語言模型根據前文的詞,預測下一個將出現的詞。如果語言模型的引數正確,如果每個詞的詞向量設定正確,那麼語言模型的預測,就應該比較準確。天下文章,數不勝數,所以訓練資料,取之不盡用之不竭。

深度學習四大要素,1. 訓練資料、2. 模型、3. 算力、4. 應用。訓練資料有了,接下去的問題是模型。

 

[2] BERT 的五個關鍵詞 Pre-training、Deep、Bidirectional、Transformer、Language Understanding 分別是什麼意思?

《A Neural Probabilistic Language Model》這篇論文講的 Language Model,嚴格講是語言生成模型(Language Generative Model),預測語句中下一個將會出現的詞彙。語言生成模型能不能直接移用到其它 NLP 問題上去?

譬如,淘寶上有很多使用者評論,能否把每一條使用者轉換成評分?-2、-1、0、1、2,其中 -2 是極差,+2 是極好。假如有這樣一條使用者評語,“買了一件鹿晗同款襯衫,沒想到,穿在自己身上,不像小鮮肉,倒像是廚師”,請問這條評語,等同於 -2,還是其它?

語言生成模型,能不能很好地解決上述問題?進一步問,有沒有 “通用的” 語言模型,能夠理解語言的語義,適用於各種 NLP 問題?BERT 這篇論文的題目很直白,《BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding》,一眼看去,就能猜得到這篇文章會講哪些內容。

這個題目有五個關鍵詞,分別是 Pre-training、Deep、Bidirectional、Transformers、和 Language Understanding。其中 pre-training 的意思是,作者認為,確實存在通用的語言模型,先用文章預訓練通用模型,然後再根據具體應用,用 supervised 訓練資料,精加工(fine tuning)模型,使之適用於具體應用。為了區別於針對語言生成的 Language Model,作者給通用的語言模型,取了一個名字,叫語言表徵模型 Language Representation Model。

能實現語言表徵目標的模型,可能會有很多種,具體用哪一種呢?作者提議,用 Deep Bidirectional Transformers 模型。假如給一個句子 “能實現語言表徵[mask]的模型”,遮蓋住其中“目標”一詞。從前往後預測[mask],也就是用“能/實現/語言/表徵”,來預測[mask];或者,從後往前預測[mask],也就是用“模型/的”,來預測[mask],稱之為單向預測 unidirectional。單向預測,不能完整地理解整個語句的語義。於是研究者們嘗試雙向預測。把從前往後,與從後往前的兩個預測,拼接在一起 [mask1/mask2],這就是雙向預測 bi-directional。細節參閱《Neural Machine Translation by Jointly Learning to Align and Translate》。

BERT 的作者認為,bi-directional 仍然不能完整地理解整個語句的語義,更好的辦法是用上下文全向來預測[mask],也就是用 “能/實現/語言/表徵/../的/模型”,來預測[mask]。BERT 作者把上下文全向的預測方法,稱之為 deep bi-directional。如何來實現上下文全向預測呢?BERT 的作者建議使用 Transformer 模型。這個模型由《Attention Is All You Need》一文發明。

這個模型的核心是聚焦機制,對於一個語句,可以同時啟用多個聚焦點,而不必侷限於從前往後的,或者從後往前的,序列序列處理。不僅要正確地選擇模型的結構,而且還要正確地訓練模型的引數,這樣才能保障模型能夠準確地理解語句的語義。BERT 用了兩個步驟,試圖去正確地訓練模型的引數。第一個步驟是把一篇文章中,15% 的詞彙遮蓋,讓模型根據上下文全向地預測被遮蓋的詞。假如有 1 萬篇文章,每篇文章平均有 100 個詞彙,隨機遮蓋 15% 的詞彙,模型的任務是正確地預測這 15 萬個被遮蓋的詞彙。通過全向預測被遮蓋住的詞彙,來初步訓練 Transformer 模型的引數。然後,用第二個步驟繼續訓練模型的引數。譬如從上述 1 萬篇文章中,挑選 20 萬對語句,總共 40 萬條語句。挑選語句對的時候,其中 2*10 萬對語句,是連續的兩條上下文語句,另外 2*10 萬對語句,不是連續的語句。然後讓 Transformer 模型來識別這 20 萬對語句,哪些是連續的,哪些不連續。

這兩步訓練合在一起,稱為預訓練 pre-training。訓練結束後的 Transformer 模型,包括它的引數,是作者期待的通用的語言表徵模型。

 
三、BERT模型解析

首先來看下谷歌AI團隊做的這篇論文。

BERT的新語言表示模型,它代表Transformer的雙向編碼器表示。與最近的其他語言表示模型不同,BERT旨在通過聯合調節所有層中的上下文來預先訓練深度雙向表示。因此,預訓練的BERT表示可以通過一個額外的輸出層進行微調,適用於廣泛任務的最先進模型的構建,比如問答任務和語言推理,無需針對具體任務做大幅架構修改。

論文作者認為現有的技術嚴重製約了預訓練表示的能力。其主要侷限在於標準語言模型是單向的,這使得在模型的預訓練中可以使用的架構型別很有限。

在論文中,作者通過提出BERT:即Transformer的雙向編碼表示來改進基於架構微調的方法。

BERT 提出一種新的預訓練目標:遮蔽語言模型(masked language model,MLM),來克服上文提到的單向性侷限。MLM 的靈感來自 Cloze 任務(Taylor, 1953)。MLM 隨機遮蔽模型輸入中的一些 token,目標在於僅基於遮蔽詞的語境來預測其原始詞彙 id。

與從左到右的語言模型預訓練不同,MLM 目標允許表徵融合左右兩側的語境,從而預訓練一個深度雙向 Transformer。除了遮蔽語言模型之外,本文作者還引入了一個“下一句預測”(next sentence prediction)任務,可以和MLM共同預訓練文字對的表示。

論文的主要貢獻在於:

    證明了雙向預訓練對語言表示的重要性。與之前使用的單向語言模型進行預訓練不同,BERT使用遮蔽語言模型來實現預訓練的深度雙向表示。
    論文表明,預先訓練的表示免去了許多工程任務需要針對特定任務修改體系架構的需求。 BERT是第一個基於微調的表示模型,它在大量的句子級和token級任務上實現了最先進的效能,強於許多面向特定任務體系架構的系統。
    BERT重新整理了11項NLP任務的效能記錄。本文還報告了 BERT 的模型簡化研究(ablation study),表明模型的雙向性是一項重要的新成果。相關程式碼和預先訓練的模型將會公佈在goo.gl/language/bert上。

BERT目前已經重新整理的11項自然語言處理任務的最新記錄包括:將GLUE基準推至80.4%(絕對改進7.6%),MultiNLI準確度達到86.7% (絕對改進率5.6%),將SQuAD v1.1問答測試F1得分紀錄重新整理為93.2分(絕對提升1.5分),超過人類表現2.0分。
論文的核心:詳解BERT模型架構

本節介紹BERT模型架構和具體實現,並介紹預訓練任務,這是這篇論文的核心創新。

模型架構

BERT的模型架構是基於Vaswani et al. (2017) 中描述的原始實現multi-layer bidirectional Transformer編碼器,並在tensor2tensor庫中釋出。由於Transformer的使用最近變得無處不在,論文中的實現與原始實現完全相同,因此這裡將省略對模型結構的詳細描述。

在這項工作中,論文將層數(即Transformer blocks)表示為L,將隱藏大小表示為H,將self-attention heads的數量表示為A。在所有情況下,將feed-forward/filter 的大小設定為 4H,即H = 768時為3072,H = 1024時為4096。論文主要報告了兩種模型大小的結果:

    BERT_{BASE} : L=12, H=768, A=12, Total Parameters=110M
    BERT_{LARGE} : L=24, H=1024, A=16, Total Parameters=340M

為了進行比較,論文選擇了 BERT_{LARGE} ,它與OpenAI GPT具有相同的模型大小。然而,重要的是,BERT Transformer 使用雙向self-attention,而GPT Transformer 使用受限制的self-attention,其中每個token只能處理其左側的上下文。研究團隊注意到,在文獻中,雙向 Transformer 通常被稱為“Transformer encoder”,而左側上下文被稱為“Transformer decoder”,因為它可以用於文字生成。BERT,OpenAI GPT和ELMo之間的比較如圖1所示。

圖1:預訓練模型架構的差異。BERT使用雙向Transformer。OpenAI GPT使用從左到右的Transformer。ELMo使用經過獨立訓練的從左到右和從右到左LSTM的串聯來生成下游任務的特徵。三個模型中,只有BERT表示在所有層中共同依賴於左右上下文。

輸入表示(input representation)

論文的輸入表示(input representation)能夠在一個token序列中明確地表示單個文字句子或一對文字句子(例如, [Question, Answer])。對於給定token,其輸入表示通過對相應的token、segment和position embeddings進行求和來構造。圖2是輸入表示的直觀表示:

圖2:BERT輸入表示。輸入嵌入是token embeddings, segmentation embeddings 和position embeddings 的總和。

具體如下:

    使用WordPiece嵌入(Wu et al., 2016)和30,000個token的詞彙表。用##表示分詞。
    使用學習的positional embeddings,支援的序列長度最多為512個token。
    每個序列的第一個token始終是特殊分類嵌入([CLS])。對應於該token的最終隱藏狀態(即,Transformer的輸出)被用作分類任務的聚合序列表示。對於非分類任務,將忽略此向量。
    句子對被打包成一個序列。以兩種方式區分句子。首先,用特殊標記([SEP])將它們分開。其次,新增一個learned sentence A嵌入到第一個句子的每個token中,一個sentence B嵌入到第二個句子的每個token中。
    對於單個句子輸入,只使用 sentence A嵌入。

關鍵創新:預訓練任務

與Peters et al. (2018) 和 Radford et al. (2018)不同,論文不使用傳統的從左到右或從右到左的語言模型來預訓練BERT。相反,使用兩個新的無監督預測任務對BERT進行預訓練。

任務1: Masked LM

從直覺上看,研究團隊有理由相信,深度雙向模型比left-to-right 模型或left-to-right and right-to-left模型的淺層連線更強大。遺憾的是,標準條件語言模型只能從左到右或從右到左進行訓練,因為雙向條件作用將允許每個單詞在多層上下文中間接地“see itself”。

為了訓練一個深度雙向表示(deep bidirectional representation),研究團隊採用了一種簡單的方法,即隨機遮蔽(masking)部分輸入token,然後只預測那些被遮蔽的token。論文將這個過程稱為“masked LM”(MLM),儘管在文獻中它經常被稱為Cloze任務(Taylor, 1953)。

在這個例子中,與masked token對應的最終隱藏向量被輸入到詞彙表上的輸出softmax中,就像在標準LM中一樣。在團隊所有實驗中,隨機地遮蔽了每個序列中15%的WordPiece token。與去噪的自動編碼器(Vincent et al., 2008)相反,只預測masked words而不是重建整個輸入。

雖然這確實能讓團隊獲得雙向預訓練模型,但這種方法有兩個缺點。首先,預訓練和finetuning之間不匹配,因為在finetuning期間從未看到[MASK]token。為了解決這個問題,團隊並不總是用實際的[MASK]token替換被“masked”的詞彙。相反,訓練資料生成器隨機選擇15%的token。例如在這個句子“my dog is hairy”中,它選擇的token是“hairy”。然後,執行以下過程:

資料生成器將執行以下操作,而不是始終用[MASK]替換所選單詞:

    80%的時間:用[MASK]標記替換單詞,例如,my dog is hairy → my dog is [MASK]
    10%的時間:用一個隨機的單詞替換該單詞,例如,my dog is hairy → my dog is apple
    10%的時間:保持單詞不變,例如,my dog is hairy → my dog is hairy. 這樣做的目的是將表示偏向於實際觀察到的單詞。

Transformer encoder不知道它將被要求預測哪些單詞或哪些單詞已被隨機單詞替換,因此它被迫保持每個輸入token的分散式上下文表示。此外,因為隨機替換隻發生在所有token的1.5%(即15%的10%),這似乎不會損害模型的語言理解能力。

使用MLM的第二個缺點是每個batch只預測了15%的token,這表明模型可能需要更多的預訓練步驟才能收斂。團隊證明MLM的收斂速度略慢於 left-to-right的模型(預測每個token),但MLM模型在實驗上獲得的提升遠遠超過增加的訓練成本。

 

任務2:下一句預測

許多重要的下游任務,如問答(QA)和自然語言推理(NLI)都是基於理解兩個句子之間的關係,這並沒有通過語言建模直接獲得。

在為了訓練一個理解句子的模型關係,預先訓練一個二進位制化的下一句測任務,這一任務可以從任何單語語料庫中生成。具體地說,當選擇句子A和B作為預訓練樣本時,B有50%的可能是A的下一個句子,也有50%的可能是來自語料庫的隨機句子。例如:

Input = [CLS] the man went to [MASK] store [SEP]

he bought a gallon [MASK] milk [SEP]

Label = IsNext

Input = [CLS] the man [MASK] to the store [SEP]

penguin [MASK] are flight ##less birds [SEP]

Label = NotNext

團隊完全隨機地選擇了NotNext語句,最終的預訓練模型在此任務上實現了97%-98%的準確率。
實驗結果

如前文所述,BERT在11項NLP任務中重新整理了效能表現記錄!在這一節中,團隊直觀呈現BERT在這些任務的實驗結果,具體的實驗設定和比較請閱讀原論文.

圖3:我們的面向特定任務的模型是將BERT與一個額外的輸出層結合而形成的,因此需要從頭開始學習最小數量的引數。在這些任務中,(a)和(b)是序列級任務,而(c)和(d)是token級任務。在圖中,E表示輸入嵌入,Ti表示tokeni的上下文表示,[CLS]是用於分類輸出的特殊符號,[SEP]是用於分隔非連續token序列的特殊符號。

圖4:GLUE測試結果,由GLUE評估伺服器給出。每個任務下方的數字表示訓練樣例的數量。“平均”一欄中的資料與GLUE官方評分稍有不同,因為我們排除了有問題的WNLI集。BERT 和OpenAI GPT的結果是單模型、單任務下的資料。所有結果來自https://gluebenchmark.com/leaderboard和https://blog.openai.com/language-unsupervised/

圖5:SQuAD 結果。BERT 整合是使用不同預訓練檢查點和fine-tuning seed的 7x 系統。

圖6:CoNLL-2003 命名實體識別結果。超引數由開發集選擇,得出的開發和測試分數是使用這些超引數進行五次隨機重啟的平均值。

 
四、BERT模型的影響

BERT是一個語言表徵模型(language representation model),通過超大資料、巨大模型、和極大的計算開銷訓練而成,在11個自然語言處理的任務中取得了最優(state-of-the-art, SOTA)結果。或許你已經猜到了此模型出自何方,沒錯,它產自谷歌。估計不少人會調侃這種規模的實驗已經基本讓一般的實驗室和研究員望塵莫及了,但它確實給我們提供了很多寶貴的經驗:

    深度學習就是表徵學習 (Deep learning is representation learning):"We show that pre-trained representations eliminate the needs of many heavily engineered task-specific architectures". 在11項BERT刷出新境界的任務中,大多隻在預訓練表徵(pre-trained representation)微調(fine-tuning)的基礎上加一個線性層作為輸出(linear output layer)。在序列標註的任務裡(e.g. NER),甚至連序列輸出的依賴關係都先不管(i.e. non-autoregressive and no CRF),照樣秒殺之前的SOTA,可見其表徵學習能力之強大。
    規模很重要(Scale matters):"One of our core claims is that the deep bidirectionality of BERT, which is enabled by masked LM pre-training, is the single most important improvement of BERT compared to previous work". 這種遮擋(mask)在語言模型上的應用對很多人來說已經不新鮮了,但確是BERT的作者在如此超大規模的資料+模型+算力的基礎上驗證了其強大的表徵學習能力。這樣的模型,甚至可以延伸到很多其他的模型,可能之前都被不同的實驗室提出和試驗過,只是由於規模的侷限沒能充分挖掘這些模型的潛力,而遺憾地讓它們被淹沒在了滾滾的paper洪流之中。
    預訓練價值很大(Pre-training is important):"We believe that this is the first work to demonstrate that scaling to extreme model sizes also leads to large improvements on very small-scale tasks, provided that the model has been sufficiently pre-trained". 預訓練已經被廣泛應用在各個領域了(e.g. ImageNet for CV, Word2Vec in NLP),多是通過大模型大資料,這樣的大模型給小規模任務能帶來的提升有幾何,作者也給出了自己的答案。BERT模型的預訓練是用Transformer做的,但我想換做LSTM或者GRU的話應該不會有太大效能上的差別,當然訓練計算時的並行能力就另當別論了。

對BERT模型的觀點
 

0. high-performance的原因其實還是歸結於兩點,除了模型的改進,更重要的是用了超大的資料集(BooksCorpus 800M + English Wikipedia 2.5G單詞)和超大的算力(對應於超大模型)在相關的任務上做預訓練,實現了在目標任務上表現的單調增長

1. 這個模型的雙向和Elmo不一樣,大部分人對他這個雙向在novelty上的contribution 的大小有誤解,我覺得這個細節可能是他比Elmo顯著提升的原因。Elmo是拼一個左到右和一個右到左,他這個是訓練中直接開一個視窗,用了個有順序的cbow。

2. 可復現性差:有錢才能為所欲為(Reddit對跑一次BERT的價格討論)

For TPU pods:

4 TPUs * ~$2/h (preemptible) * 24 h/day * 4 days = $768 (base model)

16 TPUs = ~$3k (large model)

 

For TPU:

16 tpus * $8/hr * 24 h/day * 4 days = 12k

64 tpus * $8/hr * 24 h/day * 4 days = 50k

最後他問到:For GPU:"BERT-Large is 24-layer, 1024-hidden and was trained for 40 epochs over a 3.3 billion word corpus. So maybe 1 year to train on 8 P100s? " ,然後這個就很interesting了。
參考文獻

1. 知乎:如何評價谷歌最新的BERT模型

2. 華爾街見聞:NLP歷史突破

3. OPENAI-Improving Language Understanding with Unsupervised Learning

4. https://gluebenchmark.com/leaderboard