機(jī)器學(xué)習(xí)必須熟悉的算法之word2vector(一)

word2vector已經(jīng)成為NLP領(lǐng)域的基石算法。作為一名AI 從業(yè)者,如果不能主動去熟悉該算法,應(yīng)該感到臉紅。本文是一篇翻譯的文章,原文鏈接是:http://mccormickml.com/2016/04/19/word2vec-tutorial-the-skip-gram-model/
如果你的英語很好,強(qiáng)烈建議直接閱讀原文。這篇文章寫的非常好,簡明扼要,語言流暢。是我認(rèn)為入門word2vector的最好文章,沒有之一。當(dāng)然,我也不是生硬的翻譯,而是理解之后按照自己的邏輯再寫出來,希望能更加清晰一些。歡迎在評論中說出你的看法,多多交流。word2vector常見的有兩種算法CBOW和skip gram,本文使用skip gram算法作為講解對象。

一、算法的基本思想

word2vector,顧名思義,就是將語料庫中的詞轉(zhuǎn)化成向量,以便后續(xù)在詞向量的基礎(chǔ)上進(jìn)行各種計(jì)算。最常見的表示方法是counting 編碼。假設(shè)我們的語料庫中是如下三句話:
I like deep learning
I like NLP
I enjoy flying
利用counting編碼,我們可以繪出如下矩陣:


image.png

假設(shè)語料庫中的單詞數(shù)量是N,則上圖矩陣的大小就是N*N,其中的每一行就代表一個(gè)詞的向量表示。如第一行
0 2 1 0 0 0 0
是單詞I的向量表示。其中的2代表I這個(gè)單詞與like這個(gè)詞在語料庫中共同出現(xiàn)了2次。
似乎我們很簡單就完成了“word2vector”是不是?
但是這種辦法至少有三個(gè)缺陷:

  • 1是詞語數(shù)量較大時(shí),向量維度高且稀疏,向量矩陣巨大而難以存儲
  • 2是向量并不包含單詞的語義內(nèi)容,只是基于數(shù)量統(tǒng)計(jì)。
  • 3是當(dāng)有新的詞加入語料庫后,整個(gè)向量矩陣需要更新

盡管我們可以通過SVD來降低向量的維度,但是SVD本身卻是一個(gè)需要巨大計(jì)算量的操作。
很明顯,這種辦法在實(shí)際中并不好用。我們今天學(xué)習(xí)的skip gram算法可以成功克服以上三個(gè)缺陷。它的基本思想是首先將所有詞語進(jìn)行one-hot編碼,輸入只有一個(gè)隱藏層的神經(jīng)網(wǎng)絡(luò),定義好loss后進(jìn)行訓(xùn)練,后面我們會講解如何定義loss,這里暫時(shí)按下不表。訓(xùn)練完成后,我們就可以用隱藏層的權(quán)重來作為詞的向量表示?。?br> 這個(gè)思想乍聽起來很神奇是不是?其實(shí)我們早就熟悉它了。auto-encoder時(shí),我們也是用有一個(gè)隱藏層的神經(jīng)網(wǎng)絡(luò)進(jìn)行訓(xùn)練,訓(xùn)練完成后,丟去后面的output層,只用隱藏層的輸出作為最終需要的向量對象,藉此成功完成向量的壓縮。

二、舉例說明

1 構(gòu)造訓(xùn)練數(shù)據(jù)

假設(shè)我們的語料庫中只有一句話:
The quick brown fox jumps over the lazy dog.
這句話中共有8個(gè)詞(這里The與the算同一個(gè)詞)。
skip gram算法是怎么為這8個(gè)詞生成詞向量的呢?
我們知道用神經(jīng)網(wǎng)絡(luò)訓(xùn)練,大體有如下幾個(gè)步驟:

  • 準(zhǔn)備好data,即X和Y
  • 定義好網(wǎng)絡(luò)結(jié)構(gòu)
  • 定義好loss
  • 選擇合適的優(yōu)化器
  • 進(jìn)行迭代訓(xùn)練
  • 存儲訓(xùn)練好的網(wǎng)絡(luò)

所以,我們下面先來關(guān)注下如何確定X和Y的形式。
其實(shí)非常簡單,(x,y)就是一個(gè)個(gè)的單詞對。比如(the,quick)就是一個(gè)單詞對,the就是樣本數(shù)據(jù),quick就是該條樣本的標(biāo)簽。
那么,如何從上面那句話中生成單詞對數(shù)據(jù)呢?答案就是n-gram方法。多說不如看圖:

n-gram

我們以詞為單位掃描這句話,每掃描到一個(gè)詞,都把該詞左右各兩個(gè)詞共4個(gè)詞拿出來,分別與被掃描的單詞組成單詞對,作為我們的訓(xùn)練數(shù)據(jù)。
這里有兩個(gè)細(xì)節(jié),一個(gè)就是取被掃描單詞左右各2個(gè)詞,這里的2被稱為窗口尺寸,是可以調(diào)整的,用多大的窗口生成的單詞對來訓(xùn)練最好,需要具體問題具體分析。一般來說,取5是很好的經(jīng)驗(yàn)值。也就是左右各取5個(gè)單詞,共10個(gè)單詞。這里我們用2只是為了方便說明問題。
第二個(gè)細(xì)節(jié)就是句子頭尾的單詞被掃描時(shí),其能取的單詞對數(shù)要少幾個(gè),這個(gè)不影響大局,不用理會。

