BERT模型的若干問題整理記錄 & 思考

1.BERT的基本原理是什麼?

BERT來自Google的論文Pre-training of Deep Bidirectional Transformers for Language Understanding,BERT是”Bidirectional Encoder Representations from Transformers”的首字母縮寫,整體是一個自編碼語言模型(Autoencoder LM),並且其設計了兩個任務來預訓練該模型。第一個任務是採用MaskLM的方式來訓練語言模型,通俗地說就是在輸入一句話的時候,隨機地選一些要預測的詞,然後用一個特殊的符號[MASK]來代替它們,之後讓模型根據所給的標籤去學習這些地方該填的詞。第二個任務在雙向語言模型的基礎上額外增加了一個句子級別的連續性預測任務,即預測輸入BERT的兩段文本是否爲連續的文本,引入這個任務可以更好地讓模型學到連續的文本片段之間的關係。最後的實驗表明BERT模型的有效性,並在11項NLP任務中奪得SOTA結果。

BERT相較於原來的RNN、LSTM可以做到併發執行,同時提取詞在句子中的關係特徵,並且能在多個不同層次提取關係特徵,進而更全面反映句子語義。相較於word2vec,其又能根據句子上下文獲取詞義,從而避免歧義出現。同時缺點也是顯而易見的,模型參數太多,而且模型太大,少量數據訓練時,容易過擬合。

2.BERT是怎麼用Transformer的?

BERT只使用了Transformer的Encoder模塊,原論文中,作者分別用12層和24層Transformer Encoder組裝了兩套BERT模型,分別是:

  • BERTBASE:L=12,H=768,A=12,TotalParameters=110MBERT_{BASE}: L=12, H=768, A=12, Total Parameters=110M
  • BERTLARGE:L=24,H=1024,A=16,TotalParameters=340MBERT_{LARGE}: L=24, H=1024, A=16, Total Parameters=340M

其中層的數量(即,Transformer Encoder塊的數量)爲 LL,隱藏層的維度爲 HH,自注意頭的個數爲 AA。在所有例子中,我們將前饋/過濾器(Transformer Encoder端的feed-forward層)的維度設置爲 4H4H,即當 H=768H = 768 時是 30723072;當 H=1024H = 102440964096

圖示如下:

img

需要注意的是,與Transformer本身的Encoder端相比,BERT的Transformer Encoder端輸入的向量表示,多了Segment Embeddings。

3.BERT的訓練過程是怎麼樣的?

在論文原文中,作者提出了兩個預訓練任務:Masked LM和Next Sentence Prediction。

3.1 Masked LM

Masked LM的任務描述爲:給定一句話,隨機抹去這句話中的一個或幾個詞,要求根據剩餘詞彙預測被抹去的幾個詞分別是什麼,如下圖所示。

圖解 BERT 模型:從零開始構建 BERT

BERT 模型的這個預訓練過程其實就是在模仿我們學語言的過程,思想來源於完形填空的任務。具體來說,文章作者在一句話中隨機選擇 15% 的詞彙用於預測。對於在原句中被抹去的詞彙, 80% 情況下采用一個特殊符號 [MASK] 替換, 10% 情況下采用一個任意詞替換,剩餘 10% 情況下保持原詞彙不變。這麼做的主要原因是:在後續微調任務中語句中並不會出現 [MASK] 標記,而且這麼做的另一個好處是:預測一個詞彙時,模型並不知道輸入對應位置的詞彙是否爲正確的詞彙( 10% 概率),這就迫使模型更多地依賴於上下文信息去預測詞彙,並且賦予了模型一定的糾錯能力。上述提到了這樣做的一個缺點,其實這樣做還有另外一個缺點,就是每批次數據中只有 15% 的標記被預測,這意味着模型可能需要更多的預訓練步驟來收斂。

3.2 Next Sentence Prediction

Next Sentence Prediction的任務描述爲:給定一篇文章中的兩句話,判斷第二句話在文本中是否緊跟在第一句話之後,如下圖所示。
在這裏插入圖片描述

