word2vec原理總結

一篇很好的入門博客,http://mccormickml.com/2016/04/19/word2vec-tutorial-the-skip-gram-model/算法

他的翻譯,https://www.jianshu.com/p/1405932293ea網絡

能夠做爲參考的,https://blog.csdn.net/mr_tyting/article/details/80091842函數

有論文和代碼,https://blog.csdn.net/mr_tyting/article/details/80091842post

word2vector,顧名思義,就是將語料庫中的詞轉化成向量,以便後續在詞向量的基礎上進行各類計算。學習

最多見的表示方法是counting 編碼。假設咱們的語料庫中是以下三句話:優化

I like deep learning
I like NLP
I enjoy flying
利用counting編碼,咱們能夠繪出以下矩陣:ui

 

假設語料庫中的單詞數量是N,則上圖矩陣的大小就是N*N,其中的每一行就表明一個詞的向量表示。如第一行
0 2 1 0 0 0 0
是單詞I的向量表示。其中的2表明I這個單詞與like這個詞在語料庫中共同出現了2次。google

可是這種辦法至少有三個缺陷:編碼

  • 1是詞語數量較大時,向量維度高且稀疏,向量矩陣巨大而難以存儲
  • 2是向量並不包含單詞的語義內容,只是基於數量統計。
  • 3是當有新的詞加入語料庫後,整個向量矩陣須要更新

儘管咱們能夠經過SVD來下降向量的維度,可是SVD自己倒是一個須要巨大計算量的操做。
很明顯,這種辦法在實際中並很差用。咱們今天學習的skip gram算法能夠成功克服以上三個缺陷。它的基本思想是首先將全部詞語進行one-hot編碼,輸入只有一個隱藏層的神經網絡,定義好loss後進行訓練,後面咱們會講解如何定義loss,這裏暫時按下不表。訓練完成後,咱們就能夠用隱藏層的權重來做爲詞的向量表示!!
這個思想乍聽起來很神奇是否是?其實咱們早就熟悉它了。auto-encoder時,咱們也是用有一個隱藏層的神經網絡進行訓練,訓練完成後,丟去後面的output層,只用隱藏層的輸出做爲最終須要的向量對象,藉此成功完成向量的壓縮。.net

Word2Vec工做流程

Word2Vec有兩種訓練方法,一種叫CBOW,核心思想是從一個句子裏面把一個詞摳掉,用這個詞的上文和下文去預測被摳掉的這個詞;第二種叫作Skip-gram,和CBOW正好反過來,輸入某個單詞,要求網絡預測它的上下文單詞。下面以Skip-gram爲例介紹,

一、word2Vec只是一個三層 的神經網絡。
二、餵給模型一個word,而後用來預測它周邊的詞。
三、而後去掉最後一層,只保存input_layer 和 hidden_layer。
四、從詞表中選取一個詞,餵給模型,在hidden_layer 將會給出該詞的embedding repesentation。

用神經網絡訓練,大致有以下幾個步驟:

準備好data,即X和Y
定義好網絡結構
定義好loss
選擇合適的優化器
進行迭代訓練
存儲訓練好的網絡

1、構造訓練數據

假設咱們的語料庫中只有一句話:The quick brown fox jumps over the lazy dog.
這句話中共有8個詞(這裏The與the算同一個詞)。skip gram算法是怎麼爲這8個詞生成詞向量的呢?

其實很是簡單,(x,y)就是一個個的單詞對。好比(the,quick)就是一個單詞對,the就是樣本數據,quick就是該條樣本的標籤。
那麼,如何從上面那句話中生成單詞對數據呢?答案就是n-gram方法。多說不如看圖:

咱們以詞爲單位掃描這句話,每掃描到一個詞,都把該詞左右各兩個詞共4個詞拿出來,分別與被掃描的單詞組成單詞對,做爲咱們的訓練數據。

這裏有兩個細節,一個就是取被掃描單詞左右各2個詞,這裏的2被稱爲 窗口尺寸,是能夠調整的,用多大的窗口生成的單詞對來訓練最好,須要具體問題具體分析。通常來講,取5是很好的經驗值。也就是左右各取5個單詞,共10個單詞。第二個細節就是句子頭尾的單詞被掃描時,其能取的單詞對數要少幾個,這個不影響大局,不用理會。
這裏咱們須要停下來細細琢磨下,咱們這樣取單詞對做爲訓練數據的目的何在?以(fox,jumps)爲例,jumps能夠理解爲fox的上下文,咱們將fox輸入神經網絡時,但願網絡可以告訴咱們,在語料庫的8個單詞中,jumps是更可能出如今fox周圍的。
你可能會想,(fox,brown)也是一個單詞對,它輸入神經網絡後,豈不是但願神經網絡告訴咱們,在8個單詞中,brown是更可能出如今fox周圍?若是是這樣,那麼訓練完成後的神經網絡,輸入fox,它的輸出會是brown和jumps的哪個呢?
答案是取決於(fox,brown)和(fox,jumps)兩個單詞對誰在訓練集中出現的次數比較多,神經網絡就會針對哪一個單詞對按照梯度降低進行更多的調整,從而就會傾向於預測誰將出如今fox周圍。

2、數字化表示單詞對

上面咱們得到了許多單詞對做爲訓練數據,可是神經網絡不能直接接收和輸出字符串形式的單詞對,因此須要將單詞對轉化爲數字的形式。方法也很簡單,就是用one-hot編碼,以下圖所示:

 