這里我們需要停下來細(xì)細(xì)琢磨下,我們這樣取單詞對作為訓(xùn)練數(shù)據(jù)的目的何在?以(fox,jumps)為例,jumps可以理解為fox的上下文,我們將fox輸入神經(jīng)網(wǎng)絡(luò)時(shí),希望網(wǎng)絡(luò)能夠告訴我們,在語料庫的8個(gè)單詞中,jumps是更可能出現(xiàn)在fox周圍的。
你可能會想,(fox,brown)也是一個(gè)單詞對,它輸入神經(jīng)網(wǎng)絡(luò)后,豈不是希望神經(jīng)網(wǎng)絡(luò)告訴我們,在8個(gè)單詞中,brown是更可能出現(xiàn)在fox周圍?如果是這樣,那么訓(xùn)練完成后的神經(jīng)網(wǎng)絡(luò),輸入fox,它的輸出會是brown和jumps的哪一個(gè)呢?
答案是取決于(fox,brown)和(fox,jumps)兩個(gè)單詞對誰在訓(xùn)練集中出現(xiàn)的次數(shù)比較多,神經(jīng)網(wǎng)絡(luò)就會針對哪個(gè)單詞對按照梯度下降進(jìn)行更多的調(diào)整,從而就會傾向于預(yù)測誰將出現(xiàn)在fox周圍。

2數(shù)字化表示單詞對

上面我們獲得了許多單詞對作為訓(xùn)練數(shù)據(jù),但是神經(jīng)網(wǎng)絡(luò)不能直接接收和輸出字符串形式的單詞對,所以需要將單詞對轉(zhuǎn)化為數(shù)字的形式。方法也很簡單,就是用one-hot編碼,如下圖所示:


image.png

(the,quick)單詞對就表示成
【(1,0,0,0,0,0,0,0),(0,1,0,0,0,0,0,0)】
這樣就可以輸入神經(jīng)網(wǎng)絡(luò)進(jìn)行訓(xùn)練了,當(dāng)我們將the輸入神經(jīng)網(wǎng)絡(luò)時(shí),希望網(wǎng)絡(luò)也能輸出一個(gè)8維的向量,并且第二維盡可能接近1,其他維盡可能接近0。也就是讓神經(jīng)網(wǎng)絡(luò)告訴我們,quick更可能出現(xiàn)在the的周圍。當(dāng)然,我們還希望這8維向量所有位置的值相加為1,WHY?因?yàn)橄嗉訛?就可以認(rèn)為這個(gè)8維向量描述的是一個(gè)概率分布,正好我們的y值也是一個(gè)概率分布(一個(gè)位置為1,其他位置為0),我們就可以用交叉熵來衡量神經(jīng)網(wǎng)絡(luò)的輸出與我們的label y的差異大小,也就可以定義出loss了。什么,你不知道啥是交叉熵?請參考我的另一篇文章【機(jī)器學(xué)習(xí)面試之各種混亂的熵】,應(yīng)該不會讓你失望。

3定義網(wǎng)絡(luò)結(jié)構(gòu)

通過之前的敘述,我們已經(jīng)基本知道神經(jīng)網(wǎng)絡(luò)應(yīng)該是什么樣子了,總結(jié)一下,可以確定如下情況:

  • 神經(jīng)網(wǎng)絡(luò)的輸入應(yīng)該是8維的向量
  • 神經(jīng)網(wǎng)絡(luò)只有一個(gè)隱藏層
  • 神經(jīng)網(wǎng)絡(luò)的輸出應(yīng)該是一個(gè)8維向量,且各維的值相加為1
    有了這些信息,我們可以很容易定義出如下的網(wǎng)絡(luò)結(jié)構(gòu):


    image.png

觀察這個(gè)網(wǎng)絡(luò)結(jié)構(gòu),我們可以發(fā)現(xiàn),它的隱藏層并沒有激活函數(shù),但是輸出層卻用了softmax,這是為了保證輸出的向量是一個(gè)概率分布。

3 隱藏層

顯然,輸出層的神經(jīng)元應(yīng)該是8個(gè),這樣才能輸出一個(gè)8維的向量。那么隱藏層的神經(jīng)元應(yīng)該是多少?
這取決于我們希望得到的詞向量是多少維,有多少個(gè)隱藏神經(jīng)元詞向量就是多少維。每一個(gè)隱藏的神經(jīng)元接收的輸入都是一個(gè)8維向量,假設(shè)我們的隱藏神經(jīng)元有3個(gè)(僅僅是為了舉例說明使用,實(shí)際中,google推薦的是300個(gè),但具體多少合適,需要你自己進(jìn)行試驗(yàn),怎么效果好怎么來),如此以來,隱藏層的權(quán)重就可以用一個(gè)8行3列的矩陣來表示,這個(gè)8行3列的矩陣的第一行,就是三個(gè)隱藏神經(jīng)元對應(yīng)于輸入向量第一維的權(quán)重,如下圖所示:


