1. 問題抽象
skip gram是已知中間詞,最大化它相鄰詞的概率。
與CBOW的不同:CBOW的時候,是選取一次負採樣;而這裏對於中間詞的上下文的每一個詞,每一次都需要進行一個負採樣。
下面看一下條件概率:
與之前的CBOW大體形式一樣,不同之處:
(1)隱含層輸出的是中間詞對應的詞向量;而CBOW是輸出的所有中間詞上下文詞向量對應的和;
(2)theta:上下文的詞,或者是上下文的詞選出來的負樣本的詞與輸出層之間的全連接;
2. 損失函數
採用log損失函數。
但是,可以發現如果按照這個loss去對v(w)或者theta求偏導,在每一輪迭代的時候,只能夠對詞向量v(w)進行一次迭代。這裏需要進行上下文窗口次的負採樣才能對一個詞的詞向量進行迭代。顯然,效率有些低。
在真正的word2vec實現的時候,需要變換一下思路:
同樣也是基於像CBOW一樣的思想,已知上下文(Wc)的情況下,最大化中間詞。但是這裏上下文的每一個詞(Wc)都是獨立的,不像CBOW是對上下文中所有的詞進行累加。
下面重新看一下損失函數:
3. 訓練主流程
1. 對於中心詞上下文中的每一個詞,都需要選取一次負採樣,也就是構造出正負樣本;
2. 計算loss對於theta以及Wc的偏導;
計算偏導也是有順序的,像CBOW首先更新loss對於Wc的偏導,因爲這個偏導是最後我們需要更新詞向量偏導的 1/n (n負採樣的數目 + 正樣本 + 1);
3. 更新Wc對應的詞向量;
skip gram與CBOW相比,每一次負採樣skip gram只能更新一個詞對應的詞向量;而CBOW在一次負採樣,可以更新n(n指窗口)個詞。
4. 負採樣的算法
假設詞典(訓練樣本中所有的詞)中有n個詞,每一個詞都會計算出一個長度,這個長度是一個0-1之間的長度,有的短,有的長,所有詞的長度加起來=1。
每一次的長度計算:
分子:該單詞在所有語料中出現的次數;冪次:相當於做了一個平緩;
分母:語料中所有詞出現的次數累加和。
然後,初始一個非常大的數,源碼中採用10^8,將0-1進行等分。然後每一段都會對應一個詞的值域。
eg:m0屬於w1,m5屬於w2。
在每次進行負採樣的過程中,會隨機一個0-M之間的數,隨機完數字之後,也就知道了隨機的哪一個詞。eg:隨機到了1,那麼就是w1詞。
注意:如果隨機到的詞是中心詞,那麼就跳過去,再進行一次隨機。