這個類似於段落重排序的任務,即:將一篇文章的各段打亂,讓我們通過重新排序把原文還原出來,這其實需要我們對全文大意有充分、準確的理解。Next Sentence Prediction 任務實際上就是段落重排序的簡化版:只考慮兩句話,判斷是否是一篇文章中的前後句。在實際預訓練過程中,文章作者從文本語料庫中隨機選擇 50% 正確語句對和 50% 錯誤語句對進行訓練,與 Masked LM 任務相結合,讓模型能夠更準確地刻畫語句乃至篇章層面的語義信息。

BERT 模型通過對 Masked LM 任務和 Next Sentence Prediction 任務進行聯合訓練,使模型輸出的每個字 / 詞的向量表示都能儘可能全面、準確地刻畫輸入文本(單句或語句對)的整體信息,爲後續的微調任務提供更好的模型參數初始值。

4.爲什麼BERT比ELMo效果好?ELMo和BERT的區別是什麼?

4.1 爲什麼BERT比ELMo效果好?

從網絡結構以及最後的實驗效果來看,BERT比ELMo效果好主要集中在以下幾點原因:

(1).LSTM抽取特徵的能力遠弱於Transformer

(2).拼接方式雙向融合的特徵融合能力偏弱(沒有具體實驗驗證,只是推測)

(3).其實還有一點,BERT的訓練數據以及模型參數均多餘ELMo,這也是比較重要的一點

4.2 ELMo和BERT的區別是什麼?

ELMo模型是通過語言模型任務得到句子中單詞的embedding表示,以此作爲補充的新特徵給下游任務使用。因爲ELMO給下游提供的是每個單詞的特徵形式,所以這一類預訓練的方法被稱爲“Feature-based Pre-Training”。而BERT模型是“基於Fine-tuning的模式”,這種做法和圖像領域基於Fine-tuning的方式基本一致,下游任務需要將模型改造成BERT模型,纔可利用BERT模型預訓練好的參數。

5.BERT有什麼侷限性?

從XLNet論文中,提到了BERT的兩個缺點,分別如下:

  • BERT在第一個預訓練階段,假設句子中多個單詞被Mask掉,這些被Mask掉的單詞之間沒有任何關係,是條件獨立的,然而有時候這些單詞之間是有關係的,比如”New York is a city”,假設我們Mask住”New”和”York”兩個詞,那麼給定”is a city”的條件下”New”和”York”並不獨立,因爲”New York”是一個實體,看到”New”則後面出現”York”的概率要比看到”Old”後面出現”York”概率要大得多。
    • 但是需要注意的是,這個問題並不是什麼大問題,甚至可以說對最後的結果並沒有多大的影響,因爲本身BERT預訓練的語料就是海量的(動輒幾十個G),所以如果訓練數據足夠大,其實不靠當前這個例子,靠其它例子,也能彌補被Mask單詞直接的相互關係問題,因爲總有其它例子能夠學會這些單詞的相互依賴關係。
  • BERT的在預訓練時會出現特殊的[MASK],但是它在下游的fine-tune中不會出現,這就出現了預訓練階段和fine-tune階段不一致的問題。其實這個問題對最後結果產生多大的影響也是不夠明確的,因爲後續有許多BERT相關的預訓練模型仍然保持了[MASK]標記,也取得了很大的結果,而且很多數據集上的結果也比BERT要好。但是確確實實引入[MASK]標記,也是爲了構造自編碼語言模型而採用的一種折中方式。

另外還有一個缺點,是BERT在分詞後做[MASK]會產生的一個問題,爲了解決OOV的問題,我們通常會把一個詞切分成更細粒度的WordPiece。BERT在Pretraining的時候是隨機Mask這些WordPiece的,這就可能出現只Mask一個詞的一部分的情況,例如:

在這裏插入圖片描述

