word2vec基本原理和實現

Word2Vec

 

目錄

一.概述... 1

CBow模型 (Continuous Bag-of-Words Model) 2

Skip-gram模型... 2

Hierarchical Softmax. 3

Negative Sampling. 3

二.詳析... 3

基於Hierarchical Softmax的模型... 4

基於Hierarchical Softmax的模型梯度計算... 5

具體使用:... 6

對比... 8

代碼... 9

基於Negative Sampling的word2vec模型... 9

基於Negative Sampling的模型概述... 9

基於Negative Sampling的模型梯度計算... 9

具體應用:... 11

基於Negative Sampling的Skip-Gram模型... 11

代碼... 12

 

 

 

 

一.概述

https://www.cnblogs.com/chason95/articles/10746960.html

 

  1. word2vec算法的背後是一個淺層神經網絡,很多人誤以爲word2vec是一種深度學習算法。
  2. word2vec是一個計算word vector的開源工具。當我們在說word2vec算法或模型的時候,其實指的是其背後用於計算word vector的CBoW模型和Skip-gram模型。很多人以爲word2vec指的是一個算法或模型,這也是一種謬誤。

所以word2vec是一個工具,這個工具包含了CBow和Skip-gram兩種模型來計算word vector。CBow和Skip-gram也可以用於NNLM,但是word2vec並不是這麼做的,它針對NNLM的缺點提出了新的訓練技巧Hierarchical Softmax和Negative Sampling

 

CBow模型 (Continuous Bag-of-Words Model)

 

CBOW模型的訓練輸入是某一個特徵詞的上下文相關的詞對應的詞向量,而輸出就是這特定的一個詞的詞向量。比如下面這段話,我們的上下文大小取值爲4,特定的這個詞是"Learning",也就是我們需要的輸出詞向量,上下文對應的詞有8個,前後各4個,這8個詞是我們模型的輸入。由於CBOW使用的是詞袋模型,因此這8個詞都是平等的,也就是不考慮他們和我們關注的詞之間的距離大小,只要在我們上下文之內即可。

https://img2018.cnblogs.com/blog/1372735/201904/1372735-20190422201934867-74946992.png

這樣我們這個CBOW的例子裏,我們的輸入是8個詞向量,輸出是所有詞的softmax概率(訓練的目標是期望訓練樣本特定詞對應的softmax概率最大),對應的CBOW神經網絡模型輸入層有8個神經元,輸出層有詞彙表大小個神經元。隱藏層的神經元個數我們可以自己指定。通過DNN的反向傳播算法,我們可以求出DNN模型的參數,同時得到所有的詞對應的詞向量。這樣當我們有新的需求,要求出某8個詞對應的最可能的輸出中心詞時,我們可以通過一次DNN前向傳播算法並通過softmax激活函數找到概率最大的詞對應的神經元即可。

這裏介紹的是CBow的思想,也可以理解爲在NNLM中使用CBoW。基於CBoW的word2vec工具在這個思想基礎上還做了很多訓練技巧的改進。
所以如果用基於CBowNNLM,目標函數可以選交叉熵

 

Skip-gram模型

 

Skip-Gram模型和CBOW的思路是反着來的,即輸入是特定的一個詞的詞向量,而輸出是特定詞對應的上下文詞向量。還是上面的例子,我們的上下文大小取值爲4, 特定的這個詞"Learning"是我們的輸入,而這8個上下文詞是我們的輸出。
這樣我們這個Skip-Gram的例子裏,我們的輸入是特定詞, 輸出是softmax概率排前8的8個詞,對應的Skip-Gram神經網絡模型輸入層有1個神經元,輸出層有詞彙表大小個神經元。隱藏層的神經元個數我們可以自己指定。通過DNN的反向傳播算法,我們可以求出DNN模型的參數,同時得到所有的詞對應的詞向量。這樣當我們有新的需求,要求出某1個詞對應的最可能的8個上下文詞時,我們可以通過一次DNN前向傳播算法得到概率大小排前8的softmax概率對應的神經元所對應的詞即可。
和CBoW一樣,這裏介紹的是Skip-Gram的思想,也可以理解爲在NNLM中使用Skip-Gram。基於Skip-Gram的word2vec工具在這個思想基礎上也做了很多訓練技巧的改進。
這裏目標函數同樣可以選取交叉熵

 

Hierarchical Softmax

 

