在許多自然語言處理任務中,許多單詞表達是由他們的tf-idf分數決定的。即使這些分數告訴我們一個單詞在一個文本中的相對重要性,但是他們並沒有告訴我們單詞的語義。Word2Vec是一類神經網絡模型——在給定無標簽的語料庫的情況下,為語料庫的單詞產生一個能表達語義的向量。
word2vec是Google開源的一款用於詞向量計算 的工具,可以很好的度量詞與詞之間的相似性;
word2vec建模是指用CBoW模型或Skip-gram模型來計算不同 詞語的向量(word vector) 這里有一個關於word2cev的實戰代碼
CBoW是給定上下文來預測目標詞、Skip-gram給定輸入詞預測上下文,但最終都會得到下圖的“詞向量矩陣W”
Statistical Language Model (統計語言模型)
在深入word2vec之前,首先回顧下nlp中的一個基本問題:如何計算一段文本序列在某種語言下出現的概率?(Ngram)統計語言模型給出了這一類問題的一個基本解決框架。對於一段文本序列:$S=w_{1},w_{2},...,w_{T}$它的概率可表示為:$P(S)=P(w_{1},w_{2},...,w_{T})=\prod_{t=1}^{T}p(w_{t}|w_{1},w_{2},...,w_{t-1})$,即將序列的聯合概率轉化為一系列條件概率的乘積。問題變成了如何去預測這些給定previous words下的條件概率:$p(w_{t}|w_{1},w_{2},...,w_{t-1})$,由於其巨大的參數空間,這樣一個原始的模型在實際中並沒有什么用。我們更多的是采用其簡化版本——Ngram模型:$p(w_{t}|w_{1},w_{2},...,w_{t-1})\approx p(w_{t}|w_{t-n+1},...,w_{t-1})$
常見的如bigram模型(N=2)和tirgram模型(N=3)。事實上,由於模型復雜度和預測精度的限制,我們很少會考慮N>3的模型。我們可以用最大似然法去求解Ngram模型的參數——等價於去統計每個Ngram的條件詞頻。為了避免統計中出現0概率問題(一段從未在訓練集中出現過的Ngram片段會使整個序列的概率為0),人們基於原始的Ngram模型進一步發展出了back-off trigram模型(用低階的bigram和unigram代替0概率的trigram)和interpolated trigram模型(將條件概率表示為unigram、bigram、trigram三者的線性函數)。
Distributed Representation(分布特征表示語義)
不過Ngram模型仍有局限性。首先無法處理N>3的詞序列(實際應用中>3會發生參數空間的爆炸式增長,維度災難問題),其次它並沒有考慮詞與詞之間的內在聯系性(只是概率的詞頻統計)。例如,考慮"the cat is walking in the bedroom"這句話。如果我們在訓練語料中看到了很多類似“the dog is walking in the bedroom”或是“the cat is running in the bedroom”這樣的句子,那么,即使我們沒有見過這句話,也可以從“cat”和“dog”(“walking”和“running”)之間的相似性,推測出這句話的概率。然而, Ngram模型做不到。
於是,人們就自然而然的想到,能否用一個連續的稠密向量去刻畫一個word的特征呢? 這樣我們不僅可以去刻畫詞與詞之間的相似度,還可以建立一個從向量到概率的平滑函數模型,使得相似的詞向量可以映射到相近的概率空間上。這個稠密連續向量也被稱為word的distributed representation(分布式表示)。
事實上,這個概念在信息檢索(Information Retrieval)領域早就已經被廣泛使用了。只不過在IR領域里,這個概念被稱為向量空間模型(Vector Space Model,以下簡稱VSM)。
VSM是一種Statistical Semantics Hypothesis:語言的統計特征隱藏着語義的信息(Statistical pattern of human word usage can be used to figure out what people mean)。例如,兩篇具有相似詞分布的文檔可以被認為是有着相近的主題。這個Hypothesis有很多衍生版本。其中,比較廣為人知的兩個版本是Bag of Words Hypothesis和Distributional Hypothesis。前者是說,一篇文檔的詞頻(而不是詞序)代表了文檔的主題;后者是說,上下文環境相似的兩個詞有着相近的語義。后面我們會看到word2vec算法也是基於Distributional的假設。
那么,VSM是如何將稀疏離散的one-hot詞向量映射為稠密連續的Distributional Representation的呢?簡單來說,基於Bag of Words Hypothesis(詞袋假設),我們可以構造一個term-document(關聯矩陣)矩陣A:矩陣的行Ai,: 對應着詞典里的一個word,矩陣的列A:,j 對應着訓練預料里的一篇文檔;矩陣里的元素Ai,j代表着word wi 在文檔Dj 中出現的次數(或頻率)。那么我們就可以提取列向量作為word的語義向量(不過,實際應用中,我們更多的是用列向量做為文檔的主題向量,即一篇文檔的詞頻代表了文檔的主題)
term-document關聯矩陣:
doc 1:new home sales top forecasts doc 2:home sales rise in july
doc 3:increase in home sales in july doc 4: july new home sales rise
類似的,我們可以基於Distributional Hypothesis(分布式特征表達猜想/上下文特征表示)構造一個word-context的矩陣。與term-document相比,矩陣的列變成了context里的word,矩陣的元素也變成了一個context窗口里word的共現次數。word-context矩陣 通過統計一個事先指定大小的窗口內的word共現次數,不僅可以刻畫word的語義信息,還在一定程度上反映了word的語法結構信息。
word-context類語義矩陣:
doc1:I like deep learning doc2:I like NLP doc3: I enjoy flying
設置窗口的大小為1, 得到word-context矩陣:
注意,這兩類矩陣的行向量所計算的相似度有着細微的差異:term-document矩陣會給經常出現在同一篇document里的兩個word賦予更高的相似度;而word-context矩陣會給那些有着相同context的兩個word賦予更高的相似度。后者相對於前者是一種更高階的相似度,因此在傳統的信息檢索領域中得到了更加廣泛的應用。
Neural Network Language Model(神經網絡語言模型)
鑒於Ngram等模型的不足,2003年,Bengio等人發表了一篇開創性的文章:A neural probabilistic language model。在這篇文章里,他們總結出了一套用神經網絡建立統計語言模型的框架(Neural Network Language Model,以下簡稱NNLM),並首次提出了word embedding的概念(雖然沒有叫這個名字),從而奠定了包括word2vec在內后續研究word representation learning的基礎。
NNLM模型的基本思想可以概括如下:
- 假定詞表中的每一個word都對應着一個連續的特征向量;
- 假定一個連續平滑的 概率模型,輸入一段詞向量的序列,可以輸出這段序列的 聯合概率;
- 同時學習詞向量的權重和概率模型里的參數。
值得注意的一點是,這里詞向量也是要學習的參數。
在03年的論文中,Bengio等人采用了一個簡單的前向反饋神經網絡 $f(w_{t-n+1,...,w_{t}})$來擬合一個詞序列的條件概率
$p(w_{t}|w_{1},w_{2},...,w_{t-1})$(計算Ngram概率)。整個模型的網絡結構見下圖:
我們將整個模型拆分成兩部分加以理解:
- 首先是一個線性的Embedding層。它將輸入的N-1個one-hot詞向量,通過一個共享的D×V的矩陣C,映射為N-1個分布式的詞向量(distributed vector)。其中,V是詞典的大小,D是Embedding向量的緯度(一個先驗參數,可以調整)。C矩陣(C矩陣初始值是隨機初始化的)里存儲了要學習的word vector。
- 其次是一個簡單的前向反饋網絡g。它由一個tanh(激活函數)隱層和一個softmax(多分類輸出占比)輸出層組成。通過將Embedding層輸出的N-1個詞向量映射為一個長度為D的概率分布向量,從而對詞典中的word在輸入context下的條件概率作出預估:
$p(w_{i}|w_{1},w_{2},...,w_{t-1})\approx f(w_{i},w_{t-1},...,w_{t-n+1})=g(w_{i},C(w_{t-n+1}),...,C(w_{t-1}))$
我們可以通過最小化一個cross-entropy(交叉熵)的正則化損失函數來調整模型的參數θ:$L(\theta)=\frac{1}{T}\sum_{t}log f(w_{t},w_{t-1},...,w_{t-n+1})+R(\theta)$
其中,模型的參數θ包含了Embedding層矩陣C的元素,和前向反饋神經網絡g里的權重。這是一個巨大的參數空間。不過,在用SGD(一種梯度下降的方法)學習更新模型的參數時,並不是所有的參數都需要調整(例如未在輸入的context中出現的 詞對應的詞向量)。計算的瓶頸主要在softmax層的歸一化函數上(需要對詞典中所有的word計算一遍條件概率)。
下面給出softmax函數曲線和計算方程($S_{i}= \frac{e^i}{ \sum_{j} e^j}$)及計算方法:
∞∞
(圖片來自網絡)
關於softmax詳細講解,請看這個鏈接
然而,拋棄復雜的參數空間,我們不禁要問,為什么這樣一個簡單的模型會取得巨大的 成功呢?
仔細觀察這個模型你就會發現,它其實在同時解決兩個問題:一個是統計語言模型里關注的條件概率 $p(w_{t}|context)$的計算;一個是向量空間模型里關注的詞向量的表達。而這兩個問題本質上並不獨立。通過引入連續的詞向量和平滑的概率模型,我們就可以在一個連續空間里對序列概率進行建模,從而從根本上緩解數據稀疏性和緯度災難的問題。另一方面,以條件概率$p(w_{t}|context)$為學習目標去更新詞向量的權重,具有更強的導向性,同時也與VSM里的Distributional Hypothesis不謀而合。
CBoW & Skip-gram Model(詞向量模型算法)
一個問題是,同Ngram模型一樣,NNLM模型只能處理定長的序列。在03年的論文里,Bengio等人將模型能夠一次處理的序列長度N提高到了5,雖然相比bigram和trigram已經是很大的提升,但依然缺少靈活性。因此,Mikolov等人在2010年提出了一種RNNLM模型,用遞歸神經網絡代替原始模型里的前向反饋神經網絡,並將Embedding層與RNN里的隱藏層合並,從而解決了變長序列的問題。
另一個問題就比較嚴重了。NNLM的訓練太慢了。即便是在百萬量級的數據集上,即便是借助了40個CPU進行訓練,NNLM也需要耗時數周才能給出一個稍微靠譜的解來。顯然,對於現在動輒上千萬甚至上億的真實語料庫,訓練一個NNLM模型幾乎是一個impossible mission。
這時候,還是那個Mikolov站了出來。他注意到,原始的NNLM模型的訓練其實可以拆分成兩個步驟:
- 用一個簡單模型訓練出連續的詞向量;
- 基於詞向量的表達(不會同時訓練詞向量了),訓練一個連續的Ngram神經網絡模型。
而NNLM模型的計算瓶頸主要在第二步。
如果我們只想得到word的連續特征向量,是不是可以對第二步里的神經網絡模型進行簡化呢?Mikolov是這么想的,也是這么做的。他在2013年一口氣推出了兩篇paper,並開源了一款計算詞向量的工具——至此,word2vec橫空出世,主角閃亮登場。
有了前邊的基礎,理解word2vec就變的很簡單了。首先,我們對原始的NNLM模型做如下改造:
- 移除前向反饋神經網絡中非線性的hidden layer,直接將中間層的Embedding layer與輸出層的softmax layer連接;
- 忽略上下文環境的序列信息:輸入的所有詞向量均匯總到同一個Embedding layer;
- 將Future words納入上下文環境
得到的模型稱之為CBOW模型(Continuous Bag-of-Words Model),也是word2vec算法的第一個模型。上邊可以不看 :P
CBoW模型
簡單介紹下圖二 CBOW參數的含義:
- 輸入層(Input layer):上下文單詞的onehot。(假設單詞空間向量dim為V,V的值為詞典中所有詞的個數,上下文單詞個數為C)
- 所有onehot分別乘以共享的輸入權重矩陣W(V*N的矩陣,N為自己設定的數,權重矩陣W初始值為隨機初始化的任意值)
- N-dim隱藏層向量的值為所有的C個onehot與W相乘,再相加取平均,size為1*N
- 再乘以輸出權重矩陣W'(矩陣size為N*V)
- 得到向量(1*V),激活函數(softmax)處理得到V-dim概率分布(PS:因為是onehot,每個一維都代表着一個單詞),概率最大的index所表示的單詞為預測出的中間詞( target word )
- 與true label的onehot(上左圖中的true label為 w(t))作比較,誤差越小越好
所以需要定義loss function(一般為交叉熵代價函數),采用梯度下降算法更新W和W'。訓練完畢后,輸入層的每個單詞與矩陣W相乘得到的向量就是我們想要的詞向量(word embedding)這個W矩陣(所有單詞的word embedding)也叫做look up table。
詳細例子,請看這里
Skip-gram模型
CBoW模型依然是從context對target word的預測中學習到詞向量的表達。反過來,我們能否從target word對context的預測中學習到word vector呢?答案是可以的:
關於skip-gram的詳細介紹,請看這里
這個模型被稱為Skip-gram模型(名稱源於該模型在訓練時會對上下文環境里的word進行采樣)。
如果將Skip-gram模型的前向計算過程寫成數學形式(只是一個softmax),我們得到:
$p(w_{o}|w_{i})=\frac{e^{U_{o} \cdot V_{i}}}{\sum_{j}e^{U_{j} \cdot V_{i}}}$
其中,Vi 是Embedding層矩陣里的列向量,也被稱為$w_{i}$的input vector。$U_{j}$是softmax層矩陣里的行向量,也被稱為$w_{i}$的output vector。
因此,Skip-gram模型的本質是計算輸入word的input vector與目標word的output vector之間的余弦相似度,並進行softmax歸一化。我們要學習的模型參數正是這兩類詞向量。
然而,直接對詞典里的V個詞計算相似度並歸一化,顯然是一件及其耗時的impossible mission。為此,Mikolov引入了兩種優化算法:層次Softmax(Hierarchical Softmax)和負采樣(Negative Sampling)。
Hierarchical Softmax(層次Softmax)
層次Softmax的方法最早由Bengio在05年引入到語言模型中。它的基本思想是將復雜的歸一化概率分解為一系列條件概率乘積的形式:
$p(v|context)=\prod_{i=1}^{m}p(b_{i}(v)|b_{1}(v),...,b_{i-1}(v),context)$
其中,每一層條件概率對應一個二分類問題,可以通過一個簡單的邏輯回歸函數去擬合。這樣我們對V個詞的概率歸一化問題,轉化成了對$logV$個詞的概率擬合問題。我們可以通過構造一顆分類二叉樹來直觀地理解這個過程。首先,我們將原始字典D划分為兩個子集D1、D2,並假設在給定的context下,target word屬於子集D1 的概率$p(w_{t} \in D_{1}| context)$服從logistical function的形式:
$p(w_{t}\in D_{1}|context)=\frac{1}{1+e^{-U_{D_{root}}}} \cdot V_{w_{t}}$ (UDroot和Vwt 都是模型的參數)
接下來,我們可以對子集D1和D2進一步划分。重復這一過程,直到集合里只剩下一個word。這樣,我們就將原始大小為V的字典D轉換成了一棵深度為logV的二叉樹。樹的葉子節點與原始字典里的word一 一對應;非葉節點則對應着某一類word的集合。顯然,從根節點出發到任意一個葉子節點都只有一條唯一路徑——這條路徑也編碼了這個葉子節點所屬的類別。
同時,從根節點出發到葉子節點也是一個隨機游走的過程。因此,我們可以基於這顆二叉樹對葉子節點出現的似然概率進行計算。例如,對於訓練樣本里的一個target word wt,假設其對應的編碼為{1,0,1...,1},則我們構造的似然函數為:
$p(w_{t}|context)=p(D_{1}=1|context)p(D_{2}=0|D_{1}=1)...p(w_{t}|D_{k}=1)$
乘積中的每一項都是一個邏輯回歸的函數。
我們可以通過最大化這個似然函數來求解二叉樹上的參數——非葉節點上的向量,用來計算游走到某一個子節點的概率。
層次Softmax是一個很巧妙的模型。它通過構造一顆二叉樹,將目標概率的計算復雜度從最初的V降低到了logV的量級。不過付出的代價時人為增強了詞與詞之間的耦合性。例如,一個word出現的條件概率的變化,會影響到其路徑上所有非葉子節點的概率變化,間接的對其他word出現的條件概率帶來不同程度的影響。因此,構造一顆有意義的二叉樹就顯得十分重要。實踐證明,在實際的應用中,基於Huffman編碼的二叉樹可以滿足大部分應用場景的需求。
Negative Sampling(負采樣)
負采樣的思想最初來源於一種叫做Noise-Contrastive Estimation的算法,原本時為了解決那些無法歸一化的概率模型的參數預估問題。與改造模型輸出概率的層次Softmax算法不同,NCE算法改造的時模型的似然函數。
以Skip-gram模型為例,其原始的似然函數對應着一個Multinomial的分布。在用最大似然法求解這個似然函數時,我們得到一個cross-entropy的損失函數 :
$J(\theta)=- \frac {1}{T} \sum_{t=1}^T \sum_{-c \le j \le ,j \ne 0} logp(w_{t+j}|w_{t})$
式中的$p(w_{t+j}|w_{t})$是一個在整個字典上的歸一化的概率。
而在NCE的算法中,我們構造了這樣一個問題:對於一組訓練樣本<context, word>,我們想知道,target word的出現,是來自於context的驅動,還是一個事先假定的背景噪聲的驅動?顯然,我們可以用一個邏輯函數來回答這個問題:
$p(D=1|w,context)= \frac{p(w|context)}{p(w|context)+k_{p_{n}}(w)}=\sigma (logp(w|context)-logkp_{n}(w))$
這個式子給出了一個target word w來自於context驅動的概率。其中,k是一個先驗參數,表明噪聲的采樣頻率。p(w | context)是一個非歸一化的概率分布,這里采用softmax歸一化函數中的分子部分。pn(w)則是背景噪聲的詞分布。通常采用word的unigram分布。
通過對噪聲分布的k采樣,我們得到一個新的數據集:<context,word,label>。其中,label標記了數據的來源(真實數據分布還是背景噪聲分布?)。在這個新的數據集上,我們就可以用最大化上式中邏輯回歸的似然函數來求解模型的參數。
而Mikolov在2013年的論文里提出的負采樣算法,是NCE的一個簡化版本。在這個算法里,Mikolov拋棄了NCE似然函數中對噪聲的依賴,直接用原始softmax函數里的分子定義了邏輯回歸函數,進一步簡化了計算:
$p(D=1|w_{0},w_{i})=\sigma (U_{o} \cdot V_{i})$
此時,模型相應的目標函數變為:
$J(\theta)=log \sigma (U_{o} \cdot V_{i})+ \sum_{j=1}^{k}E_{w_{j} \sim p_{n}(w)}[log \sigma (-U_{j} \cdot V_{i})]$
除了這里介紹的層次Softmax和負采樣的優化算法,Mikolov在13年的論文里還介紹了另一個trick:下采樣(subsample)。其基本思想是在訓練時依賴概率隨機丟棄那些高頻的詞:
$p_{discard}=1- \sqrt{ \frac {t}{f(x)}}$
其中,t是一個先驗參數,一般取為10-5。f(w)是w在語料中出現的頻率。實驗證明,這種下采樣技術可以顯著提高低頻詞的詞向量的准確度。
參考文獻:
- Mikolov T, Chen K, Corrado G, et al. Efficient Estimation of Word Representations in Vector Space[J]. Computer Science, 2013.(這篇文章就講了兩個模型:CBOW 和 Skip-gram)
- Mikolov T, Sutskever I, Chen K, et al. Distributed Representations of Words and Phrases and their Compositionality[J]. 2013, 26:3111-3119.(這篇文章針對Skip-gram模型計算復雜度高的問題提出了一些改進)
- Presentation on Word2Vec(這是NIPS 2013workshop上Mikolov的PPT報告)
- https://www.cnblogs.com/iloveai/p/word2vec.html word2vec詳解
- https://blog.csdn.net/bitcarmanlee/article/details/82320853 softmax函數
- https://www.jianshu.com/p/d2f0759d053c CBoW模型
- https://blog.csdn.net/u010665216/article/details/78721354 skip-gram函數
S