屏幕快照 2018-11-17 下午4.22.52.png

下面就是見證奇跡的時(shí)刻!

網(wǎng)絡(luò)訓(xùn)練完成后,這個(gè)8行3列的矩陣的每一行就是一個(gè)單詞的詞向量!如下圖所示:


image.png

so,訓(xùn)練完成后,我們只需要保存好隱藏層的權(quán)重矩陣即可,輸出層此時(shí)已經(jīng)完成歷史使命,可以丟掉了。
那么怎么使用去掉了輸出層的網(wǎng)絡(luò)呢?
我們知道,網(wǎng)絡(luò)的輸入是one-hot編碼的單詞,它與隱藏層權(quán)重矩陣相乘實(shí)際上是取權(quán)重矩陣特定的行,如下圖所示:


image.png

這意味著,隱藏層實(shí)際上相當(dāng)于是一個(gè)查找表,它的輸出就是輸入的單詞的詞向量。

4輸出層

當(dāng)我們從隱藏層獲得一個(gè)單詞的詞向量后,就要經(jīng)過輸出層了。
輸出層的神經(jīng)元數(shù)量和語料庫中的單詞數(shù)量一樣。每一個(gè)神經(jīng)元可以認(rèn)為對應(yīng)一個(gè)單詞的輸出權(quán)重,詞向量乘以該輸出權(quán)重就得到一個(gè)數(shù),該數(shù)字代表了輸出神經(jīng)元對應(yīng)的單詞出現(xiàn)在輸入單詞周圍的可能性大小,通過對所有的輸出層神經(jīng)元的輸出進(jìn)行softmax操作,我們就把輸出層的輸出規(guī)整為一個(gè)概率分布了。如下圖所示:

output layer

這里有一點(diǎn)需要注意,我們說輸出的是該單詞出現(xiàn)在輸入單詞周圍的概率大小,這個(gè)“周圍”包含單詞的前面,也包含單詞的后面。

三、直覺的啟示

前面,我們表示,skip gram算法生成的詞向量可以包含語義信息,也就是說,語義相近的詞其詞向量也相近。這里,我們給一個(gè)直覺的解釋。
首先,語義相近的詞往往有著類似的上下文。這是什么意思呢?舉例來說,“聰明”和“伶俐”兩個(gè)詞語義是相近的,那么它們的使用場景也是相似的,它們周圍的詞很大程度上是相近或相同的。
語義相近的詞有著相似的上下文,讓我們的神經(jīng)網(wǎng)絡(luò)在訓(xùn)練過程中對相近的詞產(chǎn)生相近的輸出向量。網(wǎng)絡(luò)如何做到這一點(diǎn)呢?答案就是訓(xùn)練完成后,網(wǎng)絡(luò)能夠?qū)φZ義相近的詞產(chǎn)生相近的詞向量。因?yàn)榇藭r(shí)的輸出層已經(jīng)訓(xùn)練完成,不會改變了。

這個(gè)直覺式的思考顯然是不嚴(yán)謹(jǐn)?shù)?,但卻能讓我們對神經(jīng)網(wǎng)絡(luò)有很好的洞見。

記得李宏毅說過,有人問,LSTM設(shè)計(jì)那么復(fù)雜,設(shè)計(jì)的人怎么知道這樣的結(jié)構(gòu)就能達(dá)到記憶的效果呢?事實(shí)上,不是知道這樣做會有記憶的效果才去這樣做,而是這樣做了,才有這樣的效果。是不是有點(diǎn)雞生蛋蛋生雞的趕腳?這就是為什么深度學(xué)習(xí)被稱為玄學(xué)的原因吧。

四、下篇預(yù)告

你可能注意到了,skip-gram算法構(gòu)造的神經(jīng)網(wǎng)絡(luò)神經(jīng)元太多了,導(dǎo)致權(quán)重矩陣非常大。 假設(shè)我們的語料庫中的詞有10000個(gè),生成的詞向量為300維。那么權(quán)重系數(shù)就有10000*300*2那么多,訓(xùn)練如此巨大的網(wǎng)絡(luò)難度很大。下一篇文章中會介紹一些小技巧,幫助我們減小訓(xùn)練的難度,使得訓(xùn)練是可行的。

最后編輯于
?著作權(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)容

  • 開發(fā)中,使用到數(shù)據(jù)庫一般會使用FMDB這個(gè)第三方庫,來簡化使用。FMDB是iOS平臺的SQLite數(shù)據(jù)庫框架,它以...
    笑忘書丶閱讀 1,574評論 0 2
  • 始終相信技多不壓身,雖然沒有在工作中使用到git,但是作為一個(gè)合格的tester,還是非常有必要要學(xué)習(xí)一下的,畢竟...
    亭子青年閱讀 1,882評論 5 21

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