probability這個詞被切分成”pro”、”#babi”和”#lity”3個WordPiece。有可能出現的一種隨機Mask是把”#babi” Mask住,但是”pro”和”#lity”沒有被Mask。這樣的預測任務就變得容易了,因爲在”pro”和”#lity”之間基本上只能是”#babi”了。這樣它只需要記住一些詞(WordPiece的序列)就可以完成這個任務,而不是根據上下文的語義關係來預測出來的。類似的中文的詞”模型”也可能被Mask部分(其實用”琵琶”的例子可能更好,因爲這兩個字只能一起出現而不能單獨出現),這也會讓預測變得容易。

爲了解決這個問題,很自然的想法就是詞作爲一個整體要麼都Mask要麼都不Mask,這就是所謂的Whole Word Masking。這是一個很簡單的想法,對於BERT的代碼修改也非常少,只是修改一些Mask的那段代碼。

TODO:另外還有別的缺點及其改進,看到相關論文再補充。

6.BERT的輸入和輸出分別是什麼?

BERT模型的主要輸入是文本中各個字/詞(或者稱爲token)的原始詞向量,該向量既可以隨機初始化,也可以利用Word2Vector等算法進行預訓練以作爲初始值;輸出是文本中各個字/詞融合了全文語義信息後的向量表示,如下圖所示(爲方便描述且與BERT模型的當前中文版本保持一致,統一以字向量作爲輸入):

圖解 BERT 模型:從零開始構建 BERT

從上圖中可以看出,**BERT模型通過查詢字向量表將文本中的每個字轉換爲一維向量,作爲模型輸入;模型輸出則是輸入各字對應的融合全文語義信息後的向量表示。**此外,模型輸入除了字向量(英文中對應的是Token Embeddings),還包含另外兩個部分:

  1. 文本向量(英文中對應的是Segment Embeddings):該向量的取值在模型訓練過程中自動學習,用於刻畫文本的全局語義信息,並與單字/詞的語義信息相融合

  2. 位置向量(英文中對應的是Position Embeddings):由於出現在文本不同位置的字/詞所攜帶的語義信息存在差異(比如:“我愛你”和“你愛我”),因此,BERT模型對不同位置的字/詞分別附加一個不同的向量以作區分

最後,BERT模型將字向量、文本向量和位置向量的加和作爲模型輸入。特別地,在目前的BERT模型中,文章作者還將英文詞彙作進一步切割,劃分爲更細粒度的語義單位(WordPiece),例如:將playing分割爲play和##ing;此外,對於中文,目前作者未對輸入文本進行分詞,而是直接將單字作爲構成文本的基本單位。

需要注意的是,上圖中只是簡單介紹了單個句子輸入BERT模型中的表示,實際上,在做Next Sentence Prediction任務時,在第一個句子的首部會加上一個[CLS] token,在兩個句子中間以及最後一個句子的尾部會加上一個[SEP] token。

7.針對句子語義相似度/多標籤分類/機器翻譯翻譯/文本生成的任務,利用BERT結構怎麼做fine-tuning?

