基于keras實(shí)現(xiàn)word2vec

譯:https://adventuresinmachinelearning.com/word2vec-keras-tutorial/

很多博客都闡述了word2vec這個(gè)模型的原理,例如空間映射、稠密向量表示,cbow/skip-gram,softmax求解,霍夫曼樹,blabla...

但數(shù)學(xué)公式理解起來比較抽象,結(jié)合工程實(shí)現(xiàn)可以更好的幫助理解。

word2vec

理解Word2Vec單詞嵌入是機(jī)器學(xué)習(xí)歷程中的關(guān)鍵組成部分。詞嵌入是在機(jī)器學(xué)習(xí)模型中執(zhí)行高效自然語言處理的必要步驟。本文將展示如何在Keras深度學(xué)習(xí)框架中執(zhí)行Word2Vec單詞嵌入。同時(shí),本文還將展示當(dāng)我們的詞匯表非常大時(shí),使用基于softmax的詞嵌入訓(xùn)練方案會導(dǎo)致訓(xùn)練過程極其緩慢。一種稱為“負(fù)采樣”的技術(shù)已經(jīng)解決這個(gè)問題,并且已經(jīng)在TensorFlow中實(shí)現(xiàn)了(nce_loss)。

不幸的是,這個(gè)損失函數(shù)在Keras中不存在,因此在本文中,我們將自己實(shí)現(xiàn)它。這也是因禍得福了,因?yàn)樽约簩?shí)現(xiàn)它將有助于我們理解負(fù)采樣如何工作,從而更好地理解Word2Vec Keras過程。


詞嵌入

如果我們用一批文檔去訓(xùn)練某種自然語言機(jī)器學(xué)習(xí)系統(tǒng)(比如聊天機(jī)器人),我們需要?jiǎng)?chuàng)建所有文檔中最常用單詞的詞匯表。在某些情況下,該詞匯表的長度可能大于10,000個(gè)單詞。為了向我們的機(jī)器學(xué)習(xí)模型表示一個(gè)單詞,一種很淳樸的方式是使用one-hot表示,即一個(gè)全0的矢量,除了表示我們那個(gè)單詞的位置設(shè)置為1。但是這是一種低效的方式 ,一個(gè)10,000字的向量是很難訓(xùn)練的。另一個(gè)問題是,這些one-hot向量不包含單詞語義信息,如何讓它在文檔的上下文中連貫使用?(比如一詞多義?)

詞嵌入的目的是將大的one-hot向量“壓縮”成更小的向量(幾百個(gè)元素),這些向量保留了單詞的一些含義和上下文,而Word2Vec是最常用的詞嵌入方法。

上下文,word2Vec以及skip-gram模型

表達(dá)詞的上下文是word2Vec最關(guān)鍵的作用?!皌he cat sat on the mat”這句話中“sat”一詞的上下文是(“the”,“cat”,“on”,“the”,“mat”)。換句話說,這些詞是通常出現(xiàn)在目標(biāo)詞“sat”周圍的詞。具有相似上下文的單詞在Word2Vec下具有相似的詞義,并且壓縮它們的向量維度后,所表示的意義也是相似的。在word2Vec的skip-gram模型版本中(稍后將詳細(xì)介紹),目標(biāo)是獲取目標(biāo)詞,即“sat”,并預(yù)測其周圍的上下文詞。

這種學(xué)習(xí)的最終產(chǎn)物是網(wǎng)絡(luò)中的嵌入層,這個(gè)嵌入層其實(shí)是一種查找表:每行表示我們詞匯表中相應(yīng)單詞的向量。舉個(gè)栗子:我們設(shè)詞匯表有6個(gè)詞,one-hot表示就是一個(gè)6維的向量,通過詞嵌入將維度壓縮到3(假設(shè)數(shù)據(jù)哦??):

原詞匯表 one-hot 壓縮后的向量
[1,0,0,0,0,0] [0.2,-0.5,-0.7]
[0,1,0,0,0,0] [0.8,0.5,0.7]
機(jī) [0,0,1,0,0,0] [0.4,-0.3,0.6]
[0,0,0,1,0,0] [0.1,-0.1,-0.9]
學(xué) [0,0,0,0,1,0] [0.2,-0.3,0.6]
習(xí) [0,0,0,0,0,1] [0.9,-0.4,-0.8]

