詞向量簡介
無論是是機器學習還是深度學習在處理不同任務時都需要對對象進行向量化表示,詞向量(Word Vector)或稱為詞嵌入(Word Embedding)做的事情就是將詞表中的單詞映射為實數向量。(長文預警)
基於one-hot編碼的詞向量方法
最簡單方法就是將詞向量用one-hot向量來表征。
在訓練詞向量之前,我們都有一個包含我們需要的所有詞的詞表。首先,我們對每個詞進行編號,假設詞表的長度為n,則對於每一個詞的表征向量均為一個n維向量,且只在其對應位置上的值為1,其他位置都是0。
one-hot向量將每個單詞表示為完全獨立的實體,這樣的表征方法主要有兩個問題:
- 有序性問題:它無法反映文本的有序性。因為語言並不是一個完全無序的隨機序列。比如說,一個字之后只有接特定的字還能組成一個有意義的詞,特定的一系列詞按特定的順序組合在一起才能組成一個有意義的句子。
- 語義鴻溝:其無法通過詞向量來衡量相關詞之間的距離關系,即這樣的表征方法無法反映詞之間的相似程度,因為任意兩個向量的距離是相同的。
- 維度災難:高維情形下將導致數據樣本稀疏,距離計算困難,這對下游模型的負擔是很重的。
就這樣,我們有了語言模型,語言模型的出現是我得以判斷一個句子的合理性的置信度,最經典的就是N-gram模型和神經網絡語言模型(Neural Network Language Model)。
統計語言模型
我們從統計語言模型開始,來解決無序性的這個問題。
在自然語言處理中有一個基本問題:如何計算一段文本序列在某種語言下出現的概率? 為什么將其稱為一個基本問題呢?在問答系統中,對於一個問題句,如果我們能計算出每個候選句作為答案的概率,則我們只需要選取概率最大的文本作為答案。
統計語言模型給出了這一類問題的一個基本解決框架。對於一段文本序列
他們的概率可以表示為:
即將序列的聯合概率轉化為一系列條件概率的乘積。這樣,要求出一段文本的聯合概率,僅需要計算出每個詞或者每段文本在給定previous words下的條件概率:
由於其巨大的參數空間(或說過長的上文文本),這樣一個原始的模型在實際中並沒有什么用,比如文中的詞與文檔開頭的詞並沒有什么相關性。我們更多的是僅用之前的n個文本來計算當前文本的條件概率,即我們常說的N-gram模型:
當我們假設一個詞的出現不依賴於其他任何詞時,稱為unigram;當一個詞的出現依賴於上一個詞時,我們稱為bigram...
我們可以用最大似然法去求解Ngram模型的參數,即等價於去統計每個Ngram的條件詞頻。事實上,由於模型復雜度和預測精度的限制,我們很少會考慮N>3的模型。
從分布式表征到SVD分解
分布式表征(Distribution)
但是,Ngram模型仍有其局限性。
- 由於參數空間的爆炸式增長,它無法處理更長程的context(N>3);
- 其次,它雖然可以描述上下文之間的概率關系,但這種處理方式本質的數學的形式仍是一個個離散的one-hot向量,或者說Ngram僅僅解決了文本之間的轉移概率的問題,並沒有解決文本本身的表征問題。例如,假設我們在訓練語料中看到了很多類似“the dog is walking in the bedroom”或是“the cat is running in the bedroom”這樣的句子,那么,即使我們看不懂英文,也可以明白“cat”和“dog”(“walking”和“running”)之間是相似的。然而,Ngram模型能描述的只有running出現在“cat”和“dog”之后的概率都很高,但是無法表述“cat”與“dog”是這兩個詞是相似的。
- 我們知道one-hot向量的長度對應於整個詞表的長度。在動輒上完甚至上百萬的實際應用中,這樣的表征方法將面臨巨大的維度災難問題。
我們怎樣取解決這樣一個維度災難的問題呢。我們可以這樣來思考,one-hot編碼方式之所以簡單,是因為這樣的方式完美地表述了每個對象之間的個性,或者說假設每個對象之間是完全獨立的。要描述對象之間的共性,我們只需要將表征對象的維度進行壓縮,在較小的空間中用連續的稠密向量來描述每個對象的抽象特征,這個稠密向量的為一個維度對應一個特定的抽象屬性。比如說我們要描述100個人的身體素質特征,最簡單的方法是對其進行one-hot編碼,我們將對每個人得到一個長度為100的向量,但是如果我們用第一維來表示身高,第二維來表示體重,第三維...這樣我們可以用長度遠遠小於100的向量來表征一個人。相似的,我們可以用相同的方法來刻畫一段文本的特征,同時,我們還可以建立一個從向量到概率的平滑函數模型,使得相似的詞向量可以映射到相近的概率空間上,從而將Ngram模型得到的概率信息也整合到向量之中。這樣一個稠密連續向量也就是所謂的詞向量的分布式表征。
事實上,這個概念在信息檢索(Information Retrieval)領域早就已經被廣泛地使用了,當時,這個方法被稱為向量空間模型(Vector Space Model,以下簡稱VSM)。VSM主要基於兩個假說:詞袋假說(Bag of Words Hypothesis)和分布假說(Distributional Hypothesis)。前者是說,一篇文檔的詞頻(而不是詞序)代表了文檔的主題;后者是說,上下文環境相似的兩個詞有着相近的語義。
基於Bag of Words Hypothesis,我們可以構造一個term-document矩陣\(A\),矩陣的行\(A_{i,:}\)對應詞典里的一個word;矩陣的列\(A_{:,j}\)對應訓練語料里的一篇文檔;矩陣里的元素\(A_{i,j}\)代表着word \(w_i\) 在文檔 \(D_j\) 中出現的次數(或頻率)。那么,我們就可以提取行向量做為word的語義向量,或者提取列向量作為文檔的主題向量。
類似地,我們可以基於Distributional Hypothesis構造一個word-context的矩陣。此時,矩陣的列變成了context里的word,矩陣的元素也變成了一個context窗口里word的共現次數。
后面我們會看到,用SVD算法表征的詞向量就是Bag of Words Hypothesis,而word2vec算法是基於Distributional Hypothesis的。
奇異值分解(SVD)
之前我們已經清楚地講述了SVD構造詞向量的理論背景。首先,考慮到對奇異值分解不理解的同學,看完這里可以保證你完全理解奇異值分解。對奇異值分解有一定基礎的同學可以直接跳過這一小結。
簡單來說,奇異值分解是一個有着很明顯的物理意義的方法,它可以將一個比較復雜的矩陣用更小更簡單的幾個子矩陣的相乘來表示,這些小矩陣描述的是矩陣的重要的特性。就像描述一個人一樣,我們只需要簡單的描述人臉上的幾個重要特征,比如說濃眉大眼,方臉,絡腮胡,而且帶個黑框的眼鏡,你就可以在腦海中有一個較為清楚的認識。實際上,人臉上的特征是有着無數種的,之所以能這么描述,是因為這幾個特征的較其他特征更能反映人臉的特點,SVD便是這樣一個算法,讓機器學會抽取對象的重要特征。
首先,我們來回顧一下本科線性代數中學到的特征值分解,如果說一個向量\(v\)是矩陣A的特征向量,則我們可以將其表現為如下形式:
這時\(\lambda\)被稱為特征向量\(v\)對應的特征值。我們知道一個矩陣對應不同特征值的特征向量是相互正交的。而特征值分解則是將矩陣分解為
其中,\(Q\)為這個矩陣A的特征向量組成的矩陣,\(\Sigma\)是一個對角陣,對角陣的每個元素為特征向量對應的特征值。由於特征向量是相互正交的,則我們可以將特征向量看作是幾何空間的不同方向,特征值分解則是將一個矩陣分解為在不同正交方向上的向量表征,特征值則是分解后對應方向上的分量大小。如果我們需要提取這個方陣最主要的特征,則只需要找到最大的特征值及其對應的特征向量即可。
然而,特征值分解具有其自己的局限性,即變換矩陣必須為方陣。然而,實際生活中,大部分問題都不能表征為方陣的形式。比如有n個樣本,每個樣本有m個特征,此時的矩陣A可能就不是方陣。
奇異值分解則是一種可以適用於任意矩陣的一種分解方法:
假設A是一個\(n \times m\)的矩陣,則\(U\)為\(n \times n\)大小的矩陣,各個向量是相互正交的,被稱為左奇異向量;\(\Sigma\)為\(n \times m\) 大小的矩陣,僅在對角線上有值,而\(V^T\)中各個向量也是相互正交的,被稱為右奇異向量,為什么呢, 可以用下面公式簡單解釋一下特征值分解與奇異值分解之間的關系:
上式使用了:\(U^TU = I\),類似的方法我們可以用\(A^TA\)來使得\(V^TV = I\)從而確定\(V\)矩陣,而\(\Sigma\Sigma^T\)得到一個\(n \times n\)大小的矩陣,等效於\(A^TA\)矩陣的特征向量。即\(\Sigma\)的每個特征值的平方等於\(A^TA\)的特征值。從而我們實現了對任意矩陣的奇異值分解。
與特征值分解類似,我們可以用奇異值的大小來衡量對應特征向量的重要性,通常前10%甚至更少的特征值可以占據所有特征值之和的99%以上。因此,我們可以用前k個奇異值及其對應向量來描述整個矩陣,左奇異矩陣可以對列進行壓縮,右奇異矩陣可以對行進行壓縮,從而選取一部分的奇異值和奇異向量來對原矩陣進行近似的表征(即我們的PCA降維)。
\(A_{m\times n} \approx U_{m\times r}\Sigma V^T_{r\times n}\)
奇異值分解的缺點是在於分解出來的向量通常是不能很好的解釋的,這與Word2Vec類似,但這並不影響其使用
基於SVD的詞向量方法
奇異值分解的詞向量方法的應用最開始並不是用於詞向量的表征,而是應用在潛在語義索引(Latent Semantic Indexing)算法中的,感興趣的同學可以自己搜一下相關算法的原理,這里只介紹該算法中用SVD生成詞向量的方法。
由Bag of Words Hypothesis,假設我們有m個詞,n個文本,我們就可以生成一個對應的term-document矩陣\(A_{m \times n}\),如下所示:
鑒於這種co-occurrence矩陣在大量數據樣本的時候仍然存在着數據稀疏性和維度災難的問題,我們將用SVD的方法對其進行降維。對於上述矩陣,我們對其進行SVD分解並選取前3個特征值及其對應的特征向量,得到如下三個矩陣:
每個特征值的大小表示對應位置的屬性值的重要性大小,左奇異矩陣的每一行即代表每個詞的特征向量,右奇異矩陣的每一列表示每個文檔的特征向量。我們取每個向量后兩維的對應值投影到一個二維空間,如下所示
其中,一個紅色的點對應一個詞,一個藍色的點對應一個文檔。這樣我們可以對這些詞和文檔進行聚類,比如說stock和market可以放在一類,real和estate可以放在一類,按這樣的聚類結果,我們可以實現對文檔中的近義詞進行提取,同時,當用戶用詞取檢索文檔的時候,是可以基於語義(在向量空間中相近的詞)進行檢索,而不是僅僅用單個的詞進行檢索。
神經網絡語言模型(Neural Network Language Model)
鑒於Ngram等模型的不足,2003年,Bengio等人發表了一篇開創性的文章:A neural probabilistic language model。在這篇文章里,他們總結出了一套用神經網絡建立統計語言模型的框架(Neural Network Language Model,以下簡稱NNLM),並首次提出了word embedding的概念(雖然沒有叫這個名字),從而奠定了包括word2vec在內后續研究的基礎,使得NLP進入一個萬物Embedding的時代。
NNLM模型的基本思想可以概括如下:
- 假定詞表中的每一個word都對應着一個連續的特征向量;
- 假定一個連續平滑的概率模型,輸入一段詞向量的序列,可以輸出這段序列的聯合概率;
- 同時學習詞向量的權重和Ngram概率模型里的參數。
值得注意的一點是,這里的詞向量也是要學習的參數,也就是說詞向量是在訓練的過程中自動生成的。
在03年的論文里,Bengio等人采用了一個簡單的前向反饋神經網絡\(f(w_{t-n+1},...,w_{t})\)來擬合一個詞序列的條件概率\(p(w_t|w_1,w_2,...,w_{t-1})\)。整個模型的網絡結構為一個三層神經網絡。第一層為映射層,第二層為隱藏層,第三層為輸出層見下圖:
用端到端的思想來看,我們輸入一個詞的one-hot向量表征,希望得到相應的相應詞的條件概率,則神經網絡模型要做的就是擬合一個由one-hot向量映射為相應概率模型的函數。我們將上圖的網絡結構拆成兩部分來理解:
- 首先是一個線性的映射層。它將輸入的N−1個one-hot詞向量,通過一個共享的D×V的矩陣C,映射為N−1個分布式的詞向量(distributed vector)。其中,V是詞典的大小,D是Embedding向量的維度(一個先驗參數)。C矩陣里存儲了要學習的word vector,為什么這是我們需要的詞向量呢?試想一下,當我們把n個one-hot表征的詞向量詞典輸入到神經網絡中,單層的神經網絡進行的運算無非就是\(Y = W^TX\),這個操作等效於查表操作,one-hot向量將n個詞向量從Embedding層中原封不動地提取出來,如下圖所示。

這樣,我們在訓練語言模型的過程中,映射層的權值就等效為我們需要的詞向量表征。
- 其次是一個簡單的前向反饋神經網絡g。它由一個激活函數為tanh的隱藏層和一個softmax輸出(分類)層組成,,可以將我們得到的一系列輸出映射成對應概率。這樣,通過將Embedding層輸出的N−1個詞向量映射為一個長度為V的概率分布向量,從而對詞典中的word在輸入context下的條件概率做出預估:
注意到,當詞表長度和期望的詞向量維度確定的時候,第一層映射層和softmax輸出層的規模就已經確定了,而隱藏層打大小可以由我們自己指定。我們可以通過最小化一個帶正則項的cross-entropy損失函數來調整神經網絡的模型參數\(\theta\):
\(L(\theta)=\frac{1}{T}\sum_t{\log{f(w_t, w_{t-1}, ..., w_{t-n+1})}}+R(\theta)\)
上式的前半部分是輸出概率的交叉熵,后半部分是包含映射層和隱藏層的神經網絡參數的正則項,這將包含一個巨大的參數空間。不過,在每次用SGD學習更新模型的參數時,並不是所有的參數都會進行調整,只有當前context包含詞的詞向量才會被更新(因為映射層的輸出只會得到這些詞的輸出,並參與接下來的運算)。真正的計算瓶頸主要是在softmax層的歸一化函數上(需要對詞典中所有的word計算一遍條件概率)。
總結一下,這個模型解決了兩個問題:
- 一個是統計語言模型里關注的條件概率\(p(w_t|context)\)的計算;
- 一個是向量空間模型里關注的詞向量的表達。
這兩個問題本質上並不獨立。通過引入連續的詞向量和平滑的概率模型,我們就可以在一個連續空間里對序列概率進行建模,從而從根本上緩解數據稀疏性和維度災難的問題。另一方面,以條件概率\(p(w_t|context)\)。為學習目標去更新詞向量的權重,具有更強的導向性,同時也與Distributional Hypothesis不謀而合。
但NNLM模型仍然存在一系列問題:
- 一個問題是,由於NNLM模型使用的是全連接神經網絡,因此只能處理定長的序列。
- 另一個問題是,由於其巨大的參數空間,將NNLM的訓練太慢了。即便是在百萬量級的數據集上,即便是借助了40個CPU進行訓練,NNLM也需要耗時數周才能給出一個稍微靠譜的解來。顯然,對於現在動輒上千萬甚至上億的真實語料庫,訓練一個NNLM模型幾乎是一個impossible mission。
Word2Vec
由於NNLM存在一系列問題,因此其經歷了將近10年的左右才轉變為我們所熟知的word2vec。這里我盡量清晰簡潔地為大家講解word2vec的基本原理,如果想深入了解word2vec及其內部的數學推導,可以看大神peghoty的博客,這是我見過最全的word2vec原理講解
首先,針對第一個問題,Mikolov等人在2010年提出了一種RNNLM模型,用遞歸神經網絡代替原始模型里的前向反饋神經網絡,並將Embedding層與RNN里的隱藏層合並,從而解決了變長序列的問題。
對於第二個問題,同樣是Mikolov,他注意到,原始的NNLM模型的訓練其實可以拆分成兩個步驟:
- 用一個簡單模型訓練出連續的詞向量;
- 基於詞向量的表達,訓練一個連續的Ngram神經網絡模型。
而NNLM模型的計算瓶頸主要是在第二步。如果我們只是想得到word的詞向量,是不是可以對第二步里的神經網絡模型進行簡化呢?就這樣,他在2013年一口氣推出了兩篇paper,並開源了一款計算詞向量的工具——至此,word2vec橫空出世,主角閃亮登場。
有了前文的基礎,理解word2vec算法就變得很簡單了,這里也只帶領大家簡單的過一遍算法的基本原理,如果想進一步了解word2vec模型的實現細節,大家可以參考第5個參考文獻,里邊有word2vec最詳細的解釋。
總的來說,word2vec包括“兩個模型” + “兩個提速手段”
兩個模型
CBoW(Continues Bag-of-Words Model)
在兩個模型中,CBoW與之前的NNLM更為相似,簡單概括其思路就是:輸入中間詞前后共\(C\)個詞,預測中間詞,在這個過程中訓練出我們需要的詞向量矩陣。其模型結構如下圖所示:
下面講解一下該模型結構:
- 圖中 \([x_{1k}, ..., x_{Ck}]\) 表示第 \(k\) 個中心詞的前后\(C\)個上下文的 one-hot 向量
- 將 one-hot 向量輸入存放詞向量的矩陣 \(W_{V\times N}\)進行查表,\(V\)為詞表的大小,\(N\)為詞向量的維度
- 將查表得到的上下文向量直接進行求和,再通過一個\(N \times V\)的矩陣映射到輸出層
對比NNLM神經語言模型,它們主要有以下三個不同點:
- 移除NNLM模型中的Hidden layer結構;
- 直接將Embedding layer的查表之后累加求和(NNLM是將輸出結果拼接)
- 將下文單詞納入上、下文環境,真正考慮了Context(NNLM的輸入嚴格來說為上文文本)
Skip-gram
CBoW模型依然是從context對target word的預測中學習到詞向量的表達。反過來,我們能否從target word對context的預測中學習到word vector呢?答案顯然是可以的:這便是Skip-gram模型
這個模型被稱為Skip-gram模型,其模型結構與CBoW模型大同小異,也包括輸入層、投影層(其實是多余的,加上該層以便與與CBoW模型對比)和輸出層:
如果將Skip-gram模型的輸出層的前向計算過程寫成數學形式,我們得到:
其中,\(V_i\)是Embedding層矩陣里的列向量,即中心詞的詞向量。\(U_j\)是softmax層矩陣里的行向量,即上下文中對應詞的詞向量。
Skip-gram模型的本質是計算輸入word的input vector與目標word的output vector之間的余弦相似度,並進行softmax歸一化。我們要學習的模型參數正是這兩類詞向量。
兩個提速手段
然而,每當計算一個詞的概率都要對詞典里的V個詞計算相似度,然后進行歸一化,這基本上時不現實的。為此,Mikolov引入了兩個提速手段:層次Softmax(Hierarchical Softmax)和負采樣(Negative Sampling)。普遍認為Hierarchical Softmax對低頻詞效果較好;Negative Sampling對高頻詞效果較好,向量維度較低時效果更好。
層次Softmax(Hierarchical Softmax)
Hierarchical Softmax是word2vec中的一項關鍵技術,簡單來說,其通過構造一個Huffman樹,將復雜的歸一化概率問題轉化為一系列二分類的條件概率相乘的形式。首先,我們需要了解什么是Huffman樹。
Huffman樹
Huffman編碼又稱為最優二叉樹,表示一種帶權路徑長度最短的二叉樹。帶權路徑長度,指的就是葉子結點的權值乘以該結點到根結點的路徑長度。而我們需要構造的Huffman樹結構,是以詞表為根結點,每一個子節點為父節點的不相交子集,詞為葉節點的結構。我們將葉節點的權值轉化為詞頻,則帶權路徑長度指的就是詞頻乘以路徑的大小,帶權路徑最小的條件使得構造出來的霍夫曼樹中,高頻詞離根結點更近,而低頻詞離根結點更遠。其構造的Huffman樹如下所示:
目標詞概率
在構建Huffman樹的同時,會為每一個非葉子節點初始化一個向量,該向量用於與預測向量求條件概率,假設我們的根結點表示原始字典D,則第二層的兩個子節點表示\(D\)的兩個子集\(D_1\)和\(D_2\),則在給定context的條件下,目標詞\(w_t\)屬於\(D_1\)的條件概率可以轉換為一個二分類的邏輯回歸函數:
當走到一個子節點后,我們又用類似的方法再對其進行二分類,得到下一個二分類的條件概率。假設每當我們將其分為左子節點時記為0,將其分為右子節點時記為1,則可以將最后的路徑的用0,1組合的二叉樹編碼表示,相應的似然函數為
這樣,我們可以通過最大化這個似然函數來求解二叉樹上的參數——非每一個葉節點上的向量,用來計算游走到某一個子節點的概率。
層次Softmax是一個很巧妙的模型。它通過構造一顆二叉樹,將目標概率的計算復雜度從最初的\(V\)降低到了\(log_2V\)的量級。不過付出的代價是人為增強了詞與詞之間的耦合性。例如,一個word出現的條件概率的變化,會影響到其路徑上所有非葉節點的概率變化,間接地對其他word出現的條件概率帶來不同程度的影響。因此,構造一顆有意義的二叉樹就顯得十分重要。實踐證明,在實際的應用中,基於Huffman編碼的二叉樹可以滿足大部分應用場景的需求。
負采樣(Nagative Sampling)
與改造模型輸出概率的Hierarchical Softmax算法不同,NCE算法改造的是模型的似然函數。其思想來源於一種叫做噪聲對比估計(Noise-Contrastive Estimation)的算法。
以Skip-gram模型為例,其原始的似然函數對應着一個多項分布。在用最大似然法求解這個似然函數時,我們得到一個cross-entropy的損失函數:
式中的\(p(w_{t+j}|w_t)\)是整個字典歸一化了的概率。
在NCE算法中,我們構造了這樣一個問題:對於一組訓練樣本,我們想知道,目標詞的預測,是來自於context的驅動,還是一個事先假定的背景噪聲的驅動?顯然,我們可以用一個邏輯回歸的函數來回答這個問題:
這個式子給出了一個目標詞\(w\)來自於context驅動的概率。其中,\(k\)是一個先驗參數,表明噪聲的采樣頻率。\(p(w|context)\)是一個非歸一化的概率分布,可以看作是softmax歸一化函數中的分子部分。\(p_n(w)\)則是背景噪聲的詞分布,通常采用word的unigram分布。而\(\sigma(·)\)是我們熟悉的sigmoid函數
在Mikolov論文中的負采樣算法,是NCE的簡化版本。簡單來說,其正負采樣過程具有以下兩個步驟:
- 首先確定正樣本,通過計算中心詞與上下文中詞的其余弦相似度,再用一個sigmoid函數來判斷:
- 采樣詞典中不在中心詞上下文中的詞的詞作為負樣本,采樣頻率由該詞在語料庫中出現的頻率有關,作者給出了一個經驗公式:
其中,\(f(w_i)\)是該詞在語料庫中的出現頻率,一共采樣k個詞
經過這樣的采樣操作后,我們得到一個新的數據集。其中,label標記了數據的來源(正例被標記為1,負例被標記為0)。在這個新的數據集上,我們僅需要從采樣結果中計算計算歸一化概率分布,從而大大簡化計算過程。
一些預處理細節
這些細節在整個模型中並不是特別重要的,大多是一些小trick,但理解這些小trick有利於我們后續使用gensim訓練詞向量時對整個模型有更好的理解。
低頻詞處理
利用語料來建立詞典的時候,不是每一個出現過詞都會加入到詞典中。通常會設置一個min_count的閾值參數,用來剔除出現次數少於min_count次的詞。注意,這一類詞在訓練中也是不可見的,可以看作在訓練之前就將其從語料庫中刪除了。
高頻詞的處理
通常認為高頻詞往往只提供較少的信息(比如“的”、“是”等高頻副詞對於名詞沒有很強的相關性的),而且這些詞對應的詞向量在眾多樣本的訓練過程中也不會發生明顯的變化。因此我們引入一種下采樣(Subsampling)的操作,對一些出現頻率高於一定值的高頻詞,按一定概率進行拋棄。這樣的操作一方面可以提高我們的訓練速度,另一方面也可以提升低頻詞的表示精度。
單個句子的限制
模型訓練是以行進行的。通常我們存儲語料的時候是以行為單位來存儲句子,訓練的時候每次就是處理一個句子。為了避免句子過長,通常可以設置一個閾值參數max_sentence_length,進行強行截斷。
對於context的選擇
對於一個給定行,假設其包含T個詞,則該行依據每一個詞及其對應的context,共可生成T個訓練樣本。實際上的context選取是這樣的:事先設置好一個窗口閾值函數window,每次構造context的時候,首先生成區間[1, window]上的一個隨機整數c,然后對當前中心詞前后各取c個詞構成context。
自適應學習率
在word2vec源碼中,采用了自適應學習率:預先設置一個初始學習率\(\eta_0\),每處理完一定數量的詞進行一次調整,直到學習率到達一個下限值\(\eta_{min}\),即訓練過程中學習率是從\(\eta_0\)到\(\eta_{min}\)單調遞減的,下降到\(\eta_{min}\)時維持在恆定值保持不變。
訓練
模型采用的是隨機梯度下降算法,且僅對整個語料遍歷一次,這也是其高效的一個原因。
多線程並行
word2vec的訓練是支持多線程的,可以通過設置num_threads來設置使用的線程數。
word2vec的局限性
總的來說,word2vec通過嵌入一個線性的投影矩陣(projection matrix),將原始的one-hot向量映射為一個稠密的連續向量,並通過一個語言模型的任務去學習這個向量的權重,而這個過程可以看作是無監督或稱為自監督的,其詞向量的訓練結果與語料庫是緊密相關的,因此通常不同的應用場景需要用該場景下的語料庫去訓練詞向量才能在下游任務中獲得最好的效果。這一思想后來被廣泛應用於包括word2vec在內的各種NLP模型中,從此之后不單單是詞向量,我們也有了句向量、文檔向量,從Word Embedding走向了World Embedding的新時代。word2vec非常經典,但也有其明顯的局限性,其主要在以下幾個方面:
- 在模型訓練的過程中僅僅考慮context中的局部語料,沒有考慮到全局信息;
- 對於英文語料,對於什么是詞,怎樣分詞並不是問題(但個詞就是獨立的個體)。而對於中文而言,我們在訓練詞向量之前首先要解決分詞的問題,而分詞的效果在很多情況下將會嚴重影響詞向量的質量(如分詞粒度等),因此,從某些方面來說word2vec對中文不是那么的友好;
- 在2018年以前,對於word2vec及其一系列其他的詞向量模型都有一個相同的特點:其embedding矩陣在訓練完成后便已經是固定了的,這樣我們可以輕易從網上獲取到大量預訓練好的詞向量並快速應用到我們自己任務中。但從另一個角度來說,對於同一個詞,在任意一個句子,任意一個環境下的詞向量都是固定的,這對於一些歧義詞來說是存在較大問題的,這也是限制類似word2vec、Glove等詞向量工具性能的一個很重要的問題。
GloVe
對於GloVe(Globel Vectors)算法,其實就是SVD分解與Word2Vec的結合。
統計共現矩陣
在介紹GloVe的思想之前,我們先定義一個共現矩陣\(X\),該矩陣中的\(X_{ij}\)表示第\(j\)個單詞出現在以第\(i\)個單詞為中心,長度為\(n\)的窗口中的次數。將長度為n的窗口遍歷整個語料庫,則得到了共現矩陣\(X\)。
Glove的由來
對於大型語料庫,我們可以認為統計的詞共現矩陣X可以很好的描述詞與詞之間的相關性。但是,就像之前我們說過的,這樣大的一個共現矩陣在實際使用中將會面臨復雜的維度災難問題,因此我們需要想辦法詞向量進行降維,比如之前的SVD對詞-文檔共現矩陣進行降維就是這樣一種思想。
而對於word2vec,我們每次訓練詞向量,都是針對於局部語料進行預測(根據局部上下文預測中心詞,或根據中心詞預測局部上下文),這就使得模型的訓練過程中是很難考慮到整個語料庫的全局信息的。我們通常將其稱為一種預測模型(predictive model),其目標是不斷提高對其他詞的預測能力,即減小預測損失,從而得到詞向量。
我們有沒有一種方法,既能通過訓練的方式得到固定維度的詞向量表征,又能夠使得到的詞向量能夠充分考慮到語料庫的全局特征?這樣我們便得到了GloVe。
簡單來說,Glove相對於Word2Vec,需要提前統計詞共現矩陣,並將其整合到代價函數之中,使得訓練結果對於該統計是有一定的重建能力的。我們將其稱為一種統計模型(count-based model),其目標是優化減小重建損失(reconstruction loss),即降維之后的向量能盡量表達原始向量的完整信息。
GloVe的代價函數
我們先來看看代價函數的形式,雖然看起比較復雜,但是看完下面的解析就會變得非常清楚了
其中,\(w_i, w_j\)為訓練得到的詞向量,\(b_i, b_j\)為偏差量,\(X_{i, j}\)為共現矩陣中的元素,\(N\)為詞表大小,\(f\)為權重函數
通過共現矩陣,我們可以得到如下的概率表示:
- 單詞\(k\)出現在單詞\(i\)上下文的條件概率:
- 定義單詞\(k\)出現在兩個不同單詞\(i, j\)上下文的兩個條件概率的比率:
對於\(ratio_{i, j, k}\),有如下特性
作者認為,如果訓練得到的詞向量\(w_i\),\(w_j\),\(w_k\)也能反應如上的性質,則說明訓練得到的詞向量能夠包含共現矩陣中的全局信息。即對於訓練得到的詞向量\(w_i\),\(w_j\),\(w_k\),存在一個評估方法\(g(*)\),使得
我們可以用平方差來定義其代價函數:
這樣一個代價函數每一項包含3個單詞,意味着又\(N^3\)項,過於復雜了需要將其簡化一下。先對g(w_i,w_j,w_k)進行定義,該函數需要反應\(w_i\)與\(w_j\)的差異性,也要反映\(w_i\),\(w_j\)與\(w_k\)的相似性,因此有:
即我們需要追求:
現在只需要追求:
這樣,我們可以將代價函數簡化為:
我們將其取一個對數:
然而我們得到一個新的問題:
而
我們將\(log(P_{i, j})\)按照條件概率展開,即:
我們可以將右邊第二項看作一個偏差項,則可以使得
等價為
則代價函數變為:
另外,對於出現頻率越高的詞,我們希望其對代價函數的影響越大,因此在代價函數中添加權重項,於是代價函數進一步完善:
作者通過實踐得到的權重函數為:
小結
GloVe與Word2Vec的區別就在於GloVe考慮到了文本的全局特征,直觀上來說比Word2Vec更合理。在語料庫足夠大的情況下GloVe的效果通常會更好一些,但這也不是絕對,word2vec在很多任務上的表現也比GloVe要更好。可以嘗試的做法是將GloVe和Word2Vec進行整合(拼接等操作),會使得模型有意想不到的提升。
參考鏈接
https://www.cnblogs.com/guoyaohua/p/9240336.html
https://www.cnblogs.com/LeftNotEasy/archive/2011/01/19/svd-and-applications.html
https://www.cnblogs.com/pinard/p/6251584.html
https://kexue.fm/archives/4233
https://blog.csdn.net/itplus/article/details/37969519
http://mccormickml.com/2016/04/19/word2vec-tutorial-the-skip-gram-model/
http://qiancy.com/2016/08/17/word2vec-hierarchical-softmax/
https://www.jianshu.com/p/ed15e2adbfad
https://blog.csdn.net/coderTC/article/details/73864097
https://zhuanlan.zhihu.com/p/72329901