7.1 針對句子語義相似度的任務

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-CBDxu5DV-1585620347995)(https://gluon-nlp.mxnet.io/_images/bert-sentence-pair.png)]

實際操作時,上述最後一句話之後還會加一個[SEP] token,語義相似度任務將兩個句子按照上述方式輸入即可,之後與論文中的分類任務一樣,將[CLS] token位置對應的輸出,接上softmax做分類即可(實際上GLUE任務中就有很多語義相似度的數據集)。

7.2 針對多標籤分類的任務

多標籤分類任務,即MultiLabel,指的是一個樣本可能同時屬於多個類,即有多個標籤。以商品爲例,一件L尺寸的棉服,則該樣本就有至少兩個標籤——型號:L,類型:冬裝。

對於多標籤分類任務,顯而易見的樸素做法就是不管樣本屬於幾個類,就給它訓練幾個分類模型即可,然後再一一判斷在該類別中,其屬於那個子類別,但是這樣做未免太暴力了,而多標籤分類任務,其實是可以只用一個模型來解決的。

利用BERT模型解決多標籤分類問題時,其輸入與普通單標籤分類問題一致,得到其embedding表示之後(也就是BERT輸出層的embedding),有幾個label就連接到幾個全連接層(也可以稱爲projection layer),然後再分別接上softmax分類層,這樣的話會得到loss1, loss2, , lossnloss_1,\ loss_2,\ \cdots,\ loss_n,最後再將所有的loss相加起來即可。這種做法就相當於將n個分類模型的特徵提取層參數共享,得到一個共享的表示(其維度可以視任務而定,由於是多標籤分類任務,因此其維度可以適當增大一些),最後再做多標籤分類任務。

7.3 針對翻譯的任務

針對翻譯的任務,我自己想到一種做法,因爲BERT本身會產生embedding這樣的“副產品”,因此可以直接利用BERT輸出層得到的embedding,然後在做機器翻譯任務時,將其作爲輸入/輸出的embedding表示,這樣做的話,可能會遇到UNK的問題,爲了解決UNK的問題,可以將得到的詞向量embedding拼接字向量的embedding得到輸入/輸出的表示(對應到英文就是token embedding拼接經過charcnn的embedding的表示)。

7.4 針對文本生成的任務

關於生成任務,搜到以下幾篇論文:

BERT has a Mouth, and It Must Speak: BERT as a Markov Random Field Language Model

MASS: Masked Sequence to Sequence Pre-training for Language Generation

Unified Language Model Pre-training for Natural Language Understanding and Generation

8.BERT應用於有空格丟失或者單詞拼寫錯誤等數據是否還是有效?有什麼改進的方法?

8.1 BERT應用於有空格丟失的數據是否還是有效?

按照常理推斷可能會無效了,因爲空格都沒有的話,那麼便成爲了一長段文本,但是具體還是有待驗證。而對於有空格丟失的數據要如何處理呢?一種方式是利用Bi-LSTM + CRF做分詞處理,待其處理成正常文本之後,再將其輸入BERT做下游任務。

8.2 BERT應用於單詞拼寫錯誤的數據是否還是有效?

如果有少量的單詞拼寫錯誤,那麼造成的影響應該不會太大,因爲BERT預訓練的語料非常豐富,而且很多語料也不夠乾淨,其中肯定也還是會含有不少單詞拼寫錯誤這樣的情況。但是如果單詞拼寫錯誤的比例比較大,比如達到了30%、50%這種比例,那麼需要通過人工特徵工程的方式,以中文中的同義詞替換爲例,將不同的錯字/別字都替換成同樣的詞語,這樣減少錯別字帶來的影響。例如花被、花珼、花唄、花唄、花鋇均替換成花唄。

9.BERT的embedding向量如何的來的?

以中文爲例,BERT模型通過查詢字向量表將文本中的每個字轉換爲一維向量,作爲模型輸入(還有position embedding和segment embedding);模型輸出則是輸入各字對應的融合全文語義信息後的向量表示。

而對於輸入的token embedding、segment embedding、position embedding都是隨機生成的,需要注意的是在Transformer論文中的position embedding由sin/cos函數生成的固定的值,而在這裏代碼實現中是跟普通word embedding一樣隨機生成的,可以訓練的。作者這裏這樣選擇的原因可能是BERT訓練的數據比Transformer那篇大很多,完全可以讓模型自己去學習。

10.BERT模型爲什麼要用mask?它是如何做mask的?其mask相對於CBOW有什麼異同點?

10.1 BERT模型爲什麼要用mask?

BERT通過在輸入X中隨機Mask掉一部分單詞,然後預訓練過程的主要任務之一是根據上下文單詞來預測這些被Mask掉的單詞。其實這個就是典型的Denosing Autoencoder的思路,那些被Mask掉的單詞就是在輸入側加入的所謂噪音。 類似BERT這種預訓練模式,被稱爲DAE LM。因此總結來說BERT模型 [Mask] 標記就是引入噪音的手段。

關於DAE LM預訓練模式,優點是它能比較自然地融入雙向語言模型,同時看到被預測單詞的上文和下文,然而缺點也很明顯,主要在輸入側引入[Mask]標記,導致預訓練階段和Fine-tuning階段不一致的問題。

10.2 它是如何做mask的?

給定一個句子,會隨機Mask 15%的詞,然後讓BERT來預測這些Mask的詞,如同上述10.1所述,在輸入側引入[Mask]標記,會導致預訓練階段和Fine-tuning階段不一致的問題,因此在論文中爲了緩解這一問題,採取瞭如下措施:

如果某個Token在被選中的15%個Token裏,則按照下面的方式隨機的執行:

  • 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

這樣做的好處是,BERT並不知道[MASK]替換的是這15%個Token中的哪一個詞(注意:這裏意思是輸入的時候不知道[MASK]替換的是哪一個詞,但是輸出還是知道要預測哪個詞的),而且任何一個詞都有可能是被替換掉的,比如它看到的apple可能是被替換的詞。這樣強迫模型在編碼當前時刻的時候不能太依賴於當前的詞,而要考慮它的上下文,甚至對其上下文進行”糾錯”。比如上面的例子模型在編碼apple是根據上下文my dog is應該把apple(部分)編碼成hairy的語義而不是apple的語義。

10.3 其mask相對於CBOW有什麼異同點?

相同點: CBOW的核心思想是:給定上下文,根據它的上文 Context-Before 和下文 Context-after 去預測input word。而BERT本質上也是這麼做的,但是BERT的做法是給定一個句子,會隨機Mask 15%的詞,然後讓BERT來預測這些Mask的詞。

不同點: 首先,在CBOW中,每個單詞都會成爲input word,而BERT不是這麼做的,原因是這樣做的話,訓練數據就太大了,而且訓練時間也會非常長。

其次,對於輸入數據部分,CBOW中的輸入數據只有待預測單詞的上下文,而BERT的輸入是帶有[MASK] token的“完整”句子,也就是說BERT在輸入端將待預測的input word用[MASK] token代替了。

另外,通過CBOW模型訓練後,每個單詞的word embedding是唯一的,因此並不能很好的處理一詞多義的問題,而BERT模型得到的word embedding(token embedding)融合了上下文的信息,就算是同一個單詞,在不同的上下文環境下,得到的word embedding是不一樣的。

其實自己在整理這個問題時,萌生了新的問題,具體描述如下:

爲什麼BERT中輸入數據的[mask]標記爲什麼不能直接留空或者直接輸入原始數據,在self-attention的Q K V計算中,不與待預測的單詞做Q K V交互計算?

這個問題還要補充一點細節,就是數據可以像CBOW那樣,每一條數據只留一個“空”,這樣的話,之後在預測的時候,就可以將待預測單詞之外的所有單詞的表示融合起來(均值融合或者最大值融合等方式),然後再接上softmax做分類。

乍一看,感覺這個idea確實有可能可行,而且也沒有看到什麼不合理之處,但是需要注意的是,這樣做的話,需要每預測一個單詞,就要計算一套Q、K、V。就算不每次都計算,那麼保存每次得到的Q、K、V也需要耗費大量的空間。總而言之,這種做法確實可能也是可行,但是實際操作難度卻很大,從計算量來說,就是預訓練BERT模型的好幾倍(至少),而且要保存中間狀態也並非易事。其實還有挺重要的一點,如果像CBOW那樣做,那麼文章的“創新”在哪呢~

11.BERT的兩個預訓練任務對應的損失函數是什麼(用公式形式展示)?

BERT的損失函數由兩部分組成,第一部分是來自 Mask-LM 的單詞級別分類任務,另一部分是句子級別的分類任務。通過這兩個任務的聯合學習,可以使得 BERT 學習到的表徵既有 token 級別信息,同時也包含了句子級別的語義信息。具體損失函數如下:
L(θ,θ1,θ2)=L1(θ,θ1)+L2(θ,θ2) L\left(\theta, \theta_{1}, \theta_{2}\right)=L_{1}\left(\theta, \theta_{1}\right)+L_{2}\left(\theta, \theta_{2}\right)
其中 θ\theta 是 BERT 中 Encoder 部分的參數,θ1\theta_1 是 Mask-LM 任務中在 Encoder 上所接的輸出層中的參數,θ2\theta_2 則是句子預測任務中在 Encoder 接上的分類器參數。因此,在第一部分的損失函數中,如果被 mask 的詞集合爲 M,因爲它是一個詞典大小 |V| 上的多分類問題,那麼具體說來有:
L1(θ,θ1)=i=1Mlogp(m=miθ,θ1),mi[1,2,,V] L_{1}\left(\theta, \theta_{1}\right)=-\sum_{i=1}^{M} \log p\left(m=m_{i} | \theta, \theta_{1}\right), m_{i} \in[1,2, \ldots,|V|]
在句子預測任務中,也是一個分類問題的損失函數:
L2(θ,θ2)=j=1Nlogp(n=niθ,θ2),ni[IsNext,NotNext] L_{2}\left(\theta, \theta_{2}\right)=-\sum_{j=1}^{N} \log p\left(n=n_{i} | \theta, \theta_{2}\right), n_{i} \in[\text {IsNext}, \text {NotNext}]
因此,兩個任務聯合學習的損失函數是:
L(θ,θ1,θ2)=i=1Mlogp(m=miθ,θ1)j=1Nlogp(n=niθ,θ2) L\left(\theta, \theta_{1}, \theta_{2}\right)=-\sum_{i=1}^{M} \log p\left(m=m_{i} | \theta, \theta_{1}\right)-\sum_{j=1}^{N} \log p\left(n=n_{i} | \theta, \theta_{2}\right)
具體的預訓練工程實現細節方面,BERT 還利用了一系列策略,使得模型更易於訓練,比如對於學習率的 warm-up 策略,使用的激活函數不再是普通的 ReLu,而是 GeLu,也使用了 dropout 等常見的訓練技巧。

12.詞袋模型到word2vec改進了什麼?word2vec到BERT又改進了什麼?

12.1 詞袋模型到word2vec改進了什麼?

詞袋模型(Bag-of-words model)是將一段文本(比如一個句子或是一個文檔)用一個“裝着這些詞的袋子”來表示,這種表示方式不考慮文法以及詞的順序。而在用詞袋模型時,文檔的向量表示直接將各詞的詞頻向量表示加和。通過上述描述,可以得出詞袋模型的兩個缺點:

  • 詞向量化後,詞與詞之間是有權重大小關係的,不一定詞出現的越多,權重越大。
  • 詞與詞之間是沒有順序關係的。

而word2vec是考慮詞語位置關係的一種模型。通過大量語料的訓練,將每一個詞語映射成一個低維稠密向量,通過求餘弦的方式,可以判斷兩個詞語之間的關係,word2vec其底層主要採用基於CBOW和Skip-Gram算法的神經網絡模型。

因此,綜上所述,詞袋模型到word2vec的改進主要集中於以下兩點:

  • 考慮了詞與詞之間的順序,引入了上下文的信息
  • 得到了詞更加準確的表示,其表達的信息更爲豐富

12.2 word2vec到BERT又改進了什麼?

word2vec到BERT的改進之處其實沒有很明確的答案,如同上面的問題所述,BERT的思想其實很大程度上來源於CBOW模型,如果從準確率上說改進的話,BERT利用更深的模型,以及海量的語料,得到的embedding表示,來做下游任務時的準確率是要比word2vec高不少的。實際上,這也離不開模型的“加碼”以及數據的“巨大加碼”。再從方法的意義角度來說,BERT的重要意義在於給大量的NLP任務提供了一個泛化能力很強的預訓練模型,而僅僅使用word2vec產生的詞向量表示,不僅能夠完成的任務比BERT少了很多,而且很多時候直接利用word2vec產生的詞向量表示給下游任務提供信息,下游任務的表現不一定會很好,甚至會比較差。

參考:

BERT模型詳解

XLNet原理

圖解BERT模型:從零開始構建BERT

XLNet:運行機制及和Bert的異同比較

如何評價 BERT 模型?

【NLP】Google BERT詳解

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