(the,quick)單詞對就表示成【(1,0,0,0,0,0,0,0),(0,1,0,0,0,0,0,0)】。這樣就能夠輸入神經網絡進行訓練了,當咱們將the輸入神經網絡時,但願網絡也能輸出一個8維的向量,而且第二維儘量接近1(即接近quick),其餘維儘量接近0。也就是讓神經網絡告訴咱們,quick更可能出如今the的周圍。固然,咱們還但願這8維向量全部位置的值相加爲1,由於相加爲1就能夠認爲這個8維向量描述的是一個機率分佈,正好咱們的y值也是一個機率分佈(一個位置爲1,其餘位置爲0),咱們就能夠用交叉熵來衡量神經網絡的輸出與咱們的label y的差別大小,也就能夠定義出loss了。

三、網絡結構
網絡結構以下,它的隱藏層並無激活函數,可是輸出層卻用了softmax,這是爲了保證輸出的向量是一個機率分佈。

 

四、隱藏層
輸出層的神經元應該是8個,這樣才能輸出一個8維的向量。那麼隱藏層的神經元應該是多少?
這取決於咱們但願獲得的詞向量是多少維,有多少個隱藏神經元詞向量就是多少維。每個隱藏的神經元接收的輸入都是一個8維向量,假設咱們的隱藏神經元有3個(僅僅是爲了舉例說明使用,實際中,google推薦的是300個,但具體多少合適,須要你本身進行試驗,怎麼效果好怎麼來),如此以來,隱藏層的權重就能夠用一個8行3列的矩陣來表示,這個8行3列的矩陣的第一行,就是三個隱藏神經元對應於輸入向量第一維的權重,以下圖所示:

 

網絡訓練完成後,這個8行3列的矩陣的每一行就是一個單詞的詞向量!以下圖所示:

網絡的輸入是one-hot編碼的單詞,它與隱藏層權重矩陣相乘其實是取權重矩陣特定的行,以下圖所示:

 

這意味着,隱藏層實際上至關因而一個查找表,它的輸出就是輸入的單詞的詞向量


五、輸出層
當咱們從隱藏層得到一個單詞的詞向量後,就要通過輸出層了。
輸出層的神經元數量和語料庫中的單詞數量同樣。每個神經元能夠認爲對應一個單詞的 輸出權重,詞向量乘以該 輸出權重就獲得一個數,該數字表明瞭輸出神經元對應的單詞出如今輸入單詞周圍的可能性大小,經過對全部的輸出層神經元的輸出進行softmax操做,咱們就把輸出層的輸出規整爲一個機率分佈了。以下圖所示:

這裏有一點須要注意,咱們說輸出的是該單詞出如今輸入單詞周圍的機率大小,這個「周圍」包含單詞的前面,也包含單詞的後面。

 
前面,咱們表示,skip gram算法生成的詞向量能夠包含語義信息,也就是說,語義相近的詞其詞向量也相近。這裏,咱們給一個直覺的解釋。
首先,語義相近的詞每每有着相似的上下文。這是什麼意思呢?舉例來講,「聰明」和「伶俐」兩個詞語義是相近的,那麼它們的使用場景也是類似的,它們周圍的詞很大程度上是相近或相同的。
語義相近的詞有着類似的上下文,讓咱們的神經網絡在訓練過程當中對相近的詞產生相近的輸出向量。網絡如何作到這一點呢?答案就是訓練完成後,網絡可以對語義相近的詞產生相近的詞向量。由於此時的輸出層已經訓練完成,不會改變了。
 
六、負採樣
咱們知道對於訓練語言模型來講,softmax層很是難算,畢竟你要預測的是當前位置是哪一個詞,那麼這個類別數就等同於詞典規模,所以動輒幾萬幾十萬的類別數,算softmax函數固然很費力啦。可是,若是咱們的目標不在於訓練一個精準的語言模型,而只是爲了訓練獲得語言模型的副產物-詞向量,那麼其實只須要用這裏隱含的一個計算代價更小的「子任務」就好啦。
 
想想,給你10000張寫有數字的卡片,讓你找出其中的較大值,是否是特別費力?可是若是把裏面的較大值事先抽出來,跟五張隨機抽取的卡片混到一塊兒,讓你選出其中的較大值,是否是就容易多啦?
 
負採樣就是這個思想,即不直接讓模型從整個詞表找最可能的詞了,而是直接給定這個詞(即正例)和幾個隨機採樣的噪聲詞(即採樣出來的負例),只要模型能從這裏面找出正確的詞就認爲完成目標啦。因此這個想法對應的目標函數即:

在tensorflow裏面實現的word2Vec,vocab_szie並非全部的word的數量,並且先統計了全部word的出現頻次,而後選取出現頻次最高的前50000的詞做爲詞袋。具體操做請看代碼 tensorflow/examples/tutorials/word2vec/word2vec_basic.py,其他的詞用unkunk代替。採用一種所謂的」負採樣」的操做,這種操做每次可讓一個樣本只更新權重矩陣中一小部分,減少訓練過程當中的計算壓力。 舉例來講:一個input output pair如:(「fox」,「quick」),由上面的分析可知,其true label爲一個one−hot向量,而且該向量只是在quick的位置爲1,其他的位置均爲0,而且該向量的長度爲vocab size,由此每一個樣本都緩慢能更新權重矩陣,而」負採樣」操做只是隨機選擇其他的部分word,使得其在true label的位置爲0,那麼咱們只更新對應位置的權重。例如咱們若是選擇負採樣數量爲5,則選取5個其他的word,使其對應的output爲0,這個時候output只是6個神經元,原本咱們一次須要更新300∗10,000參數,進行負採樣操做之後只須要更新300∗6=1800個參數。

相關文章
相關標籤/搜索