一篇很好的入門博客,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
可是這種辦法至少有三個缺陷:編碼
儘管咱們能夠經過SVD來下降向量的維度,可是SVD自己倒是一個須要巨大計算量的操做。
很明顯,這種辦法在實際中並很差用。咱們今天學習的skip gram算法能夠成功克服以上三個缺陷。它的基本思想是首先將全部詞語進行one-hot編碼,輸入只有一個隱藏層的神經網絡,定義好loss後進行訓練,後面咱們會講解如何定義loss,這裏暫時按下不表。訓練完成後,咱們就能夠用隱藏層的權重來做爲詞的向量表示!!
這個思想乍聽起來很神奇是否是?其實咱們早就熟悉它了。auto-encoder時,咱們也是用有一個隱藏層的神經網絡進行訓練,訓練完成後,丟去後面的output層,只用隱藏層的輸出做爲最終須要的向量對象,藉此成功完成向量的壓縮。.net
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方法。多說不如看圖:
(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了。
四、隱藏層
網絡訓練完成後,這個8行3列的矩陣的每一行就是一個單詞的詞向量!以下圖所示:
網絡的輸入是one-hot編碼的單詞,它與隱藏層權重矩陣相乘其實是取權重矩陣特定的行,以下圖所示:
這意味着,隱藏層實際上至關因而一個查找表,它的輸出就是輸入的單詞的詞向量
這裏有一點須要注意,咱們說輸出的是該單詞出如今輸入單詞周圍的機率大小,這個「周圍」包含單詞的前面,也包含單詞的後面。
在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個參數。