理解Word2Vec
一、簡介
Word2vec 是 Word Embedding 的方法之一,屬於NLP 領域。它是將詞轉化為「可計算」「結構化」的向量的過程。它是 2013 年由Google的 Mikolov 提出了一套新的詞嵌入方法。
Word2vec 在整個 NLP 里的位置可以用下圖表示:
二、詞向量(Word Embedding)
在說明 Word2vec 之前,需要先解釋一下 Word Embedding。 它就是將「不可計算」「非結構化」的詞轉化為「可計算」「結構化」的向量。這一步解決的是「將現實問題轉化為數學問題」,是人工智慧非常關鍵的一步。
自然語言處理(NLP)相關任務中,要將自然語言交給機器學習中的演算法來處理,通常需要首先將語言數學化,因為機器不是人,機器只認數學符號。向量是人把自然界的東西抽象出來交給機器處理的東西,基本上可以說向量是人對機器輸入的主要方式了。
詞向量就是用來將語言中的詞進行數學化的一種方式,顧名思義,詞向量就是把一個詞表示成一個向量。主要有兩種表示方式:One-Hot Representation(獨熱編碼) 和 Distributed Representation。
2.1 One-Hot Representation
一種最簡單的詞向量方式是 One-Hot-Representation,就是用一個很長的向量來表示一個詞,向量的長度為詞典的大小,向量的分量只有一個 1,其他全為 0, 1 的位置對應該詞在詞典中的位置。舉個例子,
「話筒」表示為 [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 ···]
「麥克」表示為 [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 ···]
每個詞都是茫茫 0 海中的一個 1。
這種 One-Hot Representation 如果採用稀疏方式存儲,會是非常的簡潔:也就是給每個詞分配一個數字 ID。比如剛才的例子中,話筒記為 3,麥克記為 8(假設從 0 開始記)。如果要編程實現的話,用 Hash 表給每個詞分配一個編號就可以了。這麼簡潔的表示方法配合上最大熵、SVM、CRF 等等演算法已經很好地完成了 NLP 領域的各種主流任務。
但這種詞表示有兩個缺點:(1)容易受維數災難的困擾,尤其是將其用於 Deep Learning 的一些演算法時;(2)不能很好地刻畫詞與詞之間的相似性(術語好像叫做「辭彙鴻溝」):任意兩個詞之間都是孤立的。光從這兩個向量中看不出兩個詞是否有關係,哪怕是話筒和麥克這樣的同義詞也不能幸免於難。
所以會尋求發展,用另外的方式表示,就是下面這種。
2.2 Distributed Representation
另一種就是Distributed Representation 這種表示,它最早是 Hinton 於 1986 年提出的,可以克服 one-hot representation 的缺點。其基本想法是直接用一個普通的向量表示一個詞,這種向量一般長成這個樣子:[0.792, −0.177, −0.107, 0.109, −0.542, ···],也就是普通的向量表示形式。維度以 50 維和 100 維比較常見。
當然一個詞怎麼表示成這樣的一個向量是要經過一番訓練的,訓練方法較多,word2vec是其中一種,在後面會提到,這裡先說它的意義。還要注意的是每個詞在不同的語料庫和不同的訓練方法下,得到的詞向量可能是不一樣的。詞向量一般維數不高,很少有人閑著沒事訓練的時候定義一個10000維以上的維數,所以用起來維數災難的機會相對於One-Hot representation表示就大大減少了。
由於是用向量表示,而且用較好的訓練演算法得到的詞向量的向量一般是有空間上的意義的,也就是說,將所有這些向量放在一起形成一個詞向量空間,而每一向量則為該空間中的一個點,在這個空間上的詞向量之間的距離度量也可以表示對應的兩個詞之間的「距離」。所謂兩個詞之間的「距離」,就是這兩個詞之間的語法,語義之間的相似性。
一個比較爽的應用方法是,得到詞向量後,假如對於某個詞A,想找出這個詞最相似的詞,這個場景對人來說都不輕鬆,畢竟比較主觀,但是對於建立好詞向量後的情況,對電腦來說,只要拿這個詞的詞向量跟其他詞的詞向量一一計算歐式距離或者cos距離,得到距離最小的那個詞,就是它最相似的。這樣的特性使得詞向量很有意義,自然就會吸引比較多的人去研究,前有Bengio發表在JMLR上的論文《A Neural Probabilistic Language Model》,又有Hinton的層次化Log-Bilinear模型,還有google的TomasMikolov 團隊搞的word2vec,等等。詞向量在機器翻譯領域的一個應用,就是google的TomasMikolov 團隊開發了一種詞典和術語表的自動生成技術,該技術通過向量空間,把一種語言轉變成另一種語言,實驗中對英語和西班牙語間的翻譯準確率高達90%。
介紹演算法工作原理的時候舉了一個例子:考慮英語和西班牙語兩種語言,通過訓練分別得到它們對應的詞向量空間 E 和 S。從英語中取出五個詞 one,two,three,four,five,設其在 E 中對應的詞向量分別為 v1,v2,v3,v4,v5,為方便作圖,利用主成分分析(PCA)降維,得到相應的二維向量 u1,u2,u3,u4,u5,在二維平面上將這五個點描出來,如下圖左圖所示。類似地,在西班牙語中取出(與 one,two,three,four,five 對應的) uno,dos,tres,cuatro,cinco,設其在 S 中對應的詞向量分別為 s1,s2,s3,s4,s5,用 PCA 降維後的二維向量分別為 t1,t2,t3,t4,t5,將它們在二維平面上描出來(可能還需作適當的旋轉),如下圖右圖所示:
觀察左、右兩幅圖,容易發現:五個詞在兩個向量空間中的相對位置差不多,這說明兩種不同語言對應向量空間的結構之間具有相似性,從而進一步說明了在詞向量空間中利用距離刻畫詞之間相似性的合理性。
三、word2vec
word2vec模型其實就是簡單化的神經網路。我們就需要訓練神經網路語言模型,這個模型的輸出我們不關心,我們關心的是模型中第一個隱含層中的參數權重,這個參數矩陣就是我們需要的詞向量。
輸入是One-Hot Vector,Hidden Layer沒有激活函數,也就是線性的單元。Output Layer維度跟Input Layer的維度一樣,用的是Softmax回歸。當這個模型訓練好以後,我們並不會用這個訓練好的模型處理新的任務,我們真正需要的是這個模型通過訓練數據所學得的參數,例如隱層的權重矩陣。
這個模型是如何定義數據的輸入和輸出呢?一般分為CBOW(Continuous Bag-of-Words) 與Skip-Gram兩種模型。CBOW模型的訓練輸入是某一個特徵詞的上下文相關的詞對應的詞向量,而輸出就是這特定的一個詞的詞向量。Skip-Gram模型和CBOW的思路是反著來的,即輸入是特定的一個詞的詞向量,而輸出是特定詞對應的上下文詞向量。CBOW對小型資料庫比較合適,而Skip-Gram在大型語料中表現更好。


