什么是Word2Vec和Embeddings奠涌?
Word2Vec是從大量文本語料中以無監(jiān)督的方式學(xué)習(xí)語義知識(shí)的一種模型固灵,它被大量地用在自然語言處理(NLP)中缅帘。那么它是如何幫助我們做自然語言處理呢轴术?Word2Vec其實(shí)就是通過學(xué)習(xí)文本來用詞向量的方式表征詞的語義信息,即通過一個(gè)嵌入空間使得語義上相似的單詞在該空間內(nèi)距離很近钦无。Embedding其實(shí)就是一個(gè)映射逗栽,將單詞從原先所屬的空間映射到新的多維空間中,也就是把原先詞所在空間嵌入到一個(gè)新的空間中去失暂。
我們從直觀角度上來理解一下彼宠,cat這個(gè)單詞和kitten屬于語義上很相近的詞,而dog和kitten則不是那么相近弟塞,iphone這個(gè)單詞和kitten的語義就差的更遠(yuǎn)了凭峡。通過對詞匯表中單詞進(jìn)行這種數(shù)值表示方式的學(xué)習(xí)(也就是將單詞轉(zhuǎn)換為詞向量),能夠讓我們基于這樣的數(shù)值進(jìn)行向量化的操作從而得到一些有趣的結(jié)論决记。比如說摧冀,如果我們對詞向量kitten、cat以及dog執(zhí)行這樣的操作:kitten - cat + dog,那么最終得到的嵌入向量(embedded vector)將與puppy這個(gè)詞向量十分相近索昂。
模型
Word2Vec模型中建车,主要有Skip-Gram和CBOW兩種模型,從直觀上理解椒惨,Skip-Gram是給定input word來預(yù)測上下文癞志。而CBOW是給定上下文,來預(yù)測input word框产。本篇文章僅講解Skip-Gram模型凄杯。
Skip-Gram模型的基礎(chǔ)形式非常簡單,為了更清楚地解釋模型秉宿,我們先從最一般的基礎(chǔ)模型來看Word2Vec(下文中所有的Word2Vec都是指Skip-Gram模型)戒突。
Word2Vec模型實(shí)際上分為了兩個(gè)部分,第一部分為建立模型描睦,第二部分是通過模型獲取嵌入詞向量膊存。Word2Vec的整個(gè)建模過程實(shí)際上與自編碼器(auto-encoder)的思想很相似,即先基于訓(xùn)練數(shù)據(jù)構(gòu)建一個(gè)神經(jīng)網(wǎng)絡(luò)忱叭,當(dāng)這個(gè)模型訓(xùn)練好以后隔崎,我們并不會(huì)用這個(gè)訓(xùn)練好的模型處理新的任務(wù),我們真正需要的是這個(gè)模型通過訓(xùn)練數(shù)據(jù)所學(xué)得的參數(shù)韵丑,例如隱層的權(quán)重矩陣——后面我們將會(huì)看到這些權(quán)重在Word2Vec中實(shí)際上就是我們試圖去學(xué)習(xí)的“word vectors”爵卒〕舷叮基于訓(xùn)練數(shù)據(jù)建模的過程巡语,我們給它一個(gè)名字叫“Fake Task”诗祸,意味著建模并不是我們最終的目的疼阔。
tips
上面提到的這種方法實(shí)際上會(huì)在無監(jiān)督特征學(xué)習(xí)(unsupervised feature learning)中見到伊脓,最常見的就是自編碼器(auto-encoder):通過在隱層將輸入進(jìn)行編碼壓縮碗短,繼而在輸出層將數(shù)據(jù)解碼恢復(fù)初始狀態(tài)受葛,訓(xùn)練完成后偎谁,我們會(huì)將輸出層“砍掉”总滩,僅保留隱層。
The Fake Task
我們在上面提到搭盾,訓(xùn)練模型的真正目的是獲得模型基于訓(xùn)練數(shù)據(jù)學(xué)得的隱層權(quán)重咳秉。為了得到這些權(quán)重,我們首先要構(gòu)建一個(gè)完整的神經(jīng)網(wǎng)絡(luò)作為我們的“Fake Task”鸯隅,后面再返回來看通過“Fake Task”我們?nèi)绾伍g接地得到這些詞向量澜建。
接下來我們來看看如何訓(xùn)練我們的神經(jīng)網(wǎng)絡(luò)向挖。假如我們有一個(gè)句子“The dog barked at the mailman”。
- 首先我們選句子中間的一個(gè)詞作為我們的輸入詞炕舵,例如我們選取“dog”作為input word何之;
- 有了input word以后,我們再定義一個(gè)叫做skip_window的參數(shù)咽筋,它代表著我們從當(dāng)前input word的一側(cè)(左邊或右邊)選取詞的數(shù)量溶推。如果我們設(shè)置skip_window=2,那么我們最終獲得窗口中的詞(包括input word在內(nèi))就是['The', 'dog'奸攻,'barked', 'at']蒜危。skip_window=2代表著選取左input word左側(cè)2個(gè)詞和右側(cè)2個(gè)詞進(jìn)入我們的窗口,所以整個(gè)窗口大小span=2x2=4睹耐。另一個(gè)參數(shù)叫num_skips辐赞,它代表著我們從整個(gè)窗口中選取多少個(gè)不同的詞作為我們的output word,當(dāng)skip_window=2硝训,num_skips=2時(shí)响委,我們將會(huì)得到兩組 (input word, output word) 形式的訓(xùn)練數(shù)據(jù),即 ('dog', 'barked')窖梁,('dog', 'the')赘风。
- 神經(jīng)網(wǎng)絡(luò)基于這些訓(xùn)練數(shù)據(jù)將會(huì)輸出一個(gè)概率分布,這個(gè)概率代表著我們的詞典中的每個(gè)詞是output word的可能性纵刘。這句話有點(diǎn)繞邀窃,我們來看個(gè)栗子。第二步中我們在設(shè)置skip_window和num_skips=2的情況下獲得了兩組訓(xùn)練數(shù)據(jù)彰导。假如我們先拿一組數(shù)據(jù) ('dog', 'barked') 來訓(xùn)練神經(jīng)網(wǎng)絡(luò)蛔翅,那么模型通過學(xué)習(xí)這個(gè)訓(xùn)練樣本敲茄,會(huì)告訴我們詞匯表中每個(gè)單詞是“barked”的概率大小位谋。
模型的輸出概率代表著到我們詞典中每個(gè)詞有多大可能性跟input word同時(shí)出現(xiàn)。舉個(gè)栗子堰燎,如果我們向神經(jīng)網(wǎng)絡(luò)模型中輸入一個(gè)單詞“Soviet“掏父,那么最終模型的輸出概率中赊淑,像“Union”陶缺, ”Russia“這種相關(guān)詞的概率將遠(yuǎn)高于像”watermelon“洁灵,”kangaroo“非相關(guān)詞的概率。因?yàn)椤盪nion“苫费,”Russia“在文本中更大可能在”Soviet“的窗口中出現(xiàn)百框。我們將通過給神經(jīng)網(wǎng)絡(luò)輸入文本中成對的單詞來訓(xùn)練它完成上面所說的概率計(jì)算。下面的圖中給出了一些我們的訓(xùn)練樣本的例子柬泽。我們選定句子“The quick brown fox jumps over lazy dog”聂抢,設(shè)定我們的窗口大小為2(window_size=2)棠众,也就是說我們僅選輸入詞前后各兩個(gè)詞和輸入詞進(jìn)行組合闸拿。下圖中新荤,藍(lán)色代表input word,方框內(nèi)代表位于窗口內(nèi)的單詞篱瞎。
我們的模型將會(huì)從每對單詞出現(xiàn)的次數(shù)中習(xí)得統(tǒng)計(jì)結(jié)果俐筋。例如澄者,我們的神經(jīng)網(wǎng)絡(luò)可能會(huì)得到更多類似(“Soviet“请琳,”Union“)這樣的訓(xùn)練樣本對俄精,而對于(”Soviet“竖慧,”Sasquatch“)這樣的組合卻看到的很少局冰。因此康二,當(dāng)我們的模型完成訓(xùn)練后沫勿,給定一個(gè)單詞”Soviet“作為輸入味混,輸出的結(jié)果中”Union“或者”Russia“要比”Sasquatch“被賦予更高的概率翁锡。
模型細(xì)節(jié)
我們?nèi)绾蝸肀硎具@些單詞呢馆衔?首先角溃,我們都知道神經(jīng)網(wǎng)絡(luò)只能接受數(shù)值輸入,我們不可能把一個(gè)單詞字符串作為輸入匆瓜,因此我們得想個(gè)辦法來表示這些單詞驮吱。最常用的辦法就是基于訓(xùn)練文檔來構(gòu)建我們自己的詞匯表(vocabulary)再對單詞進(jìn)行one-hot編碼左冬。
假設(shè)從我們的訓(xùn)練文檔中抽取出10000個(gè)唯一不重復(fù)的單詞組成詞匯表又碌。我們對這10000個(gè)單詞進(jìn)行one-hot編碼绊袋,得到的每個(gè)單詞都是一個(gè)10000維的向量铸鹰,向量每個(gè)維度的值只有0或者1蹋笼,假如單詞ants在詞匯表中的出現(xiàn)位置為第3個(gè)躁垛,那么ants的向量就是一個(gè)第三維度取值為1,其他維都為0的10000維的向量(ants=[0, 0, 1, 0, ..., 0])擂达。
還是上面的例子板鬓,“The dog barked at the mailman”俭令,那么我們基于這個(gè)句子抄腔,可以構(gòu)建一個(gè)大小為5的詞匯表(忽略大小寫和標(biāo)點(diǎn)符號(hào)):("the", "dog", "barked", "at", "mailman"),我們對這個(gè)詞匯表的單詞進(jìn)行編號(hào)0-4箱季。那么”dog“就可以被表示為一個(gè)5維向量[0, 1, 0, 0, 0]藏雏。
模型的輸入如果為一個(gè)10000維的向量掘殴,那么輸出也是一個(gè)10000維度(詞匯表的大凶嗾)的向量病瞳,它包含了10000個(gè)概率套菜,每一個(gè)概率代表著當(dāng)前詞是輸入樣本中output word的概率大小逗柴。
下圖是我們神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu):
隱層沒有使用任何激活函數(shù)戏溺,但是輸出層使用了sotfmax。
我們基于成對的單詞來對神經(jīng)網(wǎng)絡(luò)進(jìn)行訓(xùn)練耕拷,訓(xùn)練樣本是 ( input word, output word ) 這樣的單詞對骚烧,input word和output word都是one-hot編碼的向量止潘。最終模型的輸出是一個(gè)概率分布凭戴。
隱層
說完單詞的編碼和訓(xùn)練樣本的選取么夫,我們來看下我們的隱層档痪。如果我們現(xiàn)在想用300個(gè)特征來表示一個(gè)單詞(即每個(gè)詞可以被表示為300維的向量)腐螟。那么隱層的權(quán)重矩陣應(yīng)該為10000行乐纸,300列(隱層有300個(gè)結(jié)點(diǎn))汽绢。
Google在最新發(fā)布的基于Google news數(shù)據(jù)集訓(xùn)練的模型中使用的就是300個(gè)特征的詞向量宁昭。詞向量的維度是一個(gè)可以調(diào)節(jié)的超參數(shù)(在Python的gensim包中封裝的Word2Vec接口默認(rèn)的詞向量大小為100积仗, window_size為5)。
看下面的圖片本缠,左右兩張圖分別從不同角度代表了輸入層-隱層的權(quán)重矩陣斥扛。左圖中每一列代表一個(gè)10000維的詞向量和隱層單個(gè)神經(jīng)元連接的權(quán)重向量。從右邊的圖來看丹锹,每一行實(shí)際上代表了每個(gè)單詞的詞向量稀颁。
所以我們最終的目標(biāo)就是學(xué)習(xí)這個(gè)隱層的權(quán)重矩陣。
我們現(xiàn)在回來接著通過模型的定義來訓(xùn)練我們的這個(gè)模型楣黍。
上面我們提到匾灶,input word和output word都會(huì)被我們進(jìn)行one-hot編碼。仔細(xì)想一下租漂,我們的輸入被one-hot編碼以后大多數(shù)維度上都是0(實(shí)際上僅有一個(gè)位置為1)阶女,所以這個(gè)向量相當(dāng)稀疏,那么會(huì)造成什么結(jié)果呢秃踩。如果我們將一個(gè)1 x 10000的向量和10000 x 300的矩陣相乘消别,它會(huì)消耗相當(dāng)大的計(jì)算資源,為了高效計(jì)算,它僅僅會(huì)選擇矩陣中對應(yīng)的向量中維度值為1的索引行(這句話很繞),看圖就明白。
我們來看一下上圖中的矩陣運(yùn)算拥娄,左邊分別是1 x 5和5 x 3的矩陣,結(jié)果應(yīng)該是1 x 3的矩陣,按照矩陣乘法的規(guī)則掸刊,結(jié)果的第一行第一列元素為0 x 17 + 0 x 23 + 0 x 4 + 1 x 10 + 0 x 11 = 10蚓炬,同理可得其余兩個(gè)元素為12熄捍,19苹熏。如果10000個(gè)維度的矩陣采用這樣的計(jì)算方式是十分低效的。
為了有效地進(jìn)行計(jì)算,這種稀疏狀態(tài)下不會(huì)進(jìn)行矩陣乘法計(jì)算冀续,可以看到矩陣的計(jì)算的結(jié)果實(shí)際上是矩陣對應(yīng)的向量中值為1的索引凭需,上面的例子中滚澜,左邊向量中取值為1的對應(yīng)維度為3(下標(biāo)從0開始)塘淑,那么計(jì)算結(jié)果就是矩陣的第3行(下標(biāo)從0開始)—— [10, 12, 19]捌治,這樣模型中的隱層權(quán)重矩陣便成了一個(gè)”查找表“(lookup table)森枪,進(jìn)行矩陣計(jì)算時(shí),直接去查輸入向量中取值為1的維度下對應(yīng)的那些權(quán)重值。隱層的輸出就是每個(gè)輸入單詞的“嵌入詞向量”揍移。
輸出層
經(jīng)過神經(jīng)網(wǎng)絡(luò)隱層的計(jì)算罕邀,ants這個(gè)詞會(huì)從一個(gè)1 x 10000的向量變成1 x 300的向量竖席,再被輸入到輸出層艳馒。輸出層是一個(gè)softmax回歸分類器,它的每個(gè)結(jié)點(diǎn)將會(huì)輸出一個(gè)0-1之間的值(概率)陆爽,這些所有輸出層神經(jīng)元結(jié)點(diǎn)的概率之和為1。
下面是一個(gè)例子,訓(xùn)練樣本為 (input word: “ants”仔拟, output word: “car”) 的計(jì)算示意圖臀栈。
直覺上的理解
下面我們將通過直覺來進(jìn)行一些思考屎开。
如果兩個(gè)不同的單詞有著非常相似的“上下文”(也就是窗口單詞很相似,比如“Kitty climbed the tree”和“Cat climbed the tree”),那么通過我們的模型訓(xùn)練突倍,這兩個(gè)單詞的嵌入向量將非常相似腔稀。
那么兩個(gè)單詞擁有相似的“上下文”到底是什么含義呢?比如對于同義詞“intelligent”和“smart”羽历,我們覺得這兩個(gè)單詞應(yīng)該擁有相同的“上下文”焊虏。而例如”engine“和”transmission“這樣相關(guān)的詞語,可能也擁有著相似的上下文秕磷。
實(shí)際上诵闭,這種方法實(shí)際上也可以幫助你進(jìn)行詞干化(stemming),例如澎嚣,神經(jīng)網(wǎng)絡(luò)對”ant“和”ants”兩個(gè)單詞會(huì)習(xí)得相似的詞向量疏尿。
tips
詞干化(stemming)就是去除詞綴得到詞根的過程。