【NLP】詞向量:從word2vec、glove、ELMo到BERT詳解!

 

目前,詞向量(又叫詞嵌入word embedding)已經成爲NLP領域各種任務的必備一步,而且隨着bert elmo,gpt等預訓練模型的發展,詞向量演變爲知識表示方法,但其本質思想不變。學習各種詞向量訓練原理可以很好地掌握NLP各種方法。生成詞向量的方法有很多種,本文重點介紹word2vec,glove和bert。

各種詞向量的特點:

  • One-hot:維度災難 and 語義鴻溝;
  • 矩陣分解(LSA):利用全局語料特徵,但SVD求解計算複雜度大;
  • 基於NNLM/RNNLM的詞向量:詞向量爲副產物,存在效率不高等問題;
  • word2vec、fastText:優化效率高,但是基於局部語料;
  • glove:基於全局預料,結合了LSA和word2vec的優點;
  • elmo、GPT、bert:動態特徵。

從one-hot到word2vec到elmo,可以看到技術的演進總是在現有基礎上解決之前的問題,同時引出新的問題。這裏總結一下比較經典的語言模型:word2vec、glove、ELMo、BERT。

word2vec

word2vec來源於2013年的論文《Efficient Estimation of Word Representation in Vector Space》,它的核心思想是利用神經網絡對詞的上下文訓練得到詞的向量化表示,訓練方法:CBOW(通過附近詞預測中心詞)、Skip-gram(通過中心詞預測附近的詞):

CBOW與Skip-gram基本結構

CBOW :

NOTE:花括號內{}爲解釋內容.

  1. 輸入層:上下文單詞的onehot. {假設單詞向量空間dim爲V,上下文單詞個數爲C}
  2. 所有onehot分別乘以共享的輸入權重矩陣W. {V*N矩陣,N爲自己設定的數,初始化權重矩陣W}
  3. 所得的向量 {因爲是onehot所以爲向量} 相加求平均作爲隱層向量, size爲1*N.
  4. 乘以輸出權重矩陣W' {N*V}
  5. 得到向量 {1*V} 激活函數處理得到V-dim概率分佈 {PS: 因爲是onehot嘛,其中的每一維斗代表着一個單詞},概率最大的index所指示的單詞爲預測出的中間詞(target word)
  6. 與true label的onehot做比較,誤差越小越好

所以,需要定義loss function(一般爲交叉熵代價函數),採用梯度下降算法更新W和W'。訓練完畢後,輸入層的每個單詞與矩陣W相乘得到的向量的就是我們想要的詞向量(word embedding),這個矩陣(所有單詞的word embedding)也叫做look up table(其實聰明的你已經看出來了,其實這個look up table就是矩陣W自身),也就是說,任何一個單詞的onehot乘以這個矩陣都將得到自己的詞向量。有了look up table就可以免去訓練過程直接查表得到單詞的詞向量了。

Skip-gram 

跟CBOW的原理相似,它的輸入是目標詞,先是將目標詞映射爲一個隱藏層向量,根據這個向量預測目標詞上下文兩個詞,因爲詞彙表大和樣本不均衡,同樣也會採用多層softmax或負採樣優化。

分層softmax

一般神經網絡語言模型在預測的時候,輸出的是預測目標詞的概率,也就是說我每一次預測都要基於全部的數據集進行計算,這無疑會帶來很大的時間開銷。不同於其他神經網絡,word2vec提出兩種加快訓練速度的方式,一種是Hierarchical softmax,另一種是Negative Sampling。

 

原始神經網絡模型的輸入輸出框架

 

word2vec hierarchical softmax結構

和傳統的神經網絡輸出不同的是,word2vec的hierarchical softmax結構是把輸出層改成了一顆哈夫曼樹,其中圖中白色的葉子節點表示詞彙表中所有的|V|個詞,黑色節點表示非葉子節點,每一個葉子節點也就是每一個單詞,都對應唯一的一條從root節點出發的路徑。我們的目的是使得w=wO這條路徑的概率最大,即: P(w=wO|wI)最大,假設最後輸出的條件概率是W2最大,那麼我只需要去更新從根結點到w2這一個葉子結點的路徑上面節點的向量即可,而不需要更新所有的詞的出現概率,這樣大大的縮小了模型訓練更新的時間。

我們應該如何得到某個葉子結點的概率呢?

 

假設我們要計算W2葉子節點的概率,我們需要從根節點到葉子結點計算概率的乘積。我們知道,本模型替代的只是原始模型的softmax層,因此,某個非葉子節點的值即隱藏層到輸出層的結果仍然是uj,我們對這個結果進行sigmoid之後,得到節點往左子樹走的概率p,1-p則爲往右子樹走的概率。關於這棵樹的訓練方式比較複雜,但也是通過梯度下降等方法,這裏不詳述,感興趣的可以閱讀論文word2vec Parameter Learning Explained。