NNLM中,hidden layer是由input經過神經網絡的線性變換加激活函數得到的,基於CBow的word2vec中,將這步簡化爲了直接對input中的詞向量們做average pooling,即輸入(1,2,3,4),(9,6,11,8),(5,10,7,12),得到(5,6,7,8)。(基於Skip-gram的word2vec的hidden layer就直接等於input了,其實就是沒有hidden layer)
另外第二個改進是針對隱藏層到softmax層的。我們知道,哈夫曼樹是一種讓權重高的節點(使用頻率高的)編碼短(更快取到)的數據結構。word2vec就使用哈夫曼樹來對單詞們編碼,從根節點開始,每個節點之間都對應一個權重,通過節點權重和隱層中間語義的二分類邏輯迴歸來判斷對應的下一個單詞應該出現在那個葉子節點上。可以看出,哈夫曼樹的葉子節點就對應了NNLM中輸出softmax層中的一個個神經元。
這樣,我們在訓練階段,如果使用NNLM,我們需要對所有V個節點都進行前向傳播,而使用了Hierarchical Softmax之後,前向傳播最多隻用計算logV次即可(哈夫曼樹樹深)。大大降低了前向傳播的計算量。
不過反向傳播更新參數的計算量可能並沒有減少。我們依然可以把哈夫曼樹的葉子節點們看作NNLM中最後一層輸出層,所以目標函數還是可以用同樣的softmax。

 

Negative Sampling

 

Hierarchical Softmax有效降低了前向傳播的計算量,但是其實它是增加了網絡的參數量的。Negative Sampling則是從另一個方向來對NNLM做改進。
其實思路比Hierarchical Softmax簡單,就是我們要根據輸入的wi兩邊的2c個詞,然wi在輸出中概率最高,那麼我們再採幾個負樣本的詞,然後他們在輸出中概率最低,這樣可以避免網絡的參數傾向於讓大家的得分都越來越高(冷落了那些出現較少的但是其實也很重要的詞)。這點在推薦系統中比較常見。

 

 

 

二.詳析

現在我們開始關注word2vec的語言模型如何改進傳統的神經網絡的方法。由於word2vec有兩種改進方法,一種是基於Hierarchical Softmax的,另一種是基於Negative Sampling的。

 

基於Hierarchical Softmax的模型

 我們先回顧下傳統的神經網絡詞向量語言模型,裏面一般有三層,輸入層(詞向量),隱藏層和輸出層(softmax層)。裏面最大的問題在於從隱藏層到輸出的softmax層的計算量很大,因爲要計算所有詞的softmax概率,再去找概率最大的值。這個模型如下圖所示。其中V是詞彙表的大小。

 

https://images2017.cnblogs.com/blog/1042406/201707/1042406-20170727105326843-18935623.png

 

 word2vec對這個模型做了改進,

  1. 首先,對於從輸入層到隱藏層的映射,沒有采取神經網絡的線性變換加激活函數的方法,而是採用簡單的對所有輸入詞向量求和並取平均的方法。比如輸入的是三個4維詞向量:(1,2,3,4),(9,6,11,8),(5,10,7,12),那麼我們word2vec映射後的詞向量就是(5,6,7,8)。由於這裏是從多個詞向量變成了一個詞向量。
  2. 第二個改進就是從隱藏層到輸出的softmax層這裏的計算量個改進。爲了避免要計算所

有詞的softmax概率,word2vec採樣了霍夫曼樹來代替從隱藏層到輸出softmax層的映射。我們在上一節已經介紹了霍夫曼樹的原理。如何映射呢?這裏就是理解word2vec的關鍵所在了。

由於我們把之前所有都要計算的從輸出softmax層的概率計算變成了一顆二叉霍夫曼樹,那麼我們的softmax概率計算只需要沿着樹形結構進行就可以了。如下圖所示,我們可以沿着霍夫曼樹從根節點一直走到我們的葉子節點的詞w2。

https://images2017.cnblogs.com/blog/1042406/201707/1042406-20170727105752968-819608237.png

和之前的神經網絡語言模型相比,我們的霍夫曼樹的所有內部節點就類似之前神經網絡隱藏層的神經元,其中,根節點的詞向量對應我們的投影后的詞向量,而所有葉子節點就類似於之前神經網絡softmax輸出層的神經元,葉子節點的個數就是詞彙表的大小。在霍夫曼樹中,隱藏層到輸出層的softmax映射不是一下子完成的,而是沿着霍夫曼樹一步步完成的,因此這種softmax取名爲"Hierarchical Softmax"。

