本文介紹
- wordvec的概念
- 語言模型訓練的兩種模型CBOW+skip gram
- word2vec 優化的兩種方法:層次softmax+負采樣
- gensim word2vec默認用的模型和方法
未經許可,不要轉載。
機器學習的輸入都是數字,而NLP都是文字; 為了讓機器學習應用在NLP上,需要把文字轉換為數字,把文字嵌入到數學空間。
1. 詞表示:
-
詞的獨熱表示:onehot (詞之間是孤立的)
- onehot:
- 思想:假設詞表大小為N, 則每個單字表示為N維向量; 每個單字只有1位為1,其他為0;茫茫0海中一個1
- 缺點:詞之間是孤立的;維度太大
- onehot:
-
詞的分布式表示:(能描述詞之間的語義關系)
- 基於矩陣的分布式表示
- 基於聚類的分布式表示
- 基於神經網絡的分布表示,詞嵌入 word embedding
- 將01表示改為浮點數表述;降維
- word2vec是用神經網絡訓練語言模型(NNLM)過程中得到的參數.
-
其他概念
- 語言模型: 就是一段文字成為句子的概率; 經常用的ngram, n=2或3
2. NNLM 神經網絡語言模型
用神經網絡訓練語言模型,常見有兩種; 用上下文預測term(CBOW), 用term預測上下文(skip-gram),結構一般是簡單三層網絡,一個輸入層、一個隱含層、一個輸出層。
2.1 CBOW 連續詞袋模型

