深度學習NLP-詞向量篇(含代碼實現)

本文是最近學習了斯坦福大學的NLP課程CS224N,和一些相關教程後,整理出來的一篇關於詞向量的學習筆記。主要記錄了關於詞向量的產生,關於計數的詞向量生成法,基於分佈的詞向量生成法(Cbow,Skip-gram,GloVe),和一些相關知識。

一、詞嵌入的簡介

語言模型

在計算機學科裏,一個語言模型往往指的是使用一種知識表達的方法,通過計算一個單詞/句子產生的概率來表達一種語言規律。傳統的語言模型中詞的表示是原始的、面向字符串的。兩個語義相似的詞的字符串可能完全不同,比如“番茄”和“西紅柿”。這給所有NLP任務都帶來了挑戰——字符串本身無法儲存語義信息。所以我們提出了基於語義的語言表達方式——通過編碼的方式表達單詞以及單詞間的聯繫(語義)。這也就是我們今天要介紹的詞嵌入。

詞嵌入

簡單來說,詞嵌入就是將文本轉換成數字,方法不同,數值表徵也不同。在深入之前,先來討論下爲什麼需要詞嵌入?

人們經過實踐得出結論,多數機器學習算法和幾乎所有的深度學習框架都不能處理原始個格式的字符串和文本。機器需要數字作爲輸入,才能執行分類迴歸這樣的任務。文本中蘊含着海量的數據,有必要從中提取出有用的東西,並創建應用,比如亞馬遜商品評論、文檔或新聞的情感分析、谷歌搜索的分類和聚類。

給詞嵌入下個定義:詞嵌入是使用詞典,將單詞映射到矢量上。

二、實現詞嵌入的方法

實現詞嵌入大體有兩種方法:基於頻率和基於預測。

基於頻率的詞嵌入

一般來講基於頻率我們可以簡單理解成對每一個單詞在語料庫中出現次數的計數。一般來說,有三種方式:

  1. 計數向量
  2. TF-IDF向量
  3. 共現向量

這裏就不詳細展開了,有興趣的同學可以看一下這篇博客裏面有詳細記載關於三種計數方式的講解。

基於預測的詞嵌入

基於預測的詞嵌入是我們今天講解的重點。主要有CBow,Skip-gram,和GloVe三個方法。前兩個是2012年Mitolov大神推出。本來人家是要推出一個詞預測模型的,詞嵌入的結果只是副產物。但是由於發現詞嵌入矩陣不僅僅能用來預測詞。還能作爲一種語言表達方式,通過編碼單詞達到表達單詞和單詞的語義的效果。故基於預測的詞嵌入的方法開始他的傳奇。目前,詞嵌入作爲一個NLP模型的基礎操作,已廣泛應用到各個NLP任務中了。GloVe是斯坦福大學在2014年推出的一款升級款詞嵌入方法。目前也是應用非常廣泛的詞嵌入Benchmark。

三、基於預測的方法

基於預測的詞嵌入方法,說的通俗一點就是學習詞向量的分佈。下面簡單講解下三個應用廣泛的方法。

CBow&Skip-gram

在這裏插入圖片描述
如圖所示,我們可以看到兩個模型的區別,Cbow用輸入的上下文來預測目標單詞。Skip-gram用輸入的單詞預測目標上下文。假設有一個句子“Pineapples are spiked and yellow”,兩個模型的預測方式如下:

  1. 在CBOW中,先在句子中選定一箇中心詞,並把其他詞作爲這個中心詞的上下文。如 圖4 CBOW所示,把“spiked”作爲中心詞,把“Pineapples are and yellow”作爲中心詞的上下文。在學習過程中,使用上下文的詞向量預測中心詞,這樣中心詞的語義就被傳遞到上下文的詞向量中,如“spiked”=>“pineapple”,從而達到學習語義信息的目的。
  2. 在Skip-gram中,同樣先選定一箇中心詞,並把其他詞作爲這個中心詞的上下文。如 圖4 Skip-gram所示,把“spiked”作爲中心詞,把“Pineapples are and yellow”作爲中心詞的上下文。不同的是,在學習過程中,使用中心詞的詞向量去預測上下文,從而達到學習語義信息的目的。

一般來說,CBOW比Skip-gram訓練速度快,訓練過程更加穩定,原因是CBOW使用上下文average的方式進行訓練,每個訓練step會見到更多樣本。而在生僻字(出現頻率低的字)處理上,skip-gram比CBOW效果更好,原因是skip-gram不會刻意迴避生僻字。

CBOW和Skip-gram的算法實現:
在這裏插入圖片描述
如所示,Skip-gram是一個具有3層結構的神經網絡,分別是:
Input Layer(輸入層):接收一個one-hot張量 作爲網絡的輸入,裏面存儲着當前句子中心詞的one-hot表示。
Hidden Layer(隱藏層):將張量乘以一個word embedding張量,並把結果作爲隱藏層的輸出,得到一個形狀爲的張量,裏面存儲着當前句子中心詞的詞向量。
Output Layer(輸出層):將隱藏層的結果乘以另一個word embedding張量,得到一個形狀爲的張量。

這個張量經過softmax變換後,就得到了使用當前中心詞對上下文的預測結果。根據這個softmax的結果,我們就可以去訓練詞向量模型。在實際操作中,使用一個滑動窗口(一般情況下,長度是奇數),從左到右開始掃描當前句子。每個掃描出來的片段被當成一個小句子,每個小句子中間的詞被認爲是中心詞,其餘的詞被認爲是這個中心詞的上下文。