~~~

(2)Negative Sampling 負採樣

傳統神經網絡在訓練過程中的每一步,都需要計算詞庫中其他詞在當前的上下文環境下出現的概率值,這導致計算量十分巨大。

 

然而,對於word2vec中的特徵學習,可以不需要一個完整的概率模型。CBOW和Skip-Gram模型在輸出端使用的是一個二分類器(即Logistic Regression),來區分目標詞和詞庫中其他的 k個詞(也就是把目標詞作爲一類,其他詞作爲另一類)。下面是一個CBOW模型的圖示,對於Skip-Gram模型輸入輸出是倒置的。

 

此時,最大化的目標函數如下:

 

其中,Qθ(D=1|w,h)爲二元邏輯迴歸的概率,具體爲在數據集 D中、輸入的embedding vector θ、上下文爲 h的情況下詞語 w 出現的概率;公式後半部分爲 k 個從 [噪聲數據集] 中隨機選擇 kk個對立的詞語出現概率(log形式)的期望值。可以看出,目標函數的意義是顯然的,即儘可能的 [分配(assign)] 高概率給真實的目標詞,而低概率給其他 k 個 [噪聲詞],這種技術稱爲負採樣(Negative Sampling)。

這種想法來源於噪聲對比評估方法(NEC),大致思想是:假設X=(x1,x2,,xTd)是從真實的數據(或語料庫)中抽取樣本,但是樣本服從什麼樣的分佈我們不知道,那麼先假設其中的每個xi服從一個未知的概率密度函數pd。這樣我們需要一個相對可參考的分佈反過來去估計概率密度函數pd,這個可參考的分佈或稱之爲噪音分佈應該是我們知道的,比如高斯分佈,均勻分佈等。假設這個噪音分佈的概率密度函數pn,從中抽取樣本數據爲Y=(y1,y2,,yTn)Y=(y1,y2,,yTn),而這個數據稱之爲噪聲樣本,我們的目的就是通過學習一個分類器把這兩類樣本區別開來,並能從模型中學到數據的屬性,噪音對比估計的思想就是“通過比較而學習”。

具體來說,word2vec裏面的負採樣:將輸出層的V個樣本分爲正例(Positive Sample)也就是目標詞對應的項,以及剩餘V1個負例(Negative Samples)。舉個例子有個樣本phone

number,這樣wI=phone,wO=number, 正例就是number這個詞,負例就是不太可能與phone共同出現的詞。負採樣的思想是每次訓練只隨機取一小部分的負例使他們的概率最小,以及對應的正例概率最大。隨機採樣需要假定一個概率分佈,word2vec中直接使用詞頻作爲詞的分佈,不同的是頻數上乘上0.75,相比於直接使用頻次作爲權重,取0.75冪的好處可以減弱不同頻次差異過大帶來的影響,使得小頻次的單詞被採樣的概率變大。

 

採樣權重

負採樣定義的損失函數如下:

 

損失函數,一部分是正樣本(期望輸出的詞),另一部分是負採樣隨機抽取出來的負樣本集合,V'wo是輸出向量

如果大家理解的還不是很深的話,接下來將通過谷歌發佈的tensorflow官方word2vec代碼解析加深理解。代碼鏈接:https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/tutorials/word2vec/word2vec_basic.py,之後我會對代碼進行詳細剖析,歡迎跟蹤~謝謝

glove

word2vec只考慮到了詞的局部信息,沒有考慮到詞與局部窗口外詞的聯繫,glove利用共現矩陣,同時考慮了局部信息和整體的信息。Count-based模型,如GloVe,本質上是對共現矩陣進行降維。首先,構建一個詞彙的共現矩陣,每一行是一個word,每一列是context。共現矩陣就是計算每個word在每個context出現的頻率。由於context是多種詞彙的組合,其維度非常大,我們希望像network embedding一樣,在context的維度上降維,學習word的低維表示。這一過程可以視爲共現矩陣的重構問題,即reconstruction loss。(這裏再插一句,降維或者重構的本質是什麼?我們選擇留下某個維度和丟掉某個維度的標準是什麼?Find the lower-dimensional representations which can explain most of the variance in the high-dimensional data,這其實也是PCA的原理)。

來自論文《Glove: Global vectors for word representation》。Glove損失函數的確定

 

ELMO

之前介紹詞向量均是靜態的詞向量,無法解決一次多義等問題。下面介紹三種elmo、GPT、bert詞向量,它們都是基於語言模型的動態詞向量。下面從幾個方面對這三者進行對比:

 

