詞向量word2vec(圖學習參考資料)

2022-11-10 18:01:37

介紹詞向量word2evc概念,及CBOW和Skip-gram的演演算法實現。
專案連結: https://aistudio.baidu.com/aistudio/projectdetail/5009409

在自然語言處理任務中,詞向量(Word Embedding)是表示自然語言裡單詞的一種方法,即把每個詞都表示為一個N維空間內的點,即一個高維空間內的向量。通過這種方法,實現把自然語言計算轉換為向量計算。

圖1 所示的詞向量計算任務中,先把每個詞(如queen,king等)轉換成一個高維空間的向量,這些向量在一定意義上可以代表這個詞的語意資訊。再通過計算這些向量之間的距離,就可以計算出詞語之間的關聯關係,從而達到讓計算機像計算數值一樣去計算自然語言的目的。

因此,大部分詞向量模型都需要回答兩個問題:

  1. 如何把詞轉換為向量?

自然語言單詞是離散訊號,比如「香蕉」,「橘子」,「水果」在我們看來就是3個離散的詞。

如何把每個離散的單詞轉換為一個向量?

  1. 如何讓向量具有語意資訊?

比如,我們知道在很多情況下,「香蕉」和「橘子」更加相似,而「香蕉」和「句子」就沒有那麼相似,同時「香蕉」和「食物」、「水果」的相似程度可能介於「橘子」和「句子」之間。

那麼,我們該如何讓詞向量具備這樣的語意資訊?

1.如何把詞轉換為向量

自然語言單詞是離散訊號,比如「我」、「 愛」、「人工智慧」。如何把每個離散的單詞轉換為一個向量?通常情況下,我們可以維護一個如 圖2 所示的查詢表。表中每一行都儲存了一個特定詞語的向量值,每一列的第一個元素都代表著這個詞本身,以便於我們進行詞和向量的對映(如「我」對應的向量值為 [0.3,0.5,0.7,0.9,-0.2,0.03] )。給定任何一個或者一組單詞,我們都可以通過查詢這個excel,實現把單詞轉換為向量的目的,這個查詢和替換過程稱之為Embedding Lookup。

上述過程也可以使用一個字典資料結構實現。事實上如果不考慮計算效率,使用字典實現上述功能是個不錯的選擇。然而在進行神經網路計算的過程中,需要大量的算力,常常要藉助特定硬體(如GPU)滿足訓練速度的需求。GPU上所支援的計算都是以張量(Tensor)為單位展開的,因此在實際場景中,我們需要把Embedding Lookup的過程轉換為張量計算,如 圖3 所示。

假設對於句子"我,愛,人工,智慧",把Embedding Lookup的過程轉換為張量計算的流程如下:

  1. 通過查詢字典,先把句子中的單詞轉換成一個ID(通常是一個大於等於0的整數),這個單詞到ID的對映關係可以根據需求自定義(如圖3中,我=>1, 人工=>2,愛=>3,...)。

  2. 得到ID後,再把每個ID轉換成一個固定長度的向量。假設字典的詞表中有5000個詞,那麼,對於單詞「我」,就可以用一個5000維的向量來表示。由於「我」的ID是1,因此這個向量的第一個元素是1,其他元素都是0([1,0,0,…,0]);同樣對於單詞「人工」,第二個元素是1,其他元素都是0。用這種方式就實現了用一個向量表示一個單詞。由於每個單詞的向量表示都只有一個元素為1,而其他元素為0,因此我們稱上述過程為One-Hot Encoding。

  3. 經過One-Hot Encoding後,句子「我,愛,人工,智慧」就被轉換成為了一個形狀為 4×5000的張量,記為$V$。在這個張量裡共有4行、5000列,從上到下,每一行分別代表了「我」、「愛」、「人工」、「智慧」四個單詞的One-Hot Encoding。最後,我們把這個張量$V$和另外一個稠密張量$W$相乘,其中$W$張量的形狀為5000 × 128(5000表示詞表大小,128表示每個詞的向量大小)。經過張量乘法,我們就得到了一個4×128的張量,從而完成了把單詞表示成向量的目的。

