主要參考:html
http://www.cnblogs.com/Determined22/p/5804455.html
算法
http://www.cnblogs.com/Determined22/p/5807362.html
網絡
http://blog.csdn.net/u014595019/article/details/51943428
機器學習
http://www.open-open.com/lib/view/open1426578842601.html
分佈式
仍是先給出總結:函數
神經機率語言模型NPLM,訓練語言模型並同時獲得詞表示工具
word2vec:CBOW / Skip-gram,直接以獲得詞表示爲目標的模型。學習
CBOW(Continuous Bag-of-Words),用周圍詞預測中心詞:
優化
Skip-gram,用中心詞預測周圍詞:
ui
原始的CBOW / Skip-gram模型雖然去掉了NPLM中的隱藏層從而減小了耗時,但因爲輸出層仍然是softmax(),因此實際上依然「impractical」。
兩種加速策略,一種是Hierarchical Softmax,另外一種是Negative Sampling。
http://www.cnblogs.com/Determined22/p/5804455.html
神經機率語言模型NPLM
近年來,基於神經網絡來獲得詞表示的模型備受青睞。這類模型所獲得的詞的向量表示是分佈式表示distributed representation,一般被稱爲word embedding(詞嵌入;詞向量)。這種基於預測(predict)的模型的超參數每每要多於基於計數(count)的模型,所以靈活性要強一些。下面就簡要介紹利用神經網絡來獲得詞表示的開山之做——神經機率語言模型(NPLM, Neural Probabilistic Language Model),經過訓練語言模型,同時獲得詞表示。
語言模型是指一個詞串
{wt}Tt=1=wT1=w1,w2,...,wT
{wt}t=1T=w1T=w1,w2,...,wT 是天然語言的機率
P(wT1)
P(w1T)。 詞
wt
wt的下標
t
t 表示其是詞串中的第
t
t 個詞。根據乘法公式,有
P(w1,w2,...,wT)=P(w1)P(w2|w1)P(w3|w1,w2)...P(wT|w1,w2,...,wT−1)
P(w1,w2,...,wT)=P(w1)P(w2|w1)P(w3|w1,w2)...P(wT|w1,w2,...,wT−1)
所以要想計算出這個機率,那就要計算出
P(wt|w1,w2,...,wt−1),t∈{1,2,...,T}
P(wt|w1,w2,...,wt−1),t∈{1,2,...,T} :
P(wt|w1,w2,...,wt−1)=count(w1,w2,...,wt−1,wt)count(w1,w2,...,wt−1)
P(wt|w1,w2,...,wt−1)=count(w1,w2,...,wt−1,wt)count(w1,w2,...,wt−1)
count()是指詞串在語料中出現的次數。暫且拋開數據稀疏(若是分子爲零那麼機率爲零,這個零合理嗎?若是分母爲零,又怎麼辦?)不談,若是詞串的長度很長的話,這個計算會很是費時。n-gram模型是一種近似策略,做了一個馬爾可夫假設:認爲目標詞
wt
wt 的條件機率只與其以前的
n−1
n−1 個詞有關:
P(wt|w1,w2,...,wt−1)≈P(wt|wt−(n−1),wt−(n−2),...,wt−1)=count(wt−(n−1),wt−(n−2),...,wt−1,wt)count(wt−(n−1),wt−(n−2),...,wt−1)
P(wt|w1,w2,...,wt−1)≈P(wt|wt−(n−1),wt−(n−2),...,wt−1)=count(wt−(n−1),wt−(n−2),...,wt−1,wt)count(wt−(n−1),wt−(n−2),...,wt−1)
神經機率語言模型NPLM延續了n-gram的假設:認爲目標詞
wt
wt 的條件機率與其以前的
n−1
n−1 個詞有關。但其在計算
P(wt|w1,w2,...,wt−1)
P(wt|w1,w2,...,wt−1) 時,則使用的是機器學習的套路,而不使用上面count()的方式。那麼它是如何在訓練語言模型的同時又獲得了詞表示的呢?
圖片來源:參考資料[1],加了幾個符號
設訓練語料爲
D
D ,提取出的詞表爲
V={w1−,w2−,...,w|V|−−−}
V={w1_,w2_,...,w|V|_} 。詞
wi−
wi_ 的下標
i−
i_ 表示其是詞表中的第
i
i 個詞,區別於不帶下劃線的下標。大體說來,NPLM將語料中的一個詞串
wtt−(n−1)
wt−(n−1)t 的目標詞
wt
wt 以前的
n−1
n−1 個詞的詞向量(即word embedding,設維度爲
m
m )按順序首尾拼接獲得一個「長」的列向量
x
x ,做爲輸入層(也就是說共
(n−1)m
(n−1)m 個神經元)。而後通過權重矩陣
Hh×(n−1)m
Hh×(n−1)m 來到隱層(神經元數爲
h
h ),並用tanh函數激活。以後再通過權重矩陣
U|V|×h
U|V|×h 來到輸出層(神經元數固然爲
|V|
|V| ),並使用softmax()將其歸一化爲機率。另外存在一個從輸入層直連輸出層的權重矩陣
W|V|×(n−1)m
W|V|×(n−1)m 。因此網絡的輸出以下(隱層和輸出層加了偏置):
z=Utanh(Hx+d)+b+Wx
z=Utanh(Hx+d)+b+Wx
y^i−=P(wi−|wt−(n−1),wt−(n−2),...,wt−1)=softmax(zi−)=expzi−∑k=1|V|expzk−,wi−∈V
y^i_=P(wi_|wt−(n−1),wt−(n−2),...,wt−1)=softmax(zi_)=expzi_∑k=1|V|expzk_,wi_∈V
y^i−
y^i_ 表示目標詞是詞表中第
i
i 個詞
wi−
wi_ 的機率。
expzi−
expzi_ 表示前
n−1
n−1 個詞對詞表中第
i
i 個詞
wi−
wi_ 的能量彙集。
詞表中的每一個詞的詞向量都存在一個矩陣
C
C 中,look-up操做就是從矩陣中取出須要的詞向量。由此能夠看出,NPLM模型和傳統神經網絡的區別在於,傳統神經網絡須要學習的參數是權重和偏置;而NPLM模型除了須要學習權重和偏置外,還須要對輸入(也就是詞向量)進行學習。
那麼,模型的參數就有:
C,U,H,W,b,d
C,U,H,W,b,d 。
對於目標詞
wt
wt ,模型對它的損失爲(使用對數損失函數時,經驗風險最小化等價於極大似然估計;在本處,對數損失是交叉熵損失的一種特殊狀況)
J=−logy^t=−logP(wt|wt−(n−1),wt−(n−2),...,wt−1)=−logsoftmax(zt)
J=−logy^t=−logP(wt|wt−(n−1),wt−(n−2),...,wt−1)=−logsoftmax(zt)
那麼模型的經驗風險爲(省略了常係數)
J=−∑wtt−(n−1)∈Dlogy^t=−∑wtt−(n−1)∈DlogP(wt|wt−(n−1),wt−(n−2),...,wt−1)=−∑wtt−(n−1)∈Dlogsoftmax(zt)
J=−∑wt−(n−1)t∈Dlogy^t=−∑wt−(n−1)t∈DlogP(wt|wt−(n−1),wt−(n−2),...,wt−1)=−∑wt−(n−1)t∈Dlogsoftmax(zt)
因此接下來就可使用梯度降低等方法來迭代求取參數了。這樣便同時訓練了語言模型和詞向量。
word2vec:CBOW / Skip-gram
上面介紹的NPLM以訓練語言模型爲目標,同時獲得了詞表示。2013年的開源工具包word2vec則包含了CBOW和Skip-gram這兩個直接以獲得詞向量爲目標的模型。
這裏先介紹兩種模型的沒有加速策略的原始形式(也就是輸出層是softmax的那種。對於Skip-gram模型,做者在paper中稱之爲「impractical」),兩種加速策略將在下篇文中介紹。
與NPLM不一樣,在CBOW / Skip-gram模型中,目標詞
wt
wt 是一個詞串中間的詞而不是最後一個詞,其擁有的上下文(context)爲先後各
m
m 個詞:
wt−m,...,wt−1,wt+1,...,wt+m
wt−m,...,wt−1,wt+1,...,wt+m 。NPLM基於n-gram,至關於目標詞只有上文。後文中,「目標詞」和「中心詞」是同一律念,「周圍詞」和「上下文」是同一律念。
在CBOW / Skip-gram模型中,任一個詞
wi−
wi_ 將獲得兩個word embedding(設維度爲
n
n):做爲中心詞時的詞向量,也稱爲輸出詞向量
vi−∈Rn×1
vi_∈Rn×1 ;以及做爲周圍詞時的詞向量,也稱爲輸入詞向量
ui−∈Rn×1
ui_∈Rn×1 。詞向量的下標和詞的下標相對應,好比說目標詞
wt
wt 的詞向量就對應爲
vt
vt 和
ut
ut 。
與NPLM相似,詞表中每一個詞的詞向量都存在一個矩陣中。因爲存在兩套詞向量,所以就有兩個矩陣:輸入詞矩陣
Vn×|V|=[v1−,...,v|V|−−−]
Vn×|V|=[v1_,...,v|V|_] ,其每一列都是一個詞做爲周圍詞時的詞向量;輸出詞矩陣
U|V|×n=[u⊤1−;...;u⊤|V|−−−]
U|V|×n=[u1_⊤;...;u|V|_⊤] ,其每一行都是一個詞做爲中心詞時的詞向量。好比說若想取出詞做爲周圍詞時的詞向量,只要知道詞在詞表中的編號便可,取出的操做至關於用輸入詞矩陣乘以詞的one-hot representation。
(一)CBOW(Continuous Bag-of-Words)
不帶加速的CBOW模型是一個兩層結構,經過上下文來預測中心詞——
輸入層:
n
n 個節點,上下文共
2m
2m 個詞的詞向量的平均值;
輸入層到輸出層的鏈接邊:輸出詞矩陣
U|V|×n
U|V|×n ;
輸出層:
|V|
|V| 個節點。第
i
i 個節點表明中心詞是詞
wi−
wi_ 的機率。
若是要「看作」三層結構的話,能夠認爲——
輸入層:
2m×|V|
2m×|V|個節點,上下文共
2m
2m 個詞的one-hot representation
輸入層到投影層到鏈接邊:輸入詞矩陣
Vn×|V|
Vn×|V| ;
投影層::
n
n 個節點,上下文共
2m
2m 個詞的詞向量的平均值;
投影層到輸出層的鏈接邊:輸出詞矩陣
U|V|×n
U|V|×n ;
輸出層:
|V|
|V| 個節點。第
i
i 個節點表明中心詞是詞
wi−
wi_ 的機率。
這樣表述相對清楚,將one-hot到word embedding那一步描述了出來。但我的認爲投影層不宜稱爲「隱層」,由於我以爲隱層可能每每有加非線性的意思,而這裏沒有。
圖片來源:參考資料[5],把記號都改爲和本文一致
首先,將中心詞
wt
wt 的上下文
ct
ct :
wt−m,...,wt−1,wt+1,...,wt+m
wt−m,...,wt−1,wt+1,...,wt+m 由one-hot representation(
xt+j
xt+j )轉爲輸入詞向量(
vt+j
vt+j ):
vt+j=Vxt+j,j∈{−m,...,m}∖{0}
vt+j=Vxt+j,j∈{−m,...,m}∖{0}
進而將上下文的輸入詞向量
vt−m,...,vt−1,vt+1,...,vt+m
vt−m,...,vt−1,vt+1,...,vt+m 求平均值,做爲模型輸入:
v^t=12m∑jvt+j,j∈{−m,...,m}∖{0}
v^t=12m∑jvt+j,j∈{−m,...,m}∖{0}
這一步叫投影(projection)。能夠看出,CBOW像詞袋模型(BOW)同樣拋棄了詞序信息。丟掉詞序看起來不太好,不過開個玩笑的話:「研表究明,漢字的序順並不定一能影閱響讀,事證明明瞭當你看這完句話以後才發字現都亂是的」。
與NPLM不一樣,CBOW模型沒有隱藏層,投影以後就用softmax()輸出目標詞是某個詞的機率,進而減小了計算時間:
z=Uv^t
z=Uv^t
y^i−=P(wi−|wt−m,...,wt−1,wt+1,...,wt+m)=softmax(zi−)=softmax(u⊤i−v^t),wi−∈V
y^i_=P(wi_|wt−m,...,wt−1,wt+1,...,wt+m)=softmax(zi_)=softmax(ui_⊤v^t),wi_∈V
那麼模型的參數就是兩個詞向量矩陣:
U,V
U,V 。
對於中心詞
wt
wt ,模型對它的損失爲
J=−logy^t=−logP(wt|wt−m,...,wt−1,wt+1,...,wt+m)=−logsoftmax(zt)=−logexp(u⊤tv^t)∑|V|k=1exp(u⊤k−v^t)=−u⊤tv^t+log∑k=1|V|exp(u⊤k−v^t)=−zt+log∑k=1|V|expzk−
J=−logy^t=−logP(wt|wt−m,...,wt−1,wt+1,...,wt+m)=−logsoftmax(zt)=−logexp(ut⊤v^t)∑k=1|V|exp(uk_⊤v^t)=−ut⊤v^t+log∑k=1|V|exp(uk_⊤v^t)=−zt+log∑k=1|V|expzk_
因此模型的經驗風險爲
J=−∑wt+mt−m∈Dlogyt^=−∑wt+mt−m∈DlogP(wt|wt−m,...,wt−1,wt+1,...,wt+m)=−∑wt+mt−m∈Dlogsoftmax(zt)
J=−∑wt−mt+m∈Dlogyt^=−∑wt−mt+m∈DlogP(wt|wt−m,...,wt−1,wt+1,...,wt+m)=−∑wt−mt+m∈Dlogsoftmax(zt)
下面開始是很是無聊的求導練習。。。
若是用SGD來更新參數的話,只需求出模型對一個樣本的損失的梯度。也就是說上式的求和號能夠沒有,直接對
J
J 求梯度,來更新參數。
I. 首先是對輸出詞矩陣
U⊤=[u1−,...,u|V|−−−]
U⊤=[u1_,...,u|V|_] :
由於
zi−=u⊤i−v^t
zi_=ui_⊤v^t ,因此
∂J∂ui−=∂zi−∂ui−∂J∂zi−=v^t∂J∂zi−
∂J∂ui_=∂zi_∂ui_∂J∂zi_=v^t∂J∂zi_ (這裏的
∂J∂zi−
∂J∂zi_ 有點像BP算法中的
δ
δ ),那麼先求
∂J∂zi−
∂J∂zi_ :
(1) 對
∀wi−∈V∖{wt}
∀wi_∈V∖{wt} ,有
yi−=0
yi_=0,那麼
∂J∂zi−=∂(−zt+log∑|V|k=1expzk−)∂zi=0+∂∑|V|k=1expzk−∂zi−∑k=1|V|expzk−=expzi−∑k=1|V|expzk−=y^i−=y^i−−yi−
∂J∂zi_=∂(−zt+log∑k=1|V|expzk_)∂zi=0+∂∑k=1|V|expzk_∂zi_∑k=1|V|expzk_=expzi_∑k=1|V|expzk_=y^i_=y^i_−yi_
(2) 對
wi−=wt
wi_=wt ,有
yi−=1
yi_=1,那麼
∂J∂zi−=∂J∂zt=−1+y^t=y^i−−yi−
∂J∂zi_=∂J∂zt=−1+y^t=y^i_−yi_
可見兩種情形的結果是統一的。
所以有
∂J∂ui−=(y^i