ELMO是“Embedding from Language Models"簡稱。在此之前word embedding本質是個靜態方式,靜態的意思就是說單詞訓練好之後就固定了,在以後使用時,單詞不會跟着上下文場景變化而變化。如Jobs is the CEO of apple,he finally eat an apple.用word2vec “apple”的表示是一樣的向量,動態模型可以解決此問題。

ELMO的本質思想是:事先用一個語言模型去學習單詞的word embedding, 當在使用時,單詞已經具備了特定的上下文,這時候可以根據上下文的語義去調整單詞的word embedding, 這樣經過調整的word embedding更能表達這個上下文中具體的含義,也就解決了一詞多義問題,故ELMO本質就是根據當前上下文對Word Embedding進行動態調整的過程。

Elmo採用典型的兩階段過程:第一階段使用預訓練語言模型進行訓練,第二階段當做具體的下游任務時,從預訓練的網絡中提取對應的詞的Word Embedding作爲特徵補充到下游任務中。

第一階段,預訓練:採用雙層雙向LSTM對上下文進行編碼,上下文使用靜態的word embedding, 對每層LSTM,將上文向量與下文向量進行拼接作爲當前向量,利用大量的預料訓練這個網絡。對於一個新的句子,可以有三種表示,最底層的word embedding, 第一層的雙向LSTM層的輸出,這一層能學習到更多句法特徵,第二層的雙向LSTM的輸出,這一層能學習到更多詞義特徵。經過elmo訓練,不僅能夠得到word embedding, 又能學習到一個雙層雙向的神經網絡。

 

第二階段,下游任務使用:將一個新的句子作爲elmo預訓練網絡的輸入,這樣該句子在elmo網絡中能獲得三個embedding, 可以將三個embedding加權作爲word embedding, 並將此作爲下游任務的輸入,這被稱爲“Feature-based Pre-Training"。

GPT

GPT是Generative Pre-Traxining的簡稱。與ELMO相似,採用兩階段的模式:利用語言模型進行預訓練,通過fine-tuning模式應用到下游任務。

利用語言模型進行預訓練:與elmo不同的是,GPT使用transformer進行提取特徵,並且是單向的transformer,只是根據上文來預測某個詞,Transformer模型主要是利用自注意力(self-attention)機制的模型。

 

fine-tuning: 與ELMo當成特徵的做法不同,OpenAI GPT不需要再重新對任務構建新的模型結構,而是直接在transformer這個語言模型上的最後一層接上softmax作爲任務輸出層,然後再對這整個模型進行微調。

 

由於不同NLP任務的輸入有所不同,在transformer模型的輸入上針對不同NLP任務也有所不同。具體如下圖,對於分類任務直接講文本輸入即可;對於文本蘊涵任務,需要將前提和假設用一個Delim分割向量拼接後進行輸入;對於文本相似度任務,在兩個方向上都使用Delim拼接後,進行輸入;對於像問答多選擇的任務,就是將每個答案和上下文進行拼接進行輸入。

 

BERT

BERT是“Bidirectional Encoder Representations from Transformers"的簡稱。

同GPT採用兩階段模式:利用雙向transformer語言模型進行預訓練,通過fine-tuning模式解決下游任務。

BERT創新: Masked語言模型和Next Sentence Prediction。

