介紹詞向量word2evc概念,及CBOW和Skip-gram的演演算法實現。
專案連結: https://aistudio.baidu.com/aistudio/projectdetail/5009409
在自然語言處理任務中,詞向量(Word Embedding)是表示自然語言裡單詞的一種方法,即把每個詞都表示為一個N維空間內的點,即一個高維空間內的向量。通過這種方法,實現把自然語言計算轉換為向量計算。
如 圖1 所示的詞向量計算任務中,先把每個詞(如queen,king等)轉換成一個高維空間的向量,這些向量在一定意義上可以代表這個詞的語意資訊。再通過計算這些向量之間的距離,就可以計算出詞語之間的關聯關係,從而達到讓計算機像計算數值一樣去計算自然語言的目的。
因此,大部分詞向量模型都需要回答兩個問題:
自然語言單詞是離散訊號,比如「香蕉」,「橘子」,「水果」在我們看來就是3個離散的詞。
如何把每個離散的單詞轉換為一個向量?
比如,我們知道在很多情況下,「香蕉」和「橘子」更加相似,而「香蕉」和「句子」就沒有那麼相似,同時「香蕉」和「食物」、「水果」的相似程度可能介於「橘子」和「句子」之間。
那麼,我們該如何讓詞向量具備這樣的語意資訊?
自然語言單詞是離散訊號,比如「我」、「 愛」、「人工智慧」。如何把每個離散的單詞轉換為一個向量?通常情況下,我們可以維護一個如 圖2 所示的查詢表。表中每一行都儲存了一個特定詞語的向量值,每一列的第一個元素都代表著這個詞本身,以便於我們進行詞和向量的對映(如「我」對應的向量值為 [0.3,0.5,0.7,0.9,-0.2,0.03] )。給定任何一個或者一組單詞,我們都可以通過查詢這個excel,實現把單詞轉換為向量的目的,這個查詢和替換過程稱之為Embedding Lookup。
上述過程也可以使用一個字典資料結構實現。事實上如果不考慮計算效率,使用字典實現上述功能是個不錯的選擇。然而在進行神經網路計算的過程中,需要大量的算力,常常要藉助特定硬體(如GPU)滿足訓練速度的需求。GPU上所支援的計算都是以張量(Tensor)為單位展開的,因此在實際場景中,我們需要把Embedding Lookup的過程轉換為張量計算,如 圖3 所示。
假設對於句子"我,愛,人工,智慧",把Embedding Lookup的過程轉換為張量計算的流程如下:
通過查詢字典,先把句子中的單詞轉換成一個ID(通常是一個大於等於0的整數),這個單詞到ID的對映關係可以根據需求自定義(如圖3中,我=>1, 人工=>2,愛=>3,...)。
得到ID後,再把每個ID轉換成一個固定長度的向量。假設字典的詞表中有5000個詞,那麼,對於單詞「我」,就可以用一個5000維的向量來表示。由於「我」的ID是1,因此這個向量的第一個元素是1,其他元素都是0([1,0,0,…,0]);同樣對於單詞「人工」,第二個元素是1,其他元素都是0。用這種方式就實現了用一個向量表示一個單詞。由於每個單詞的向量表示都只有一個元素為1,而其他元素為0,因此我們稱上述過程為One-Hot Encoding。
經過One-Hot Encoding後,句子「我,愛,人工,智慧」就被轉換成為了一個形狀為 4×5000的張量,記為$V$。在這個張量裡共有4行、5000列,從上到下,每一行分別代表了「我」、「愛」、「人工」、「智慧」四個單詞的One-Hot Encoding。最後,我們把這個張量$V$和另外一個稠密張量$W$相乘,其中$W$張量的形狀為5000 × 128(5000表示詞表大小,128表示每個詞的向量大小)。經過張量乘法,我們就得到了一個4×128的張量,從而完成了把單詞表示成向量的目的。
得到每個單詞的向量表示後,我們需要思考下一個問題:比如在多數情況下,「香蕉」和「橘子」更加相似,而「香蕉」和「句子」就沒有那麼相似;同時,「香蕉」和「食物」、「水果」的相似程度可能介於「橘子」和「句子」之間。那麼如何讓儲存的詞向量具備這樣的語意資訊呢?
我們先學習自然語言處理領域的一個小技巧。在自然語言處理研究中,科研人員通常有一個共識:使用一個單詞的上下文來了解這個單詞的語意,比如:
「蘋果手機質量不錯,就是價格有點貴。」
「這個蘋果很好吃,非常脆。」
「菠蘿質量也還行,但是不如蘋果支援的APP多。」
在上面的句子中,我們通過上下文可以推斷出第一個「蘋果」指的是蘋果手機,第二個「蘋果」指的是水果蘋果,而第三個「菠蘿」指的應該也是一個手機。事實上,在自然語言處理領域,使用上下文描述一個詞語或者元素的語意是一個常見且有效的做法。我們可以使用同樣的方式訓練詞向量,讓這些詞向量具備表示語意資訊的能力。
2013年,Mikolov提出的經典word2vec演演算法就是通過上下文來學習語意資訊。word2vec包含兩個經典模型:CBOW(Continuous Bag-of-Words)和Skip-gram,如 圖4 所示。
假設有一個句子「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不會刻意迴避生僻字。
我們以這句話:「Pineapples are spiked and yellow」為例分別介紹CBOW和Skip-gram的演演算法實現。
如 圖5 所示,CBOW是一個具有3層結構的神經網路,分別是:
$$