Skip-gram的理想實現

使用神經網絡實現Skip-gram中,模型接收的輸入應該有2個不同的tensor:
代表中心詞的tensor:假設我們稱之爲center_words ,一般來說,這個tensor是一個形狀爲[batch_size, vocab_size]的one-hot tensor,表示在一個mini-batch中,每個中心詞的ID。
代表目標詞的tensor:假設我們稱之爲target_words ,一般來說,這個tensor是一個形狀爲[batch_size, 1]的整型tensor,這個tensor中的每個元素是一個[0, vocab_size-1]的值,代表目標詞的ID。

在理想情況下,我們可以使用一個簡單的方式實現skip-gram。即把需要預測的每個目標詞都當成一個標籤,把skip-gram當成一個大規模分類任務進行網絡構建,過程如下:
聲明一個形狀爲[vocab_size, embedding_size]的張量,作爲需要學習的詞向量,記爲。對於給定的輸入,使用向量乘法,將乘以,這樣就得到了一個形狀爲[batch_size, embedding_size]的張量,記爲。這個張量就可以看成是經過詞向量查表後的結果。
聲明另外一個需要學習的參數,這個參數的形狀爲[embedding_size, vocab_size]。將上一步得到的去乘以,得到一個新的tensor ,此時的是一個形狀爲[batch_size, vocab_size]的tensor,表示當前這個mini-batch中的每個中心詞預測出的目標詞的概率。
使用softmax函數對mini-batch中每個中心詞的預測結果做歸一化,即可完成網絡構建。

Skip-gram的實際實現 (負採樣的使用)

然而在實際情況中,vocab_size通常很大(幾十萬甚至幾百萬),導致和也會非常大。對於而言,所參與的矩陣運算並不是通過一個矩陣乘法實現,而是通過指定ID,對參數進行訪存的方式獲取。然而對而言,仍要處理一個非常大的矩陣運算(計算過程非常緩慢,需要消耗大量的內存/顯存)。爲了緩解這個問題,通常採取負採樣(negative_sampling)的方式來近似模擬多分類任務。

假設有一箇中心詞和一個目標詞正樣本。在Skip-gram的理想實現裏,需要最大化使用預測的概率。在使用softmax學習時,需要最大化的預測概率,同時最小化其他詞表中詞的預測概率。之所以計算緩慢,是因爲需要對詞表中的所有詞都計算一遍。然而我們還可以使用另一種方法,就是隨機從詞表中選擇幾個代表詞,通過最小化這幾個代表詞的概率,去近似最小化整體的預測概率。比如,先指定一箇中心詞(如“人工”)和一個目標詞正樣本(如“智能”),再隨機在詞表中採樣幾個目標詞負樣本(如“日本”,“喝茶”等)。有了這些內容,我們的skip-gram模型就變成了一個二分類任務。對於目標詞正樣本,我們需要最大化它的預測概率;對於目標詞負樣本,我們需要最小化它的預測概率。通過這種方式,我們就可以完成計算加速。上述做法,我們稱之爲負採樣。

在實現的過程中,通常會讓模型接收3個tensor輸入:
代表中心詞的tensor:假設我們稱之爲center_words ,一般來說,這個tensor是一個形狀爲[batch_size, vocab_size]的one-hot tensor,表示在一個mini-batch中每個中心詞具體的ID。
代表目標詞的tensor:假設我們稱之爲target_words ,一般來說,這個tensor同樣是一個形狀爲[batch_size, vocab_size]的one-hot tensor,表示在一個mini-batch中每個目標詞具體的ID。
代表目標詞標籤的tensor:假設我們稱之爲labels ,一般來說,這個tensor是一個形狀爲[batch_size, 1]的tensor,每個元素不是0就是1(0:負樣本,1:正樣本)。

模型訓練過程如下:
用去查詢,用去查詢,分別得到兩個形狀爲[batch_size, embedding_size]的tensor,記爲和。
點乘這兩個tensor,最終得到一個形狀爲[batch_size]的tensor 。
使用sigmoid函數作用在上,將上述點乘的結果歸一化爲一個0-1的概率值,作爲預測概率,根據標籤信息label訓練這個模型即可。
在結束模型訓練之後,一般使用作爲最終要使用的詞向量,可以用提供的向量表示。通過向量點乘的方式,計算兩個不同詞之間的相似度。

這裏,提供了Skip-gram的實現代碼

四、基於全局信息的GloVe

Cbow 或者Skip-Gram取得了很大的成功,不管在訓練效率還是在詞向量的計算效果上面。但是考慮到Cbow/Skip-Gram 是一個local context window的方法,比如使用NS來訓練,缺乏了整體的詞和詞的關係,負樣本採用sample的方式會缺失詞的關係信息。另外,直接訓練Skip-Gram類型的算法,很容易使得高曝光詞彙得到過多的權重。
在這裏插入圖片描述

Global Vector融合了矩陣分解Latent Semantic Analysis (LSA)的全局統計信息和local context window優勢。融入全局的先驗統計信息,可以加快模型的訓練速度,又可以控制詞的相對權重。

設共現矩陣爲X,其元素爲Xi,j。Xi,j 的意義爲:在整個語料庫中,單詞i和單詞j共同出現在一個窗口中的次數。

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

Ref:
斯坦福CS224N課程
詞向量的深度解析
word2vec進階之skim-gram和CBOW模型
cs224n系列之word2vec & 詞向量
GloVe原理介紹

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章