word2vec
在NLP領域中,為了能表示人類的語言符號,一般會把這些符號轉成一種數學向量形式以方便處理,我們把語言單詞嵌入到向量空間中就叫詞嵌入(word embedding)。谷歌開源的word2vec則是這麼一種詞嵌入工具,它能生成詞向量,通過詞向量可以很好地度量詞與詞之間的相似性。word2vec採用的模型包含了連續詞袋模型(CBOW)和Skip-Gram模型。通過它可以在大資料量上進行高效訓練從而得到詞向量。
n-gram語言模型
在討論詞向量時先看NLP中很重要的統計語言模型,簡單來說就是計算某個句子出現的概率,比如“我今天上班遲到了”這句話在整個語言下的概率,一般我們會通過一個大的語料庫來進行統計。
用數學語言來描述,假設我們的句子為
,則該句子的概率為
其中P(w1)表示第一個詞w1出現的概率;P(w2|w1)是第一個詞出現的前提下第二個詞出現的概率;以此類推。比如s=“我今天上班遲到了”,那麼P(s)=P(我)P(今天|我)P(上班|我,今天)P(遲到了|我,今天,上班)。
上面的語言模型的引數空間太大而且資料稀疏,導致在實際中基本無法使用。所以我們需要一個假設,某個詞出現的概率只與它前面的一個或幾個詞有關,這個假設就是馬爾科夫假設。有了它問題就變簡單了,某個句子出現的概率就可以用下面表示(這裡假設某詞只與前面一個詞相關)。
n-gram這種處理序列資訊的方式依然存在侷限性,比如當n大於3時基本就無法處理了,引數空間太大。另外它不能表示詞與詞之間的關聯性。於是我們看下另外一種語言模型——神經網路語言模型,雖然它並不能完全解決n的問題,但它提供了另外一種語言模型思路。實際上,在深度學習中有另外的處理方式,比如RNN、LSTM等,可以克服n-gram中n無法取太大(即無法關聯距離較遠的詞)的缺點。
one-hot形式的詞向量
在繼續瞭解神經網路語言模型之前我們先看怎麼用向量來表示詞,前面我們說過詞向量就是用來表示人類語言的一種數學化的方式,其包含了很多種表示方式。其中最簡單的向量方式即是one-hot形式。
它的處理方式簡單粗暴,一般就是統計詞庫包含的所有V個詞,然後將這V個詞固定好順序,然後每個詞就可以用一個V維的稀疏向量來表示,向量中只有在該詞出現的位置的元素才為1,其它元素全為0。比如下面這幾個詞,第一個元素為1的表示中國,第六個元素為1的表示美國,第五個元素為1的表示日本。
中國 [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,0,0]
日本 [0,0,0,0,1,0,0,0,0,……,0,0,0,0,0,0,0]複製程式碼
從中可以看到one-hot形式的維數通常會很大,因為詞數量一般在10W級別,這會導致訓練時難度大大增加,造成維數災難。另外這麼多維只以順序資訊並且只用1和0來表示單詞,很浪費空間。再一個是這種方式的任意兩個詞都是孤立的,沒法看出兩個詞之間的相似性。於是看看有沒有改進的方法。
分散式詞向量
鑑於one-hot形式詞向量的缺點,出現了另外一種詞向量表示方式——分散式詞向量(distributed word representation)。 分散式詞向量則乾脆直接用普通的向量來表示詞向量,而元素的值為任意實數,該向量的維數可以在事前確定,一般可以為50維或100維。這時的詞向量類似如下(這裡假設用5維來表示):
中國 [1.25, 0.2, 0.3, 0.5, 0.6]
美國 [0.1, 0.3, 0.5, 0.1, 1.5]
日本 [2.2, 0.2, 0.4, 0.6, 1.0]複製程式碼
其中每個元素的具體數值則由訓練來確定。這樣一來就克服了在深度學習中可能的維度災難,而且充分利用了空間,如果使用適當的訓練方法訓練出來的詞向量可以直接根據兩個詞之間的距離來計算相似性。
神經網路語言模型
神經網路語言模型即用神經網路來訓練語言模型,最經典的模型是Bengio等人提出的三層神經網路,它思路大概是對於語料C任意一個詞w,取它的前n-1個詞作為輸入,這個跟n-gram的思路是同樣的,而w則為它的輸出,有了輸入和輸出就組成了訓練樣本了。
下面根據上圖進行講解,首先設每個詞w用m維向量來表示,則每個詞都有對應著自己的m維向量,另外設語料的總詞數為v。接著分別看三層網路,
- 輸入層,輸入層負責將前n-1個詞向量輸入,即將
輸入,而他們的連線方式只是將他們首尾拼接起來即可,這樣輸入其實就是一個m(n-1)維向量,設為X。
- 隱含層,該層節點數可自己設定,該層輸出為z = tanh(wx+p),其中w為輸入層到隱含層的權重,p為偏置項。
- 輸出層,一共有v個節點,每個節點的值為對應詞的概率,即下個詞為該詞的概率值,最後還會通過softmax激勵函式對輸出值歸一化。y值的計算公式為y = uz+q,其中u是隱含層到輸出層的權重,q為偏置項。
現在樣本集及神經網路結構都有了,接下去使用梯度下降法對其進行優化訓練就能得到一個語言模型。
通過神經網路訓練出來的語言模型自帶平滑,這個歸功於我們的啟用函式,而傳統的n-gram方式則需要我們額外做平滑化處理。而且詞向量還能表示詞語的相似性。
Skip-gram和CBOW模型
神經網路語言模型解決了概率平滑、資料稀疏及維度災難等問題,但它仍然無法徹底解決n的問題,即通過前n個詞來預測接著的單詞,這裡認為神經網路語言模型無法取n大於5。另外一個是訓練需要花費很多時間。
為了克服這些缺點,出現了CBOW模型和Skip-gram模型。它們都是通過對原始的神經網路語言模型進行改良。
另外CBOW模型和Skip-gram模型的輸入向量中不再使用one-hot形式,而是可以假設一個m維向量,初始值可以隨機設定,然後通過訓練不斷優化最後得到具體的向量值。這也就是為什麼說我們在訓練CBOW模型和Skip-gram模型時會產生一個詞向量的副產品,該詞向量是一個分散式詞向量。
以CBOW模型為例
它對原始的神經網路語言模型做了一些改造,比如把原來的隱含層去掉了,投影層直接與輸出層相連,這是因為隱含層增加了計算量,而且去掉後基本不會影響效果。投影層做的操作就是累加輸入層的所有向量,再回想一下傳統神經網路語言模型是怎麼處理輸入層的?就是向量的連線操作,將輸入層的所有向量首尾相連線。這種方式也就意味著丟棄詞語的序列資訊,這很好理解,原來方式是輸入向量首尾先連,而現在是做累和操作。
- 輸入層,對於詞w(t),取前後若干個詞作為輸入,比如前後2個詞,則w(t-2)、w(t-1)、t(t+1)、t(t+2)作為輸入。
- 投影層,對輸入層所有向量做求和累加操作。
- 輸出層,是一棵龐大的很深的二叉樹,如下圖,樹的葉子結點表示語料庫中出現的詞,比如w1 w2 w3 w4 ...wv,語料庫總共有v個不同的詞,它其實是一棵哈夫曼樹,通過語料庫中詞頻而構建的,把詞頻當做權值然後按照哈夫曼樹構造的演算法進行構造即可,這個比較簡單。
CBOW模型的訓練
訓練其實就是根據某個詞前後若干詞來預測該詞,這其實可以看成是多分類。最樸素的想法就是直接使用softmax來分別計算每個詞的對應的歸一化的概率。但對於動輒十幾萬詞彙量的場景中使用softmax計算量太大,於是需要用一種二分類組合形式的hierarchical softmax,即輸出層為一棵二叉樹。
現在看看怎麼來訓練這棵二叉樹。如下圖,每個二叉樹葉子結點表示一個詞,非葉子結點則代表詞,但它有一個權重引數\theta,每個非葉子結點的權重引數都不同,另外再約定每個節點的左邊的子節點編碼為1,右邊的子節點編碼為0。那麼從根節點開始(根節點不作編碼),詞“每天”的編碼為10,詞“運動”的編碼為00。
現在假設正確輸出為“每天”,對應的編碼為10,那麼具體是怎麼更新引數的?實際上除了葉子結點,其他節點都可以看成是一個神經元,可以看到它是一個二分類的結構,那麼通過logistic迴歸就可以實現二分類。為了找到“每天”這個詞,首先通過根節點,經過logistic分類後應該分到左邊子節點,即編碼為1,接著繼續進行logistic分類到右邊子節點,即編碼為0,然後得到最後的結果。
設w為某個詞,w前後若干個詞用$w_m$表示,二叉樹總共有s層,設從根節點到w節點經過的節點的引數為$\theta_1,\theta2,...\theta{s-1}$,比如“每天”經過的引數為$\theta_1,\theta_2$,再設從第二層節點到w節點經過的節點的編碼為$b_2,b_3,...,b_s$,則w的條件概率為,
我們知道除了葉子結點外,其他每個節點都是做logistic迴歸,有
為方便計算取對數似然函式作為目標函式,得到
其中l為語料庫,接著對目標函式做最大化優化,可以看到目標函式中有兩個引數需要學習,一個是$\theta$一個是輸入x,x學習就是得到我們的詞向量副產品,而$\theta$則是CBOW模型的引數。分別對兩者求偏導,有
有了偏導就可以用梯度上升法了,繼續求另外一個偏導,有
這樣,兩個向量引數都可以通過梯度上升法更新訓練了。
========廣告時間========
鄙人的新書《Tomcat核心設計剖析》已經在京東銷售了,有需要的朋友可以到 item.jd.com/12185360.ht… 進行預定。感謝各位朋友。
=========================
歡迎關注: