BERT發(fā)展史(三)全方位多角度理解Word2Vec
建議先閱讀之前兩篇文章:
BERT發(fā)展史(一)從詞嵌入講起
BERT發(fā)展史(二)語言模型
0. 寫在前面
在上一篇介紹的神經網絡語言模型中,我們訓練模型的目標是得到一個泛化能力強、無需平滑的語言模型,而詞向量只是我們在訓練語言模型過程中的一個副產物,這個副產物可以起到詞嵌入的作用,將語料庫中的詞語映射為一個個的向量,且向量能夠表征一定的語義信息。那么,從詞嵌入的角度出發(fā),我們是否可以使用這個模型專門用于將詞語轉換為向量呢?可以當然是可以,不過有以下問題需要考慮:
- 語言模型由于其任務限制,只能使用前面的詞語來預測當前詞,缺少后面詞語的上下文信息。
- 模型的最后一層softmax層計算非常耗時。
因此,如果要使用神經網絡來實現(xiàn)詞嵌入,我們需要對神經網絡語言模型進行一定的改進。接下來,就讓我們看看Word2Vec是如何解決以上問題的。
PS. 關于Word2Vec的代碼和數學推導,網上以及文末的參考資料中都要非常好且詳細的介紹,這篇文章并不想重復前人工作,因此,本文在基本概念之外,也加入了許多理解性的東西(如對語義如何建模到向量中的理解,詞向量維度的理解等),希望能夠起到參考價值。
1. Word2Vec概覽
Word2Vec并非指一個模型,而是2013年Google開源的一個獲取詞向量的工具包,由于簡單高效,大大降低了詞向量在工業(yè)界的應用門檻。我們先來看下Word2Vec能夠取得的效果:
- 相似詞:通過向量間距離的遠近來尋找相似詞,如man的相似詞woman;
- 詞語線性運算:V(King) - V(man) + V(woman) = V(Queen)
由此可見,Word2Vec可以通過上下文將語義較好的嵌入到向量空間中。由于Word2Vec生成的詞向量將自然語言的特征較好地融合進了低維度稠密詞向量中,使用詞向量進行后續(xù)的各種NLP任務便可以取得較好的結果。
Word2Vec本身的模型結構是比較簡單的,但模型結構以外有許多需要理解的內容,對Word2Vec的理解可以幫助我們更好地調節(jié)深度學習模型參數,更好地理解包括BERT在內的后續(xù)各個模型。要理解Word2Vec,我們主要需要了解其中的四個概念:
- CBOW
- Skip-gram
- Hierarchical softmax
- Negative Sampling
其中,前兩個代表Word2Vec中兩種不同的獲取詞向量的策略,或者說模型結構;后兩個則是兩種改進softmax計算復雜度過高問題的方法。
這篇文章將對以上四個概念進行深入剖析,之后將給出對Word2Vec如何建模語義信息的理解和對詞向量維度的理解。
2. CBOW & Skip-gram
首先,與語言模型只使用當前詞前面的詞語不同,我們將使用當前詞周圍的詞來建模詞向量。其次,要明確的是,CBOW和Skip-gram都是使用淺層的神經網絡,他們的區(qū)別在于輸入和輸出的不同。
CBOW:以當前詞的周圍詞語作為輸入,當前詞作為輸出。即上下文預測當前詞。
Skip-gram:以當前詞作為輸入,當前詞的周圍詞作為輸出。即當前詞預測上下文。
2.1 CBOW
CBOW使用當前詞周圍的詞語來預測當前詞,所謂周圍詞,既包括前面的詞語,也包括后面的詞語。至于取前后幾個詞語,由Context window指定。
還是舉例子??來說明:
我們有一個句子:“知識改變命運”。分詞為["知識", "改變", "命運"]。構造詞表為{0: <pad>, 1: 知識, 2: 改變, 3: 命運}。其中,<pad>是自己構造的一個「填充詞」。
使用CBOW的方法,取Context window=1,構造樣本為:
<pad>, 改變 —> 知識
知識,命運 —> 改變
改變,<pad> —> 命運
接下來,和神經網絡語言模型一樣,我們?yōu)樵~表中的每個詞語分配一個隨機初始化的詞向量(瞎編的數字??):
其中,矩陣的第一行為詞表中序號為0的詞語的詞向量,以此類推。注意,我們最終的目標并不是得到一個神經網絡模型,而是得到更新后的詞向量矩陣。
為了方便起見,我們先從一個上下文詞語預測當前詞開始,比如使用「知識」這個詞去預測「改變」。神經網絡的輸入為知識這個詞的詞向量,輸出為預測詞表中的所有詞出現(xiàn)的概率。目標是最大化「改變」這個詞出現(xiàn)的概率,即P(改變|知識)。其結構如下圖所示(畫功拙劣,湊活著看吧~??):
最后的輸出向量做一次softmax運算,就可以得到詞表中四個詞語的概率了。然后針對損失函數使用反向傳播進行優(yōu)化就行了。
需要注意的是,在這個神經網絡的訓練過程中,需要更新的參數不只是其權重矩陣W',還有其輸入?。
再來看「知識」和「命運」預測「改變」的情況,結構圖如下:
以上就是CBOW得到詞向量的策略了,主要就是利用單層神經網絡使用上下文預測當前詞。
有了以上基礎,再看Skip-gram就簡單明了了。
2.2 Skip-gram
skip-gram以當前詞作為輸入,當前詞的上下文詞語作為輸出。這個策略在構造樣本時有兩個概念需要清楚,一個是skip_window,類似于CBOW的context_window,用于指定選取上下文時的單側窗口大小;另一個是num_skips,表示我們將從上下文窗口中選取幾個詞作為label。
同樣還是「知識改變命運」這個例子,以skip_window=1, num_skips=2構造以下樣本(這里我沒有構造填充詞):
改變—> 知識
改變—>命運
有了輸入和輸出,接下來的訓練方式就是正常的神經網絡的訓練了。
實際實現(xiàn)過程中,有一些需要注意的點。
- 以上面例子為例,構造樣本時,若num_skips=1,我們需要在窗口的兩個詞中取一個作為label;取詞的方式為隨機取一個,這里的隨機并不是等概率隨機,而是詞頻越高概率越高。
- 上面的例子看起來是構造了兩個樣本,但在實際訓練過程中,這兩個樣本共同組成一個樣本用于計算損失函數:
從極大似然估計的角度來看,我們要最大化P(知識|改變)和P(命運|改變)的乘積。由于加了log,乘積的形式變成了相加的形式。這等價于兩個子樣本組成一個batch計算損失函數。如果你讀過word2vec的源碼的話,你會發(fā)現(xiàn),skip-gram在構造樣本時,并非是將CBOW中的([知識,命運],改變)翻轉為(改變,[知識,命運]),而是構造了兩個樣本:(改變,知識),(改變,命運)。實際運算時,只需要將上述樣本放在同一個batch里面就行了。這也是為什么代碼里需要保證batch_size % num_skips == 0。
另外,關于CBOW和Skip-gram的表述,你可能看到比較多的是以下兩幅圖:
?
看起來比我前面畫的神經網絡多了一層,但其實是一樣的。這兩幅圖將「取」詞向量這一步作為了神經網絡的第一層,使用詞語的one-hot編碼(即上圖中的輸入層)與詞向量矩陣(即上圖中第一層的權重矩陣)相乘,其實就是取詞向量矩陣中,詞語編號對應的那一行。
2.3 比較
根據Word2Vec作者Mikolov的說法,兩者的比較如下:
Skip-gram: works well with small amount of the training data, represents well even rare words or phrases.
CBOW: several times faster to train than the skip-gram, slightly better accuracy for the frequent words.
這里給出我對以上比較的理解。
關于訓練集大小:Skip-gram在數據集較小時能取得更好的效果;原因我認為有兩點:1. 數據集較小時,低頻詞較多,Skip-gram對低頻詞的表示效果較好(原因后面會說);2. 同樣的語料庫,Skip-gram能產生更多(子)樣本。
關于訓練速度:CBOW訓練速度更快。這是因為,一個batch中,CBOW包含batch_size個中心詞樣本,Skip-gram包含batch_size/num_skips個中心詞樣本,同樣的batch_size遍歷一次樣本集,CBOW需要更少的step。
關于低頻高頻詞的表示效果:Skip-gram對低頻詞的表示效果優(yōu)于CBOW,CBOW對高頻詞的表示效果略優(yōu)于Skip-gram。原因的話,我從兩個方面進行闡述:1. 直觀上來理解,CBOW通過上下文預測中心詞,如知識___命運,類似于完形填空,選擇概率最高的一個詞填入其中,這就要求詞向量對于概率最高的那些詞有足夠的「理解」;而Skip-gram則是根據中心詞填周圍的詞,如___改變___,要在中心詞周圍填詞,詞向量需要對該詞有足夠的「理解」才能填詞,包括低頻詞。2. 從反向傳播更新詞向量的角度來看,在反向傳播更新詞向量時,CBOW使用相同的梯度更新所有輸入詞向量,如對于([知識,命運],改變)這個樣本,知識和命運的詞向量使用同樣的梯度進行更新,這就使得低頻詞的詞向量更新被高頻詞「平滑」掉了。而Skip-gram則不存在這個問題。
3. Trick
到了這里,其實就不屬于模型結構介紹的范疇了,這一塊主要是為了加速模型訓練,使模型能夠應用于大規(guī)模語料庫。
首先看一下為什么softmax層這么費時。
softmax的公式如下:
?可以看出,針對一個高維向量,即使要計算softmax后的一個元素值,也需要針對所有元素做指數運算,當維度非常高時,這種計算無疑是非常費時的。在word2vec中,需要做softmax運算的向量維度為詞表詞語個數,當語料庫非常大時,詞表詞語個數也會變得非常大。但我們關注的只是某一個詞的概率,即計算softmax后的某一個元素值,這里肯定存在許多無用計算。
3.1 Hierarchical softmax
分層softmax的出發(fā)點是,將詞表中的所有詞語組織成一棵哈夫曼樹,計算詞語出現(xiàn)概率時,使用從根節(jié)點到詞語所在葉節(jié)點路徑上的向量進行運算。這種方法不僅降低了softmax層的運算,還減少了輸出層的計算量。
具體來說,先將詞表中的詞語組織到哈夫曼樹的葉節(jié)點上。什么是哈夫曼樹以及如何構建網上有很多資料,這里不再贅述了。簡單來說,這里使用的哈夫曼樹就是一棵二叉樹,每個非葉節(jié)點存放一個向量(可以理解成神經網絡中的參數,需要在訓練過程中更新),每個葉節(jié)點存放一個詞語,詞語的詞頻越高,該葉節(jié)點離根節(jié)點越近。
還是以「知識 改變 命運」為例,使用「知識」預測「改變」,假定語料庫中的詞頻知識>改變>命運,則模型簡單結構和構建的哈夫曼樹如下圖:
3.2 Negative Sampling
Negative Sampling(NEG)使用簡單的隨機負采樣來代替復雜的哈夫曼樹,大幅提高性能,可以作為Hierarchical softmax的一種替代方法。
同樣以「知識 改變 命運」為例,使用「知識」預測「改變」,那么「改變」這個詞就是一個「正樣本」, 其他的所有詞為「負樣本」, 假設我們采集到的負樣本集合為{命運},那么我們需要最大化:
乘號前面表示預測為正樣本的概率,后面表示預測不是負樣本的概率。因此,最大化P可以理解為,增大預測正樣本的概率同時降低預測負樣本的概率。
另外,負樣本的采集為隨機采集,同樣,這里的隨機也并不是等概率隨機,而是根據各個詞語所占的詞頻比例進行相應概率的采樣。
3.3 比較
由于Hierarchical Softmax使用了哈夫曼樹,非葉節(jié)點的數量并不等于詞語的數量,因此也沒有了「輸出詞向量」這個概念,可能會損失一些效果(如Glove中,最后效果最好的詞向量為輸入詞向量和輸出詞向量的平均)。
根據word2vec官網,兩者的比較如下:
hierarchical softmax : better for infrequent words
negative sampling : better for frequent words, better with low dimensional vectors
4. 幾點思考與理解
4.1 對語義建模的理解
Word2Vec主要是通過詞語與其上下文之間的關系來對語義進行建模的。出發(fā)點就是擁有相同上下文的詞語語義更加相似,體現(xiàn)到詞向量上,就是擁有相同上下文的詞語的詞向量距離更近。如“蘋果是一種水果”,“香蕉是一種水果”,蘋果和香蕉擁有相同的上下文詞語,那么我們認為蘋果和香蕉的語義是相似的,它們的詞向量的距離也應該是更近的。那么Word2Vec是怎么做到的呢?
要理解這一點,我們需要來簡單地看一下反向傳播的過程。針對圖一:
以上,我們就推出了原始形式下,word2vec的詞向量更新公式。讓我們以圖形的形式來理解一下這個更新公式:
因此,使用word2vec訓練詞向量,其過程就是相同上下文的詞語的詞向量相互靠近,不同上下文的詞語的詞向量相互遠離的過程。對于類似上下文的詞語,其詞向量在空間上更加靠近,向量之間的距離也更短。
4.2 對詞向量維度的理解
有了前面的理解,再來看一下詞向量的維度。圖五中,我們畫出了二維向量相互靠近的過程,在二維空間,如果我們想要靠近一個向量,勢必也要遠離另外一些向量。但如果我們的相似詞語比較多時,勢必無法靠近所有相似詞語的向量。而維度越高,越可以在保持與當前相似向量距離變化不大的情況下,靠近另外一個相似向量。
因此,詞向量的維度越高,一個詞語能夠與越多的詞語產生正確的「靠近運動」,表現(xiàn)在語言層面,可以理解為具有更加豐富的語義。一般,訓練詞向量使用的語料庫越大,就應該使用越大的詞向量維度,這樣也能夠得到具備更加豐富語義的詞向量。
但詞向量的維度并非越高越好,維度越高,詞向量所占的存儲空間越大,頂層任務所需要的計算量越大。因此,實際使用中,可以根據具體語料庫的大小和實際計算要求選擇。
5. 不足與改進空間
總的來說,word2vec通過詞語與上下文的相互關系來將語義建模到向量中,但word2vec沒有考慮詞語之間的順序關系,也沒有考慮整個語料庫的統(tǒng)計信息(word2vec屬于基于預測的詞嵌入方法),通過上下文關系建模語義的過程,也會損失許多語義和句法等信息。這就給后續(xù)的研究留下了許多可開展的空間......
6. 參考資料推薦
我在學習word2vec的過程中,閱讀了非常多的資料,有些對理解Word2Vec幫助巨大,下面我將個人覺得最好的資料推薦出來(百度一下或google一下都能搜到):
【1】word2vec Parameter Learning Explained. Xin Rong ronxin@umich.edu
這篇論文強烈推薦!論文對Word2Vec的四個主要概念進行了非常詳細的介紹,也有一些Intutive的解釋幫助理解!首推!
【2】Word2Vec中的數學原理詳解
強烈推薦!文章介紹Word2Vec的由來和前置知識,最難得的是,文章對四個主要概念都進行了前向傳播和反向傳播的推導,認真啃下來,對理解Word2Vec幫助巨大!
【3】[NLP] 秒懂詞向量Word2vec的本質
我接觸Word2Vec前期看的文章,幫助我建立了對Word2Vec的初步認識,理解了Word2Vec到底為何方神圣;文中推薦的許多資料也讓我在后續(xù)的學習過程中受益匪淺!
tensorflow官方的word2vec基礎代碼實現(xiàn),對于理解word2vec的樣本構造,訓練細節(jié)等大有幫助。