- 變量:詞表大小V, 要嵌入到N維空間中,C/2是窗口大小,即上下文取幾個term(不算當前term);- N一般取50~300
- 步驟:參考自 https://www.zhihu.com/question/44832436
- input layer:窗口內的C個詞的onehot表示
- input layer -> hidden layer:(V維表示降到N維表示)
- 通過權重矩陣\(W_{V\times N}\) ,將 \(V \times C\)映射為 $N \times C $
- hidden layer + 激活函數:C個詞表示為1個詞
- word2vec中激活函數,用了簡單取平均;
- hidden layer -> output layer:1個N維詞還原到高維V維中;
- 通過權重矩陣\(W_{N\times V}^{'}\) ,將 \(N \times 1\)映射為 \(V\times 1\)
- output layer + softmax 激活函數,將值歸一化到0~1之間 y
- 用BP+梯度下降優化cost function y和真實y之間的距離,迭代優化參數 \(W、W^{'}\)
- 收斂result:y是V維向量,每個元素取值0~1, 將最大元素值,還原為onehot編碼,就是最終結果了。
2.2 skip-gram 語言模型
思路同CBOW, 只是輸入是1個詞,輸出是C個詞;
一般用BP訓練得到參數,預測用一次前向傳播;
3. word2vec用的優化方法
word2vec結合了CBOW, skip-gram的方法 訓練得到參數\(W\), 但在計算中做了很多優化;
可以看到,NNLM計算中,兩個問題導致計算量大;
- 詞表維度大;
- softmax計算量大;
下面介紹兩種優化方法;
3.1 hierarchical softmax 層次softmax
/ˌhī(ə)ˈrärkikəl/
-
huffman: 帶權路徑長度最短為目標,可以用log(V)長度的編碼表示

帶權路徑長度WPL:
- 圖a: 5 * 2 + 7 * 2 + 2 * 2 +13 * 2 = 54
- 圖b:5 * 3 + 2 * 3 + 7 * 2 + 13 * 1 = 48 (huffman, 帶權路徑長度較小)
- 參考自: https://zhuanlan.zhihu.com/p/56139075
-
層次softmax
softmax需要對每個詞語都計算輸出概率,並進行歸一化,計算量很大;
進行softmax的目的是多分類,那么是否可以轉成多個二分類問題呢, 如SVM思想? 從而引入了層次softmax-
示意圖

-
為什么有效?
- 1)用huffman編碼做詞表示
- 2)把N分類變成了log(N)個2分類。 如要預測的term(足球)的編碼長度為4,則可以把預測為'足球',轉換為4次二分類問題,在每個二分類上用二元邏輯回歸的方法(sigmoid);
- 3)邏輯回歸的二分類中,sigmoid函數導數有很好的性質,\(\sigma^{'}(x) = \sigma(x)(1-\sigma(x))\)
- 4)采用隨機梯度上升求解二分類,每計算一個樣本更新一次誤差函數
-
參考自:http://flyrie.top/2018/10/31/Word2vec_Hierarchical_Softmax/
-
gensim的word2vec 默認已經不采用分層softmax了, 因為$log_2 1000=10 $也挺大的;如果huffman的根是生僻字,則分類次數更多;
-
3.2 高頻詞抽樣+負采樣
為了解決NNLM中softmax過程的計算性能問題,通常有幾種優化技巧:
- 將常見的單詞組合(word pairs)或者詞組作為單個“words”來處理
- 對高頻次單詞進行抽樣來減少訓練樣本的個數
- 對優化目標采用“negative sampling”方法,這樣每個訓練樣本的訓練只會更新一小部分的模型權重,從而降低計算負擔
參考自:https://www.jianshu.com/p/56554a63410f
3.2.1 對高頻詞抽樣
主要思想是少訓練沒有區分度的高頻term;
對於我們在訓練原始文本中遇到的每一個單詞,它們都有一定概率被我們從文本中刪掉,而這個被刪除的概率與單詞的頻率有關。詞頻越高(stopword),抽樣越少;
-

-
抽樣率 \(P(w_{i}) = (\sqrt{\frac{Z(w_i)}{t}}+1)\times \frac{t}{Z(w_i)} = \sqrt{\frac{t}{Z(w_i)}} + \frac{t}{Z(w_i)}\) ,其中
-
\(Z(w_i)\)是詞在語料中的出現概率,反比關系,越高頻詞抽的越少;
-
\(t\)是設定的閾值,正比關系,\(t\)越大,不同頻率單詞的采樣概率差異越大; gensim word2vec中默認值是0.001
-
抽樣率直觀理解
import numpy as np import matplotlib.pyplot as plt x = np.array(range(1, 100)) / 1000.0 t1 = 0.001 t2 = 0.0001 y1 = np.power(t1/x, 0.5) + t1/x y2 = np.power(t2/x, 0.5) + t2/x plt.plot(x, y1, '-', label='t=0.001') plt.plot(x, y2, '-', label='t=0.0001') plt.legend()
-
3.2.2 負采樣 Negative sampling
- 問題:在NNLM中對於每個樣本w, 都要更新一次hidden->output的參數陣\(W^{'}_{N\times V}\),計算量很大;比如詞表大小V=10000, N=300, 那么權重矩陣有300萬個參數;
- 思想:如果每次只更新目標詞(正例 positive word)和少數幾個負例(negative words), 那么計算量會顯著減少; 比如如果我們每次只更新M=1+5個,則更新了6*300=1800, 1800/300萬=0.06%; 計算量減少了3個數量級。
- negative words如何選擇:根據詞表中出現的概率,出現概率越高,被選作負樣本的概率越高;
- \(P(w_i) = \frac{f(w_i)^{3/4}}{\sum_{j=0}^{v}{f(w_j)^{3/4}}}\), 其中\(f(w_j)\)是出現的概率,3/4是經驗值,比線性關系更弱化了些;
4. gensim word2vec默認參數(CBOW+負采樣)
默認用了CBOW模型,采用高頻詞抽樣+負采樣進行優化;
from gensim.models import Word2Vec
word2vec.Word2Vec(sentences=None, size=100, alpha=0.025, window=5, min_count=5, max_vocab_size=None, sample=0.001, seed=1, workers=3, min_alpha=0.0001, sg=0, hs=0, negative=5, ns_exponent=0.75, cbow_mean=1, iter=5, null_word=0, trim_rule=None, sorted_vocab=1, batch_words=10000, compute_loss=False, callbacks=(), max_final_vocab=None)
- 上下文窗口大小:window=5
- 忽略低頻次term:min_count=5
- 語言模型是用CBOW還是skip-gram?sg=0 是CBOW
- 優化方法是用層次softmax還是負采樣:hs=0 是負采樣
- 負采樣樣本數: negative=5 (一般設為5-20)
- 負采樣采樣概率的平滑指數:ns_exponent=0.75
- 高頻詞抽樣的閾值 sample=0.001