可以看到,每個(gè)單詞(行)由大小為3的向量表示。這種嵌入層/查找表可以使用簡單的神經(jīng)網(wǎng)絡(luò)和softmax輸出訓(xùn)練得出,如下圖所示:


Word2Vec-softmax網(wǎng)絡(luò)結(jié)構(gòu)

上面的神經(jīng)網(wǎng)絡(luò)的輸入是以one-hot表示的目標(biāo)詞,接著通過隱藏層的訓(xùn)練,讓有效上下文單詞的概率增加,同時(shí)讓無效上下文單詞的概率降低(也就是在目標(biāo)單詞的周圍上下文中從不出現(xiàn)的單詞)。softmax函數(shù)負(fù)責(zé)輸出最后的概率。訓(xùn)練完成后,輸出層將被丟棄,我們的嵌入向量就是隱藏層的權(quán)重。

Word2Vec有兩種形式:skip-gram和CBOW。skip-gram輸入目標(biāo)詞預(yù)測周圍的上下文詞,而CBOW正好相反,輸入一組上下文詞預(yù)測其中的目標(biāo)詞。本文我們只考慮skip-gram(效果好一些)。

softmax VS negative sampling

使用softmax輸出的問題在于它的計(jì)算量非常大??紤]softmax函數(shù)的定義:

P(y = j \mid x)= \frac{e ^ {x ^ T w_j}} {\sum_{k = 1} ^ K e ^ {x ^ T w_k}}

這里的P為輸出為類j的概率。分子的算法:將隱藏層的輸出與連接到類j輸出層的權(quán)重相乘;分母的算法:對所有輸出類采用與分子相同的算法,并求和。如果輸出采用一個(gè)10000維的one-hot向量表示,那采用梯度下降算法求解模型時(shí),需要計(jì)算數(shù)以百萬計(jì)的權(quán)重,這會非常耗時(shí)且效率低下。

還有一種稱為負(fù)抽樣的解決方案。它在Mikolov等人的原始Word2Vec論文中有所描述。簡單理解為:所有將目標(biāo)詞與目標(biāo)詞上下文連在一起的網(wǎng)絡(luò),則增強(qiáng)它們的權(quán)重;而對于非目標(biāo)詞上下文的網(wǎng)絡(luò),不是去降低它們的權(quán)重,而是簡單的對它們進(jìn)行下采樣。這就是negative sampling。

為了在Keras中使用負(fù)樣本訓(xùn)練嵌入層,我們可以重新設(shè)想我們訓(xùn)練網(wǎng)絡(luò)的方式。我們可以將原來的softmax層替換為簡單的二分類器。對于在目標(biāo)詞的上下文中的單詞,我們希望我們的網(wǎng)絡(luò)輸出1,對于我們的負(fù)樣本,我們希望我們的網(wǎng)絡(luò)輸出0。因此,我們基于keras實(shí)現(xiàn)的Word2Vec網(wǎng)絡(luò)的輸出層只是一個(gè)sigmoid。

我們還需要一種方法來確保進(jìn)過網(wǎng)絡(luò)訓(xùn)練后,相似的單詞最終具有類似的嵌入向量。因此,我們要確保在相同上下文中出現(xiàn)的詞,網(wǎng)絡(luò)總是輸出1,而從未在相同上下文中出現(xiàn)的詞,網(wǎng)絡(luò)總是輸出0。因此,我們需要提供sigmoid輸出層一個(gè)矢量相似性得分:相似矢量輸出高分和不相似矢量輸出低分。兩個(gè)向量之間使用的最典型的相似性度量是余弦相似度得分:

similarity = cos(\theta)= \frac{\textbf {A} \cdot \textbf {B}} {\parallel \textbf {A} \parallel_2 \parallel \textbf {B} \parallel_2}

這種度量方法的分母用于歸一化結(jié)果,真正的相似性操作在分子上:向量AB之間的點(diǎn)積

綜上所述,我們基于Keras的Word2Vec實(shí)現(xiàn)新的負(fù)抽樣網(wǎng)絡(luò)具有以下特點(diǎn):

  • 目標(biāo)詞的(整數(shù))輸入,上下文詞的正負(fù)例
  • 嵌入層查找(即在嵌入矩陣中查找單詞的整數(shù)索引以獲取單詞向量)
  • 點(diǎn)積運(yùn)算
  • 輸出sigmoid層

