TF入門04-TF實現Word2Vec

Word2Vec是一組用來產生詞嵌入的模型,包括兩種主要的模型:skip-gram和CBOW。

Skip-gram vs CBOW

算法層面上, 兩種模型很相似,CBOW模型是從兩邊預測中心詞,skip-gram模型是中心詞預測兩邊。比如,對於“The quick brown fox jumps”,CBOW模型從上下文"the, “quick”, “fox”, 和"jumps"預測中心詞“brown”,skip-gram模型從“brown”預測上下文"the, “quick”, “fox”, 和"jumps"。

統計層面上,CBOW模型通過將上下文看做一個樣本組成,將分佈信息做了平滑處理。大多數情況下,cbow模型適用於小型數據集;skip-gram模型將每個上下文-中心詞對看做一個樣本,用在大型數據集上表現更好。

在本文中,我們使用skip-gram模型來構建word2vec。爲了得到詞嵌入向量,我們需要構建一個單隱藏層的神經網絡,然後用來執行特定任務來完成訓練;但是訓練得到的模型並不是我們需要的。我們只關注隱藏層的權重,這些權重就是詞嵌入向量。

上面的特定任務是指給定中心詞預測上下文。對於句子中的某個詞,在詞的上下文中隨機選擇一個詞;網絡模型可以輸出整個詞典中每個詞是中心詞上下文的概率。

Softmax、Negative Sampling & Noise Contrastive Estimation(NCE)

爲了得到某個詞的所有可能上下文詞的概率分佈,我們使用softmax來實現。softmax函數根據輸入xix_i輸出一個概率值pip_i。在這裏xix_i表示中心詞的一個可能的上下文:
softmax(xi)=exp(xi)jexp(xj) softmax(x_i) = \frac{exp(x_i)}{\sum_j exp(x_j)}
但是,softmax用於歸一化的分母的計算需要遍歷整個詞典,通常情況下詞典長度在百萬級別,而且指數的計算也比較耗時,這就導致了softmax的計算量進一步加大

爲了規避這個計算瓶頸,我們可以使用分層softmax(hierarchical softmax)和基於採樣的softmax。論文Distributed Representations of Words and Phrases and their Compositionality 指出訓練skip-gram模型,和分層softmax方法相比,使用negative sampling的方法訓練速度更快,得到的詞向量更好。

Negative Sampling(負採樣)是基於採樣方法的一種。基於採樣的方法也包括重要性採樣(importance sampling)和目標採樣(target sampling)。負採樣方法是NCE的簡化版:負採樣對噪聲樣本(負樣本)的採樣數量k以及噪聲數據服從的分佈Q做了假定,kQ(w)=1

負採樣方法用於學習詞嵌入表示,並不能保證其梯度值和softmax函數梯度值相近;而NCE方法隨着負樣本採樣數的增加其提取值也愈來愈逼近於softmax的梯度值。Mnih and Teh(2012)表明使用25個噪聲樣本的計算結果與softmax的計算值差距不大,而且運算速度能加快45倍。因此,我們使用NCE來實現word2vec。

基於採樣的方法,無論是負採樣還是NCE方法,只適用於訓練階段;在應用階段還需要執行softmax來得到正則化的概率結果。

數據介紹

2006年3月3日的維基百科文本的100MB數據text8。

100MB數據訓練得到的詞嵌入雖然表現不太好,但是從中也能看到一些有趣的現象。使用空格切分數據後,文本包括17005207個詞。爲了得到更好的詞嵌入,需要使用更大的數據集。

Overview

使用TensorFlow實現模型,需要景觀兩個階段:定義計算圖以及圖的運行。

階段一:圖定義

  1. 導入數據(tf.data 、placeholders)
  2. 定義權重
  3. 定義模型
  4. 定義損失函數loss
  5. 定義優化器

階段二:執行運算圖

  1. 變量初始化
  2. 初始化迭代器/向模型傳送數據
  3. 執行前向計算
  4. 計算cost
  5. 梯度計算來調整模型參數

階段一:圖定義

1. 創建dataset,生成樣本

skip-gram模型的輸入爲(中心詞,上下文詞)pair對。數據傳送到模型之前,需要將字符串類型轉換成indices表示,如果“computer”是詞典中第100個單詞,那麼對象下標爲99。

每一個樣本數據是一個標量,BATCH_SIZE個輸入樣本的構成tensor的shape 爲[BATCH_SIZE],輸出樣本的shape爲[BATCH_sIZE, 1].

2.定義權重

在embedding矩陣中每一行表示一個詞的向量表示。如果詞向量長度爲EMBED_SIZE,embedding矩陣的shape爲[VOCAB_SIZE, EMBED_SIZE]

3. Inference

爲了從embed_matrix中得到對應輸入的詞向量表示,我們可以使用tf.nn.embedding_lookup來實現:

這個函數相當於一個查表操作,根據輸入ids在params找到對應的向量。

如果輸入是one_hot表示,向量乘以矩陣可以很快地找到one_hot非零值對應的向量(one_hot中非零值爲第4個,相乘後結果就是矩陣的第4行);使用相乘方法,由於one_hot表示有很多0值進而會產生許多不必要的計算;使用tf.nn.lookup就可以節省這些不必要的計算。

爲了得到中心詞的embedding表示,

embed = tf.nn.embedding_lookup(embed_matrix, center_words, name='embed')

4. 定義損失函數

​ TensorFlow已經爲我們實現了NCE損失函數:

tf.nn.nce_loss(
    weights,
    biases,
    labels,
    inputs,
    num_sampled,
    num_classes,
    num_true=1,
    sampled_values=None,
    remove_accidental_hits=False,
    partition_strategy='mod',
    name='nce_loss'
)

爲了計算NCE loss,需要定義計算loss的隱藏層權重weights和偏置biases。在訓練過程中這些參數會自動更新、優化。在採樣之後,最終結果的計算過程如下:

tf.matmul(embed, tf.transpose(nce_weight)) + nce_bias

這項計算包含在tf.nn_nce_loss的計算過程中。

nce_weight = tf.get_variable('nce_weight', shape=[VOCAB_SIZE, EMBED_SIZE], initializer=tf.truncated_normal_initializer(stddev=1.0 / (EMBED_SIZE ** 0.5)))
nce_bias = tf.get_variable('nce_bias', initializer=tf.zeros([VOCAB_SIZE]))

損失函數定義如下:

loss = tf.reduce_mean(tf.nn.nce_loss(weights=nce_weight,
                              biases=nce_bias,
                              labels=target_words,
                              inputs=embed,
                              num_sampled=NUM_SAMPLED,
                              num_classes=VOCAB_SIZE))

5. 定義優化器

optimizer = tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(loss)

階段二:圖的執行

創建一個會話來執行優化op。

with tf.Session() as sess:
    # 迭代器初始化
    sess.run(iterator.initializer)
    # 變量初始化
    sess.run(tf.global_variables_initializer())

    writer = tf.summary.FileWriter('graphs/word2vec_simple', sess.graph)

    for index in range(NUM_TRAIN_STEPS):
        try:
            # 執行優化,計算loss
            loss_batch, _ = sess.run([loss, optimizer])
        except tf.errors.OutOfRangeError:
            sess.run(iterator.initializer)
    writer.close()

完整代碼地址:ClickMe


歡迎關注公衆號,一起學習

Reference

Stanford CS 20: Tensorflow for Deep Learning Research

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章