2.如何讓向量具有語意資訊

得到每個單詞的向量表示後,我們需要思考下一個問題:比如在多數情況下,「香蕉」和「橘子」更加相似,而「香蕉」和「句子」就沒有那麼相似;同時,「香蕉」和「食物」、「水果」的相似程度可能介於「橘子」和「句子」之間。那麼如何讓儲存的詞向量具備這樣的語意資訊呢?

我們先學習自然語言處理領域的一個小技巧。在自然語言處理研究中,科研人員通常有一個共識:使用一個單詞的上下文來了解這個單詞的語意,比如:

「蘋果手機質量不錯,就是價格有點貴。」

「這個蘋果很好吃,非常脆。」

「菠蘿質量也還行,但是不如蘋果支援的APP多。」

在上面的句子中,我們通過上下文可以推斷出第一個「蘋果」指的是蘋果手機,第二個「蘋果」指的是水果蘋果,而第三個「菠蘿」指的應該也是一個手機。事實上,在自然語言處理領域,使用上下文描述一個詞語或者元素的語意是一個常見且有效的做法。我們可以使用同樣的方式訓練詞向量,讓這些詞向量具備表示語意資訊的能力。

2013年,Mikolov提出的經典word2vec演演算法就是通過上下文來學習語意資訊。word2vec包含兩個經典模型:CBOW(Continuous Bag-of-Words)和Skip-gram,如 圖4 所示。

  • CBOW:通過上下文的詞向量推理中心詞。
  • Skip-gram:根據中心詞推理上下文。

假設有一個句子「Pineapples are spiked and yellow」,兩個模型的推理方式如下:

  • CBOW中,先在句子中選定一箇中心詞,並把其它詞作為這個中心詞的上下文。如 圖4 CBOW所示,把「spiked」作為中心詞,把「Pineapples、are、and、yellow」作為中心詞的上下文。在學習過程中,使用上下文的詞向量推理中心詞,這樣中心詞的語意就被傳遞到上下文的詞向量中,如「spiked → pineapple」,從而達到學習語意資訊的目的。

  • Skip-gram中,同樣先選定一箇中心詞,並把其他詞作為這個中心詞的上下文。如 圖4 Skip-gram所示,把「spiked」作為中心詞,把「Pineapples、are、and、yellow」作為中心詞的上下文。不同的是,在學習過程中,使用中心詞的詞向量去推理上下文,這樣上下文定義的語意被傳入中心詞的表示中,如「pineapple → spiked」,
    從而達到學習語意資訊的目的。


說明:

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

2.1 CBOW和Skip-gram的演演算法實現

我們以這句話:「Pineapples are spiked and yellow」為例分別介紹CBOW和Skip-gram的演演算法實現。

圖5 所示,CBOW是一個具有3層結構的神經網路,分別是:

  • 輸入層: 一個形狀為C×V的one-hot張量,其中C代表上線文中詞的個數,通常是一個偶數,我們假設為4;V表示詞表大小,我們假設為5000,該張量的每一行都是一個上下文詞的one-hot向量表示,比如「Pineapples, are, and, yellow」。
  • 隱藏層: 一個形狀為V×N的引數張量W1,一般稱為word-embedding,N表示每個詞的詞向量長度,我們假設為128。輸入張量和word embedding W1進行矩陣乘法,就會得到一個形狀為C×N的張量。綜合考慮上下文中所有詞的資訊去推理中心詞,因此將上下文中C個詞相加得一個1×N的向量,是整個上下文的一個隱含表示。
  • 輸出層: 建立另一個形狀為N×V的引數張量,將隱藏層得到的1×N的向量乘以該N×V的引數張量,得到了一個形狀為1×V的向量。最終,1×V的向量代表了使用上下文去推理中心詞,每個候選詞的打分,再經過softmax函數的歸一化,即得到了對中心詞的推理概率:

$$