3.1 CBOW(Continuous Bag-of-Words)
CBOW通過上下文來預測當前值。相當於一句話中扣掉一個詞,讓你猜這個詞是什麼。
CBOW的訓練模型如下圖所示:

1、輸入層:上下文單詞的one hot. {假設單詞向量空間dim為V,上下文單詞個數為C}
2、所有one hot分別乘以共享的輸入權重矩陣W. {VN矩陣,N為自己設定的數,初始化權重矩陣W}
3、所得的向量 {因為是one hot所以為向量} 相加求平均作為隱層向量, size為1N.
4、乘以輸出權重矩陣W’ {NV}
5、得到向量 {1V} 激活函數處理得到V-dim概率分布 {PS: 因為是one hot嘛,其中的每一維斗代表著一個單詞}
6、概率最大的index所指示的單詞為預測出的中間詞(target word)與true label的one hot做比較,誤差越小越好(根據誤差更新權重矩陣)
所以,需要定義loss function(一般為交叉熵代價函數),採用梯度下降演算法更新W和W’。訓練完畢後,輸入層的每個單詞與矩陣W相乘得到的向量的就是我們想要的詞向量(word embedding),這個矩陣(所有單詞的word embedding)也叫做look up table(其實聰明的你已經看出來了,其實這個look up table就是矩陣W自身),也就是說,任何一個單詞的one hot乘以這個矩陣都將得到自己的詞向量。有了look up table就可以免去訓練過程直接查表得到單詞的詞向量了。
舉個栗子:

窗口大小是2,表示選取coffe前面兩個單詞和後面兩個單詞,作為input詞。

