本文摘錄整編了一些理論介紹,推導了word2vec中的數學原理,理論部分大量參考《word2vec中的數學原理詳解》。
背景
語言模型
在統計自然語言處理中,語言模型指的是計算一個句子的概率模型。
傳統的語言模型中詞的表示是原始的、面向字符串的。兩個語義相似的詞的字符串可能完全不同,比如“番茄”和“西紅柿”。這給所有NLP任務都帶來了挑戰——字符串本身無法儲存語義信息。該挑戰突出表現在模型的平滑問題上:標注語料是有限的,而語言整體是無限的,傳統模型無法借力未標注的海量語料,只能靠人工設計平滑算法,而這些算法往往效果甚微。
神經概率語言模型(Neural Probabilistic Language Model)中詞的表示是向量形式、面向語義的。兩個語義相似的詞對應的向量也是相似的,具體反映在夾角或距離上。甚至一些語義相似的二元詞組中的詞語對應的向量做線性減法之后得到的向量依然是相似的。詞的向量表示可以顯著提高傳統NLP任務的性能,例如《基於神經網絡的高性能依存句法分析器》中介紹的詞、詞性、依存關系的向量化對正確率的提升等。
從向量的角度來看,字符串形式的詞語其實是更高維、更稀疏的向量。若詞匯表大小為N,每個字符串形式的詞語字典序為i,則其被表示為一個N維向量,該向量的第i維為1,其他維都為0。漢語的詞匯量大約在十萬這個量級,十萬維的向量對計算來講絕對是個維度災難。而word2vec得到的詞的向量形式(下文簡稱“詞向量”,更學術化的翻譯是“詞嵌入”)則可以自由控制維度,一般是100左右。
word2vec
word2vec作為神經概率語言模型的輸入,其本身其實是神經概率模型的副產品,是為了通過神經網絡學習某個語言模型而產生的中間結果。具體來說,“某個語言模型”指的是“CBOW”和“Skip-gram”。具體學習過程會用到兩個降低復雜度的近似方法——Hierarchical Softmax或Negative Sampling。兩個模型乘以兩種方法,一共有四種實現。本文理論部分要詳細闡明的是“CBOW”模型以及Hierarchical Softmax方法。
Hierarchical Softmax
模型共同點
無論是哪種模型,其基本網絡結構都是在下圖的基礎上,省略掉hidden layer:
為什么要去掉這一層呢?據說是因為word2vec的作者嫌從hidden layer到output layer的矩陣運算太多了。於是兩種模型的網絡結構是:
其中w(t)代表當前詞語位於句子的位置t,同理定義其他記號。在窗口內(上圖為窗口大小為5),除了當前詞語之外的其他詞語共同構成上下文。
CBOW
原理
CBOW 是 Continuous Bag-of-Words Model 的縮寫,是一種根據上下文的詞語預測當前詞語的出現概率的模型。其圖示如上圖左。
CBOW是已知上下文,估算當前詞語的語言模型。其學習目標是最大化對數似然函數:
其中,w表示語料庫C中任意一個詞。從上圖可以看出,對於CBOW,
輸入層是上下文的詞語的詞向量(什么!我們不是在訓練詞向量嗎?不不不,我們是在訓練CBOW模型,詞向量只是個副產品,確切來說,是CBOW模型的一個參數。訓練開始的時候,詞向量是個隨機值,隨着訓練的進行不斷被更新)。
投影層對其求和,所謂求和,就是簡單的向量加法。
輸出層輸出最可能的w。由於語料庫中詞匯量是固定的|C|個,所以上述過程其實可以看做一個多分類問題。給定特征,從|C|個分類中挑一個。
對於神經網絡模型多分類,最朴素的做法是softmax回歸:
softmax回歸需要對語料庫中每個詞語(類)都計算一遍輸出概率並進行歸一化,在幾十萬詞匯量的語料上無疑是令人頭疼的。
不用softmax怎么樣?比如SVM中的多分類,我們都知道其多分類是由二分類組合而來的:
這是一種二叉樹結構,應用到word2vec中被作者稱為Hierarchical Softmax:
上圖輸出層的樹形結構即為Hierarchical Softmax。
非葉子節點相當於一個神經元(感知機,我認為邏輯斯諦回歸就是感知機的輸出代入f(x)=1/(1+e^x)),二分類決策輸出1或0,分別代表向下左轉或向下右轉;每個葉子節點代表語料庫中的一個詞語,於是每個詞語都可以被01唯一地編碼,並且其編碼序列對應一個事件序列,於是我們可以計算條件概率。
在開始計算之前,還是得引入一些符號:
-
從根結點出發到達w對應葉子結點的路徑.
-
路徑中包含結點的個數
-
路徑
中的各個節點
-
詞w的編碼,
表示路徑
第j個節點對應的編碼(根節點無編碼)
路徑
中非葉節點對應的參數向量
在訓練階段,當給定一個上下文,要預測后面的詞(Wn)的時候(word2vec的CBOW和Skip-gram都不是預測后面的詞,都是在中間的詞上做文章,但是本文這么寫並不影響理解),實際上我們知道要的是哪個詞(Wn),而Wn是肯定存在於二叉樹的葉子節點的,因此它必然有一個二進制編號,如”010011″,那么接下來我們就從二叉樹的根節點一個個地去遍歷,而這里的目標就是預測這個詞的二進制編號的每一位!即對於給定的上下文,我們的目標是使得預測詞的二進制編碼概率最大。我們給出w的條件概率:
這是個簡單明了的式子,從根節點到葉節點經過了-1個節點,編碼從下標2開始(根節點無編碼),對應的參數向量下標從1開始(根節點為1)。
其中,每一項是一個邏輯斯諦回歸:
考慮到d只有0和1兩種取值,我們可以用指數形式方便地將其寫到一起:
我們的目標函數取對數似然:
將代入上式,有
這也很直白,連乘的對數換成求和。不過還是有點長,我們把每一項簡記為:
怎么最大化對數似然函數呢?分別最大化每一項即可(這應該是一種近似,最大化某一項不一定使整體增大,具體收斂的證明還不清楚)。怎么最大化每一項呢?先求函數對每個變量的偏導數,對每一個樣本,代入偏導數表達式得到函數在該維度的增長梯度,然后讓對應參數加上這個梯度,函數在這個維度上就增長了。這種白話描述的算法在學術上叫隨機梯度上升法,詳見更規范的描述。
每一項有兩個參數,一個是每個節點的參數向量,另一個是輸出層的輸入
,我們分別對其求偏導數:
因為sigmoid函數的導數有個很棒的形式:
於是代入上上式得到:
合並同類項得到:
於是的更新表達式就得到了:
其中,是機器學習的老相好——學習率,通常取0-1之間的一個值。學習率越大訓練速度越快,但目標函數容易在局部區域來回抖動。
再來的偏導數,注意到
中
和
是對稱的,所有直接將
的偏導數中的
替換為
,得到關於
的偏導數:
於是的更新表達式也得到了。
不過是上下文的詞向量的和,不是上下文單個詞的詞向量。怎么把這個更新量應用到單個詞的詞向量上去呢?word2vec采取的是直接將
的更新量整個應用到每個單詞的詞向量上去:
其中,代表上下文中某一個單詞的詞向量。我認為應該也可以將其平均后更新到每個詞向量上去,無非是學習率的不同,歡迎指正。
如果沒有使用這種二叉樹,而是直接從隱層直接計算每一個輸出的概率——即傳統的softmax,就需要對|V|中的每一個詞都算一遍,這個過程時間復雜度是O(|V|)的。而使用了二叉樹(如word2vec中的Huffman樹),其時間復雜度就降到了O(log2(|V|)),速度大大地加快了。
參考文獻:
1. http://www.hankcs.com/nlp/word2vec.html