word embedding算法中最爲經典的算法就是今天要介紹word2vec,最早來源於Google的Mikolov的:
1、Distributed Representations of Sentences and Documents
2、Efficient estimation of word representations in vector space
也是開創了無監督詞嵌入的新局面,讓大量之後的NLP工作基於word2vec(或類似的改進工作)的詞嵌入再做其他任務。推薦看[1]的論文,相對比較容易看懂。也推薦看下[4],是本文中的公式和基本原理講解來源,因爲我只是用於筆記,不作爲商用,所以很多話如果我覺得可以理解的話我就不改了,但是中間會穿插一些自己的理解。希望通過本篇可以把word2vec再鞏固一遍。
詞向量表示
先講一講one-hot詞向量和distributed representation分佈式詞向量
-
one hot的表示形式:word vector = [0,1,0,…,0],其中向量維數爲詞典的個數|V|,當前詞對應的位置爲1,其他位置爲0。
-
distributed的表示形式:word vector = [0.171,-0.589,-0.346,…,0.863],其中向量維數需要自己指定(比如設定256維等),每個維度的數值需要通過訓練學習獲得。
雖然one-hot詞向量構造起來很容易,但通常並不是一個好選擇。一個主要的原因是,one-hot詞向量無法準確表達不同詞之間的相似度,如我們常常使用的餘弦相似度。對於向量 ,它們的餘弦相似度是它們之間夾角的餘弦值
word2vec工具的提出正是爲了解決上面這個問題 。它將每個詞表示成一個定長的向量,並使得這些向量能較好地表達不同詞之間的相似和類比關係。word2vec工具包含了兩個模型,即跳字模型(skip-gram) 和連續詞袋模型(continuous bag of words,CBOW)。接下來讓我們分別介紹這兩個模型以及它們的訓練方法。
跳字模型(skip-gram)
註解:看到這裏,就引出了word2vec的核心方法,其實就是認爲每個詞相互獨立,用連乘來估計最大似然函數,求解目標函數就是最大化似然函數。上面公式涉及到一箇中心詞向量v,以及北京詞向量u,因此呢很有趣的是,可以用一個input-hidden-output的三層神經網絡來建模上面的skip-model。
Skip-gram可以表示爲由輸入層(Input)、映射層(Projection)和輸出層(Output)組成的神經網絡(示意圖如下,來自[2]):
圖1
- 輸入的表示:輸入層中每個詞由獨熱編碼方式表示,即所有詞均表示成一個N維向量,其中N爲詞彙表中單詞的總數。在向量中,每個詞都將與之對應的維度置爲1,其餘維度的值均爲0。
- 網絡中傳播的前向過程:輸出層向量的值可以通過隱含層向量(K維),以及連接隱藏層和輸出層之間的KxN維權重矩陣計算得到。輸出層也是一個N維向量,每維與詞彙表中的一個單詞相對應。最後對輸出層向量應用Softmax激活函數,可以計算每一個單詞的生成概率。
訓練跳字模型
註解:上面的公式每一步都推薦推到一下,都很基礎。上面只求了對中心詞向量v的梯度,同理對背景詞向量的梯度,也很容易計算出來。然後就採用傳統的梯度下降(一般採用sgd)來訓練詞向量(其實我們最後關心的是中心詞向量來作爲詞的表徵。)
這裏有一個key point說下,也許大家也想到了:詞向量到底在哪裏呢?回看下前面圖1,有兩層神經網絡,第一層是input層到hidden層,這個中間的weight矩陣就是詞向量!!!
假設input的詞彙表N長度是10000,hidden層的長度K=300,左乘以一個10000長度one-hot編碼,實際上就是在做一個查表!因此,這個weight矩陣的行就是10000個詞的詞向量。很有創意是不是?再來看神經網絡的第二層,hidden到out層,中間hidden層有沒有激活函數呢?從前面建模看到,u和v是直接相乘的,沒有激活層,所以hidden是一個線性層。out層就是建模了v和u相乘,結果過一個softmax,那麼loss函數是最大似然怎麼辦呢?其實就是接多個只有一個true label(背景詞)的cross entropy loss,把這些loss求和。因爲交叉熵就是最大似然估計,如果這點不清楚的可以去網上搜一下,很容易知道。
所以呢,我們即可用前面常規的最大似然建模來理解如何對u和v的進行優化求解;也完全可以把skip-model套到上面圖1這樣的一個簡單神經網絡中,然後就讓工具自己來完成weight的訓練,就得到了我們想要的中心詞向量。
下圖是對這個過程的簡單可視化過程示意圖。左邊矩陣爲詞彙表中第四個單詞的one-hot表示,右邊矩陣表示包含3個神經元的隱藏層的權重矩陣,做矩陣乘法的結果就是從權重矩陣中選取了第四行的權重。因此,這個隱藏層的權重矩陣就是我們最終想要獲得的詞向量字典[2]
獲取訓練樣本:按照上下文窗口的大小從訓練文本中提取出詞彙對,下面以句子The quick brown fox jumps over the lazy dog爲例提取用於訓練的詞彙對,然後將詞彙對的兩個單詞使用one-hot編碼就得到了訓練用的train_data和target_data。 下面的圖中給出了一些我們的訓練樣本的例子。我們選定句子“The quick brown fox jumps over lazy dog”,設定我們的窗口大小爲2(window_size=2),也就是說我們僅選輸入詞前後各兩個詞和輸入詞進行組合。下圖中,藍色代表input word,方框內代表位於窗口內的單詞。Training Samples(輸入, 輸出)示意圖如下:
如果使用隨機梯度下降,那麼在每一次迭代裏我們隨機採樣一個較短的子序列來計算有關該子序列的損失,然後計算梯度來更新模型參數。
連續詞袋模型(CBOW)
CBOW就倒過來,用多個背景詞來預測一箇中心詞,CBOW對小型數據庫比較合適,而Skip-Gram在大型語料中表現更好[2]。但是方法和上面是很像的,因此這裏我就放下圖。推導的方法是一樣的。
訓練連續詞袋模型
我們發現,不論是跳字模型(skip-gram) 還是連續詞袋模型(CBOW),我們實際上都是取得input-hidden這個詞向量(weight矩陣),而不是後面帶着loss那一部分,這樣我們也很容易可以對loss(訓練方法)進行修改,這個也是下一篇要說的內容:
問:每次梯度的計算複雜度是多少?當詞典很大時,會有什麼問題?
word2vec作者很創造性地提出了2種近似訓練方法(分層softmax(hierarchical softmax)和負採樣(negative sampling)),得益於此,可以訓練大規模語料庫。
參考資料:
[1] word2vec Parameter Learning Explained,《word2vec Parameter Learning Explained》論文學習筆記
[2] Word2Vector之詳解Skip-gram(1toN)
[3] 探索:word2vec
[4] http://zh.gluon.ai/chapter_natural-language-processing/word2vec.html