Tensorflow教程-字詞的向量表示
Vector Representations of Words
在本教程我們來看一下tensorflow/g3doc/tutorials/word2vec/word2vec_basic.py檢視到一個最簡單的實現。這個基本的例子提供的程式碼可以完成下載一些資料,簡單訓練後展示結果。一旦你覺得已經完全掌握了這個簡單版本,你可以檢視向量空間模型 (VSMs)將詞彙表達(巢狀)於一個連續的向量空間中,語義近似的詞彙被對映為相鄰的資料點。向量空間模型在自然語言處理領域中有著漫長且豐富的歷史,不過幾乎所有利用這一模型的方法都依賴於 潛在語義分析), 和 預測方法 (e.g. Baroni et al.,不過簡而言之:基於計數的方法計算某詞彙與其鄰近詞彙在一個大型語料庫中共同出現的頻率及其他統計量,然後將這些統計量對映到一個小型且稠密的向量中。預測方法則試圖直接從某詞彙的鄰近詞彙對其進行預測,在此過程中利用已經學習到的小型且稠密的巢狀向量
Word2vec是一種可以進行高效率詞巢狀學習的預測模型。其兩種變體分別為:連續詞袋模型(CBOW)及Skip-Gram模型。從演算法角度看,這兩種方法非常相似,其區別為CBOW根據源詞上下文詞彙('the cat sits on the')來預測目標詞彙(例如,‘mat’),而Skip-Gram模型做法相反,它通過目標詞彙來預測源詞彙。Skip-Gram模型採取CBOW的逆過程的動機在於:CBOW演算法對於很多分散式資訊進行了平滑處理(例如將一整段上下文資訊視為一個單一觀察量)。很多情況下,對於小型的資料集,這一處理是有幫助的。相形之下,Skip-Gram模型將每個“上下文-目標詞彙”的組合視為一個新觀察量,這種做法在大型資料集中會更為有效。本教程餘下部分將著重講解Skip-Gram模型。
處理噪聲對比訓練
神經概率化語言模型通常使用softmax function 來最大化當提供前一個單詞 h(代表 "history"),後一個單詞的概率 (代表 "target"),
當 score(w_t,h) 計算了文字 w_t 和 上下文 h 的相容性(通常使用向量積)。我們使用對數似然函式來訓練訓練集的最大值,比如通過:
這裡提出了一個解決語言概率模型的合適的通用方法。然而這個方法實際執行起來開銷非常大,因為我們需要去計算並正則化當前上下文環境 h 中所有其他 V 單詞 w' 的概率得分,在每一步訓練迭代中。
從另一個角度來說,當使用word2vec模型時,我們並不需要對概率模型中的所有特徵進行學習。而CBOW模型和Skip-Gram模型為了避免這種情況發生,使用一個二分類器(邏輯迴歸)在同一個上下文環境裡從 k
從數學角度來說,我們的目標是對每個樣本最大化:
其中 代表的是資料集在當前上下文 h ,根據所學習的巢狀向量 ,目標單詞 w 使用二分類邏輯迴歸計算得出的概率。在實踐中,我們通過在噪聲分佈中繪製比對文字來獲得近似的期望值(通過計算負抽樣,而且使用這個損失函式在數學層面上也有很好的解釋:這個更新過程也近似於softmax函式的更新。這在計算上將會有很大的優勢,因為當計算這個損失函式時,只是有我們挑選出來的 k 個 噪聲單詞,而沒有使用整個語料庫 V。這使得訓練變得非常快。我們實際上使用了與Levy
et al.,比如說把目標單詞左邊的內容當做一個‘上下文’,或者以目標單詞右邊的內容,等等。現在我們把目標單詞的左右單詞視作一個上下文, 使用大小為1的視窗,這樣就得到這樣一個由(上下文,
目標單詞)
組成的資料集:
([the, brown], quick), ([quick, fox], brown), ([brown, jumped], fox), ...
前文提到Skip-Gram模型是把目標單詞和上下文顛倒過來,所以在這個問題中,舉個例子,就是用'quick'來預測 'the' 和 'brown' ,用 'brown' 預測 'quick' 和 'brown' 。因此這個資料集就變成由(輸入,
輸出)
組成的:
(quick, the), (quick, brown), (brown, quick), (brown, fox), ...
目標函式通常是對整個資料集建立的,但是本問題中要對每一個樣本(或者是一個batch_size
很小的樣本集,通常設定為16
<= batch_size <= 512
)在同一時間執行特別的操作,稱之為t-SNE 降緯技術。當我們用視覺化的方式來觀察這些向量,就可以很明顯的獲取單詞之間語義資訊的關係,這實際上是非常有用的。當我們第一次發現這樣的誘導向量空間中,展示了一些特定的語義關係,這是非常有趣的,比如文字中 male-female,gender 甚至還有 country-capital 的關係,
如下方的圖所示 (也可以參考 Collobert et al.或者 tensorflow/g3doc/tutorials/word2vec/word2vec_basic.py)。Skip-Gram模型有兩個輸入。一個是一組用整型表示的上下文單詞,另一個是目標單詞。給這些輸入建立佔位符節點,之後就可以填入資料了。
# 建立輸入佔位符
train_inputs = tf.placeholder(tf.int32, shape=[batch_size])
train_labels = tf.placeholder(tf.int32, shape=[batch_size, 1])
然後我們需要對批資料中的單詞建立巢狀向量,TensorFlow提供了方便的工具函式。
embed = tf.nn.embedding_lookup(embeddings, train_inputs)
好了,現在我們有了每個單詞的巢狀向量,接下來就是使用噪聲-比對的訓練方式來預測目標單詞。
# 計算 NCE 損失函式, 每次使用負標籤的樣本.
loss = tf.reduce_mean(
tf.nn.nce_loss(nce_weights, nce_biases, embed, train_labels,
num_sampled, vocabulary_size))
我們對損失函式建立了圖形節點,然後我們需要計算相應梯度和更新引數的節點,比如說在這裡我們會使用隨機梯度下降法,TensorFlow也已經封裝好了該過程。
# 使用 SGD 控制器.
optimizer = tf.train.GradientDescentOptimizer(learning_rate=1.0).minimize(loss)
訓練模型
訓練的過程很簡單,只要在迴圈中使用feed_dict
不斷給佔位符填充資料,同時呼叫 session.run
即可。
for inputs, labels in generate_batch(...):
feed_dict = {training_inputs: inputs, training_labels: labels}
_, cur_loss = session.run([optimizer, loss], feed_dict=feed_dict)
巢狀學習結果視覺化
使用t-SNE來看一下巢狀學習完成的結果。
超引數的選擇對該問題解決的準確性有巨大的影響。想要模型具有很好的表現,需要有一個巨大的訓練資料集,同時仔細調整引數的選擇並且使用例如二次抽樣的一些技巧。不過這些問題已經超出了本教程的範圍。
優化實現
以上簡單的例子展示了TensorFlow的靈活性。比如說,我們可以很輕鬆得用現成的tf.nn.sampled_softmax_loss()
來代替tf.nn.nce_loss()
構成目標函式。如果你對損失函式想做新的嘗試,你可以用TensorFlow手動編寫新的目標函式的表示式,然後用控制器執行計算。這種靈活性的價值體現在,當我們探索一個機器學習模型時,我們可以很快地遍歷這些嘗試,從中選出最優。
一旦你有了一個滿意的模型結構,或許它就可以使實現執行地更高效(在短時間內覆蓋更多的資料)。比如說,在本教程中使用的簡單程式碼,實際執行速度都不錯,因為我們使用Python來讀取和填裝資料,而這些在TensorFlow後臺只需執行非常少的工作。如果你發現你的模型在輸入資料時存在嚴重的瓶頸,你可以根據自己的實際問題自行實現一個數據閱讀器,參考 新的資料格式。對於Skip-Gram 模型,我們已經完成了如下這個例子tensorflow/models/embedding/word2vec_optimized.py。請自行調節以上幾個過程的標準,使模型在每個執行階段有更好地效能。
總結
在本教程中我們介紹了word2vec模型,它在解決詞巢狀問題中具有良好的效能。我們解釋了使用詞巢狀模型的實用性,並且討論瞭如何使用TensorFlow實現該模型的高效訓練。總的來說,我們希望這個例子能夠讓向你展示TensorFlow可以提供實驗初期的靈活性,以及在後期優化模型時對模型內部的可操控性。
原文地址:btpeter 校對:waiwaizheng