如何“沿着霍夫曼樹一步步完成”呢?在word2vec中,我們採用了二元邏輯迴歸的方法,即規定沿着左子樹走,那麼就是負類(霍夫曼樹編碼1),沿着右子樹走,那麼就是正類(霍夫曼樹編碼0)。判別正類和負類的方法是使用sigmoid函數,即:

其中xw是當前內部節點的詞向量,而θ則是我們需要從訓練樣本求出的邏輯迴歸的模型參數。使用霍夫曼樹有什麼好處呢?首先,由於是二叉樹,之前計算量爲V,現在變成了log2V。第二,由於使用霍夫曼樹是高頻的詞靠近樹根,這樣高頻詞需要更少的時間會被找到,這符合我們的貪心優化思想。

容易理解,被劃分爲左子樹而成爲負類的概率爲P(−)=1−P(+)。在某一個內部節點,要判斷是沿左子樹還是右子樹走的標準就是看P(−),P(+)誰的概率值大。而控制P(−),P(+)誰的概率值大的因素一個是當前節點的詞向量,另一個是當前節點的模型參數θ。

對於上圖中的w2,如果它是一個訓練樣本的輸出,那麼我們期望對於裏面的隱藏節點n(w2,1)的P(−)概率大,n(w2,2)的P(−)概率大,n(w2,3)的P(+)概率大。

回到基於Hierarchical Softmax的word2vec本身,我們的目標就是找到合適的所有節點的詞向量和所有內部節點θ, 使訓練樣本達到最大似然。那麼如何達到最大似然呢?

 

基於Hierarchical Softmax的模型梯度計算

      

我們使用最大似然法來尋找所有節點的詞向量和所有內部節點θ。先拿上面的w2例子來看,我們期望最大化下面的似然函數:

  對於所有的訓練樣本,我們期望最大化所有樣本的似然函數乘積。

  爲了便於我們後面一般化的描述,我們定義輸入的詞爲w,其從輸入層詞向量求和平均後的霍夫曼樹根節點詞向量爲xw, 從根節點到w所在的葉子節點,包含的節點總數爲lw, w在霍夫曼樹中從根節點開始,經過的第i個節點表示爲pwi,對應的霍夫曼編碼爲dwi∈{0,1},其中i=2,3,...lw。而該節點對應的模型參數表示爲θwi, 其中i=1,2,...lw−1,沒有i=lw

是因爲模型參數僅僅針對於霍夫曼樹的內部節點。

定義w經過的霍夫曼樹某一個節點j的邏輯迴歸概率爲,其表達式爲:

  那麼對於某一個目標輸出詞w,其最大似然爲:

  在word2vec中,由於使用的是隨機梯度上升法,所以並沒有把所有樣本的似然乘起來得到真正的訓練集最大似然,僅僅每次只用一個樣本更新梯度,這樣做的目的是減少梯度計算量。這樣我們可以得到w的對數似然函數L如下:

要得到模型中w詞向量和內部節點的模型參數θ, 我們使用梯度上升法即可。首先我們求模型參數θwj−1的梯度:

如果大家看過之前寫的邏輯迴歸原理小結,會發現這裏的梯度推導過程基本類似。

同樣的方法,可以求出xw的梯度表達式如下:

    有了梯度表達式,我們就可以用梯度上升法進行迭代來一步步的求解我們需要的所有的θwj−1和xw。

具體使用:

基於Hierarchical SoftmaxCBOW模型

 

基於Hierarchical SoftmaxSkip-Gram模型

 

對比

 對於從輸入層到隱藏層(投影層),skip-garm這一步比CBOW簡單,由於只有一個詞,所以,即xw就是詞w對應的詞向量。

       不是隻更新xw一個詞,而是xi,i=1,2...2c共2c個詞。這樣整體的迭代會更加的均衡。因爲這個原因,Skip-Gram模型並沒有和CBOW模型一樣對輸入進行迭代更新,而是對2c個輸出進行迭代更新。

 

代碼

https://github.com/tmikolov/word2vec/blob/master/word2vec.c

在源代碼中,基於Hierarchical Softmax的CBOW模型算法在435-463行,基於Hierarchical Softmax的Skip-Gram的模型算法在495-519行。大家可以對着源代碼再深入研究下算法。