實(shí)現(xiàn)的體系結(jié)構(gòu)如下所示:


Negative-sampling結(jié)構(gòu)圖

讓我們更仔細(xì)地考慮這個(gè)架構(gòu)。首先,我們詞匯表中的每個(gè)單詞都被賦予一個(gè)介于0和我們詞匯表大小之間的整數(shù)索引(在本例中為10,000)。我們將兩個(gè)單詞傳遞到網(wǎng)絡(luò)中,一個(gè)是目標(biāo)詞,另一個(gè)是來自周圍上下文的單詞或負(fù)樣本。我們利用輸入詞的索引來“查找”嵌入層(10,000 x 300權(quán)重張量)的行,以檢索這個(gè)詞對應(yīng)的維度為300單詞向量。然后,我們在這些向量之間執(zhí)行點(diǎn)積運(yùn)算以獲得相似性。最后,我們將相似性輸出到sigmoid層,匹配上了上下文的詞輸出1,未匹配的輸出0。


實(shí)現(xiàn)

本節(jié)將展示如何創(chuàng)建自己的基于Keras的Word2Vec實(shí)現(xiàn) - 代碼在此。

數(shù)據(jù)提取

我們首先需要一些數(shù)據(jù)。在Word2Vec TensorFlow教程中,我們將使用此處的文檔數(shù)據(jù)集。為了提取信息,我將使用上述Word2Vec教程中的一些相同的文本提取函數(shù),特別是collect_data函數(shù)。這個(gè)函數(shù)實(shí)現(xiàn)了下載數(shù)據(jù),將文本數(shù)據(jù)轉(zhuǎn)成了由字符串表示的整數(shù)(詞匯表中的每個(gè)單詞由唯一的整數(shù)表示)。要調(diào)用此函數(shù),我們運(yùn)行:

vocab_size = 10000
data, count, dictionary, reverse_dictionary = collect_data(vocabulary_size=vocab_size)

數(shù)據(jù)集前7個(gè)詞是:

[‘a(chǎn)narchism’, ‘originated’, ‘a(chǎn)s’, ‘a(chǎn)’, ‘term’, ‘of’, ‘a(chǎn)buse’]

運(yùn)行collect_data函數(shù)后,這7個(gè)詞詞表示為:

[5239, 3082, 12, 6, 195, 2, 3134]

從collect_data返回還有兩個(gè)詞典:第一個(gè)可以查找單詞并獲得其整數(shù)表示,第二個(gè)正好相反。

接下來,我們需要為訓(xùn)練定義一些常量,并創(chuàng)建一組驗(yàn)證集以便我們檢查詞向量的學(xué)習(xí)情況。

常量和驗(yàn)證集

window_size = 3
vector_dim = 300
epochs = 1000000

valid_size = 16     # Random set of words to evaluate similarity on.
valid_window = 100  # Only pick dev samples in the head of the distribution.
valid_examples = np.random.choice(valid_window, valid_size, replace=False)
  • 第一個(gè)常量 window_size是目標(biāo)單詞周圍的單詞窗口,用于從中繪制上下文單詞。
  • 第二個(gè)常量vector_dim是每個(gè)字嵌入向量的大?。何覀兊那度雽拥拇笮?0,000 x 300。
  • 最后,我們有一個(gè)大的epochs變量:指定了的訓(xùn)練迭代次數(shù)。即使采用負(fù)抽樣,詞嵌入也可能是一個(gè)耗時(shí)的過程。

下一組參數(shù)與我們要檢查的單詞相關(guān),以查看其他單詞與此驗(yàn)證集的相似之處。在訓(xùn)練過程中,我們將通過詞嵌入向量來檢查哪些單詞開始就被認(rèn)為是相似的,并確保這些單詞與我們對這些單詞的含義的理解相符。我們將從數(shù)據(jù)集前100個(gè)最常見的單詞中隨機(jī)選擇16個(gè)單詞進(jìn)行檢查(collect_data 按升序分配數(shù)據(jù)集整數(shù)中最常用的單詞,即最常用的單詞分配1,下一個(gè)最常見的2)。

接下來,我們來看看keras為我們準(zhǔn)備的skip-gram函數(shù)。

未完待續(xù)。。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容