BERT(Bidirectional Encoder Representations from Transformers)詳解(參考鏈接:https://plmsmile.github.io/2018/12/15/52-bert/

http://fancyerii.github.io/2019/03/09/bert-theory/#elmo):

1.總體框架:利用半監督學習一個雙向語言模型,然後在下游任務中,經過該語言模型後,接其他任務。

 

2. BERT輸入表示(如圖):

句子開頭有一個特殊的Token [CLS]句子結束有一個特殊的Token [SEP]如果是兩個句子同時輸入,則只有開頭有[CLS],後面那個句子沒有[CLS],只有[SEP]每個token有三個embedding,詞的Embedding;位置的Embedding和Segment的Embedding詞embedding不用多說,位置embedding是將位置用低維稠密向量表示,segment的embedding是爲了將多個句子區分,第一個句子可能用0表示,第二個用1,只有一個句子的時候可能只用0第一個token很有用,可不能小瞧,因爲它本身沒有任何意義,在進行self-attention時,會獲取下文所有信息(編碼整個句子的語義),不像其他單詞,在self-attention時獲取最多的信息是來自於自己。注意這裏的分詞會把”playing”分成”play”和”##ing”兩個Token,這種把詞分成更細粒度的Word Piece的方法是一種解決未登錄詞的常見辦法

 

3. BERT預訓練(至關重要的兩點):

Mask language model:遮掩語言模型Next Sentence Prediction:預測下一個句子(關係)4. Mask language model(遮掩語言模型):在預訓練的時候,隨機mask掉15%的單詞,讓語言模型去預測這個單詞,如圖(圖中512是padding,規定了句子的長度):

 

這樣的話有兩個缺點:

大量mask標記,造成預訓練和finetune時候的差距,因爲finetune沒有mask,finetune的時候用的是自己的數據集收斂很慢,但是效果好(比單向語言模型慢)關於第一條的解決方案:

80%的概率替換成[MASK],比如my dog is hairy → my dog is [MASK]10%的概率替換成隨機的一個詞,比如my dog is hairy → my dog is apple10%的概率替換成它本身,比如my dog is hairy → my dog is hairy這樣的好處在於:BERT並不知道[MASK]替換的是哪一個詞,而且任何一個詞都有可能是被替換掉的,比如它看到的apple可能是被替換的詞。這樣強迫模型在編碼當前時刻的時候不能太依賴於當前的詞,而要考慮它的上下文,甚至更加上下文進行”糾錯”。比如上面的例子模型在編碼apple是根據上下文my dog is應該把apple(部分)編碼成hairy的語義而不是apple的語義。5. Next Sentence Prediction(預測下一個句子):對於像QA、NLI等需要理解多個句子之間關係的下游任務,只靠語言模型是不夠的。還需要提前學習到句子之間的關係。是一個二分類任務。輸入是A和B兩個句子,標記是IsNext或NotNext,用來判斷B是否是A後面的句子。這樣,就能從大規模預料中學習到一些句間關係。

 

對於這個任務,BERT會以50%的概率抽取有關聯的句子(注意這裏的句子實際只是聯繫的Token序列,不是語言學意義上的句子),另外以50%的概率隨機抽取兩個無關的句子,然後讓BERT模型來判斷這兩個句子是否相關。6. 下游特定任務:

單句子分類(CLS+句子):輸入是一個序列,所有的Token都是屬於同一個Segment(Id=0),我們用第一個特殊Token [CLS]的最後一層輸出接上softmax進行分類,用分類的數據來進行Fine-Tuning。利用CLS進行分類。

多句子分類(CLS+句子A+SEP+句子B):對於相似度計算等輸入爲兩個序列的任務,過程如圖左上所示。兩個序列的Token對應不同的Segment(Id=0/1)。我們也是用第一個特殊Token [CLS]的最後一層輸出接上softmax進行分類,然後用分類數據進行Fine-Tuning。利用CLS分類。

NER(CLS+句子):序列標註,比如命名實體識別,輸入是一個句子(Token序列),除了[CLS]和[SEP]的每個時刻都會有輸出的Tag,然後用輸出的Tag來進行Fine-Tuning利用句子單詞做標記。QA:CLS+問題+SEP+文章。比較麻煩,比如比如SQuAD v1.1數據集,輸入是一個問題和一段很長的包含答案的文字(Paragraph),輸出在這段文字裏找到問題的答案。比如輸入的問題是:

Where do water droplets collide with ice crystals to form precipitation?

包含答案的文字是:

... Precipitation forms as smaller droplets coalesce via collision with other raindrops or ice crystals within a cloud. ...

答案是:

”within a cloud”

我們首先把問題和Paragraph表示成一個長的序列,中間用[SEP]分開,問題對應一個Segment(id=0),包含答案的文字對於另一個Segment(id=1)。這裏有一個假設,那就是答案是Paragraph裏的一段連續的文字(Span)。BERT把尋找答案的問題轉化成尋找這個Span的開始下標和結束下標的問題。

對於Paragraph的第i個Token,BERT的最後一層把它編碼成Ti,然後我們用一個向量S(這是模型的參數,需要根據訓練數據調整)和它相乘(內積)計算它是開始位置的得分,因爲Paragraph的每一個Token(當然WordPiece的中間,比如##ing是不可能是開始的)都有可能是開始可能,我們用softmax把它變成概率,然後選擇概率最大的作爲答案的開始:

 

類似的有一個向量T,用於計算答案結束的位置。

 

總結

word2vec:

nlp中最早的預訓練模型,缺點是無法解決一詞多義問題.

ELMO:

優點: 根據上下文動態調整word embedding,因爲可以解決一詞多義問題;

缺點:1、使用LSTM特徵抽取方式而不是transformer,2、使用向量拼接方式融合上下文特徵融合能力較弱,僞雙向。

GPT:

優點:使用transformer提取特徵

缺點:使用單項的語言模型,即單向transformer.

BERT:

優點:使用雙向語言模型,即使用雙向transformer;使用預測目標詞和下一句這中多任務學習方式進行訓練。

缺點:對文本字數512限制,不利於文本生成。

參考:

https://arxiv.org/abs/1810.04805

https://zhuanlan.zhihu.com/p/35074402

https://www.zhihu.com/question/44832436/answer/266068967

https://zhuanlan.zhihu.com/p/53425736

https://www.cnblogs.com/robert-dlut/p/9824346.html

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