在源代碼中,neule對應我們上面的e, syn0對應我們的xw, syn1對應我們的θij−1, layer1_size對應詞向量的維度,window對應我們的c。另外,vocab[word].code[d]指的是,當前單詞word的,第d個編碼,編碼不含Root結點。vocab[word].point[d]指的是,當前單詞word,第d個編碼下,前置的結點。

 

 

基於Negative Sampling的word2vec模型

在講基於Negative Sampling的word2vec模型前,我們先看看Hierarchical Softmax的的缺點。的確,使用霍夫曼樹來代替傳統的神經網絡,可以提高模型訓練的效率。但是如果我們的訓練樣本里的中心詞w是一個很生僻的詞,那麼就得在霍夫曼樹中辛苦的向下走很久了。能不能不用搞這麼複雜的一顆霍夫曼樹,將模型變的更加簡單呢?

Negative Sampling就是這麼一種求解word2vec模型的方法,它摒棄了霍夫曼樹,採用了Negative Sampling(負採樣)的方法來求解,下面我們就來看看Negative Sampling的求解思路。

 

基於Negative Sampling的模型概述

 既然名字叫Negative Sampling(負採樣),那麼肯定使用了採樣的方法。採樣的方法有很多種,比如之前講到的大名鼎鼎的MCMC。我們這裏的Negative Sampling採樣方法並沒有MCMC那麼複雜。

比如我們有一個訓練樣本,中心詞是w,它周圍上下文共有2c個詞,記爲context(w)。由於這個中心詞w,的確和context(w)相關存在,因此它是一個真實的正例。通過Negative Sampling採樣,我們得到neg個和w不同的中心詞wi,i=1,2,..neg,這樣context(w)和wi就組成了neg個並不真實存在的負例。利用這一個正例和neg個負例,我們進行二元邏輯迴歸,得到負採樣對應每個詞wi對應的模型參數θi,和每個詞的詞向量。

從上面的描述可以看出,Negative Sampling由於沒有采用霍夫曼樹,每次只是通過採樣neg個不同的中心詞做負例,就可以訓練模型,因此整個過程要比Hierarchical Softmax簡單。

不過有兩個問題還需要弄明白:1)如果通過一個正例和neg個負例進行二元邏輯迴歸呢? 2) 如何進行負採樣呢?

基於Negative Sampling的模型梯度計算

 

Negative Sampling負採樣方法

現在我們來看看如何進行負採樣,得到neg個負例。word2vec採樣的方法並不複雜,如果詞彙表的大小爲V,那麼我們就將一段長度爲1的線段分成V份,每份對應詞彙表中的一個詞。當然每個詞對應的線段長度是不一樣的,高頻詞對應的線段長,低頻詞對應的線段短。每個詞w的線段長度由下式決定:

在word2vec中,分子和分母都取了3/4次冪如下:

在採樣前,我們將這段長度爲1的線段劃分成M等份,這裏M>>V,這樣可以保證每個詞對應的線段都會劃分成對應的小塊。而M份中的每一份都會落在某一個詞對應的線段上。在採樣的時候,我們只需要從M個位置中採樣出neg個位置就行,此時採樣到的每一個位置對應到的線段所屬的詞就是我們的負例詞。

https://images2017.cnblogs.com/blog/1042406/201707/1042406-20170728152731711-1136354166.png

  在word2vec中,M取值默認爲108。

具體應用:

基於Negative SamplingCBOW模型

基於Negative Sampling的Skip-Gram模型

 

代碼

https://github.com/tmikolov/word2vec/blob/master/word2vec.c

在源代碼中,基於Negative Sampling的CBOW模型算法在464-494行,基於Negative Sampling的Skip-Gram的模型算法在520-542行。大家可以對着源代碼再深入研究下算法。

在源代碼中,neule對應我們上面的e, syn0對應我們的xw, syn1neg對應我們的θwi, layer1_size對應詞向量的維度,window對應我們的c。negative對應我們的neg, table_size對應我們負採樣中的劃分數M。

 另外,vocab[word].code[d]指的是,當前單詞word的,第d個編碼,編碼不含Root結點。vocab[word].point[d]指的是,當前單詞word,第d個編碼下,前置的結點。這些和基於Hierarchical Softmax的是一樣的。

以上就是基於Negative Sampling的word2vec模型,希望可以幫到大家,後面會講解用gensim的python版word2vec來使用word2vec解決實際問題。

 

 

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