假設我們此時得到的概率分布已經達到了設定的迭代次數,那麼現在我們訓練出來的look up table應該為矩陣W。即,任何一個單詞的one-hot表示乘以這個矩陣都將得到自己的word embedding。
3.2 Skip-Gram
從直觀上理解,Skip-Gram用當前詞來預測上下文。相當於給你一個詞,讓你猜前面和後面可能出現什麼詞。
接下來我們來看看如何訓練我們的神經網路。假如我們有一個句子「The dog barked at the mailman」。首先我們選句子中間的一個詞作為我們的輸入詞,例如我們選取「dog」作為input word;有了input word以後,我們再定義一個叫做skip_window的參數,它代表著我們從當前input word的一側(左邊或右邊)選取詞的數量。如果我們設置skip_window=2,那麼我們最終獲得窗口中的詞(包括input word在內)就是[‘The’, ‘dog’,’barked’, ‘at’]。skip_window=2代表著選取左input word左側2個詞和右側2個詞進入我們的窗口,所以整個窗口大小span=2×2=4。另一個參數叫num_skips,它代表著我們從整個窗口中選取多少個不同的詞作為我們的output word,當skip_window=2,num_skips=2時,我們將會得到兩組 (input word, output word) 形式的訓練數據,即 (‘dog’, ‘barked’),(‘dog’, ‘the’)。
神經網路基於這些訓練數據將會輸出一個概率分布,這個概率代表著我們的詞典中的每個詞是output word的可能性。這句話有點繞,我們來看個栗子。第二步中我們在設置skip_window和num_skips=2的情況下獲得了兩組訓練數據。假如我們先拿一組數據 (‘dog’, ‘barked’) 來訓練神經網路,那麼模型通過學習這個訓練樣本,會告訴我們辭彙表中每個單詞是「barked」的概率大小。
模型的輸出概率代表著到我們詞典中每個詞有多大可能性跟input word同時出現。舉個栗子,如果我們向神經網路模型中輸入一個單詞「中國「,那麼最終模型的輸出概率中,像「英國」, 」俄羅斯「這種相關詞的概率將遠高於像」蘋果「,」蟈蟈「非相關詞的概率。因為」英國「,」俄羅斯「在文本中更大可能在」中國「的窗口中出現。我們將通過給神經網路輸入文本中成對的單詞來訓練它完成上面所說的概率計算。
下面的圖中給出了一些我們的訓練樣本的例子。我們選定句子「The quick brown fox jumps over lazy dog」,設定我們的窗口大小為2(window_size=2),也就是說我們僅選輸入詞前後各兩個詞和輸入詞進行組合。下圖中,藍色代表input word,方框內代表位於窗口內的單詞。Training Samples(輸入, 輸出):

再次提醒,最終我們需要的是訓練出來的權重矩陣。
四、訓練注意事項
我們發現Word2Vec模型是一個超級大的神經網路(權重矩陣規模非常大)。舉個栗子,我們擁有10000個單詞的辭彙表,我們如果想嵌入300維的詞向量,那麼我們的輸入-隱層權重矩陣和隱層-輸出層的權重矩陣都會有 10000 x 300 = 300萬個權重,在如此龐大的神經網路中進行梯度下降是相當慢的。更糟糕的是,你需要大量的訓練數據來調整這些權重並且避免過擬合。百萬數量級的權重矩陣和億萬數量級的訓練樣本意味著訓練這個模型將會是個災難(太兇殘了)。
下面主要介紹兩種方法優化訓練過程:
1、負取樣(negative sampling)
負取樣(negative sampling)解決了這個問題,它是用來提高訓練速度並且改善所得到詞向量的品質的一種方法。不同於原本每個訓練樣本更新所有的權重,負取樣每次讓一個訓練樣本僅僅更新一小部分的權重,這樣就會降低梯度下降過程中的計算量。至於具體的細節我在這裡就不在介紹了。
2、層序softmax
層序softmax也是解決這個問題的一種方法。這裡也不做詳細介紹。
五、總結
最後強調一下,word2vec一個NLP工具,它可以將所有的詞向量化,這樣詞與詞之間就可以定量的去度量他們之間的關係,挖掘詞之間的聯繫。word2vec主要包含兩個模型Skip-gram和CBOW。以及兩種高效的訓練方法負取樣,層序softmax。
參考:
//easyai.tech/ai-definition/word2vec/
//www.cnblogs.com/sxron/articles/5123790.html
//blog.csdn.net/yu5064/article/details/79601683
//www.jianshu.com/p/471d9bfbd72f