本文章內(nèi)容主要翻譯自Word2Vec Tutorial - The Skip-Gram Model箱锐,英文水平還可以的建議去看原文渡蜻。
word2vec是word embedding(詞向量)的一種淺層神經(jīng)網(wǎng)絡(luò)訓(xùn)練方法甜熔。通俗的講就是把一個(gè)詞變成一個(gè)詞向量狐蜕。這篇文章主要介紹word2vec 中的skip gram模型糖儡。word2vec還用到了CBOW模型悴品,這個(gè)在本文不做介紹白对。
Part 1
The Model
skip-gram模型結(jié)構(gòu)實(shí)際上出乎意料的簡(jiǎn)單掠廓。
我們先從比較宏觀的角度來(lái)看看我們到底要干嘛。Word2Vec使用了一個(gè)可能你在機(jī)器學(xué)習(xí)的其他地方也見(jiàn)過(guò)的trick甩恼。我們打算訓(xùn)練一個(gè)單隱藏層的簡(jiǎn)單網(wǎng)絡(luò)模型來(lái)完成一個(gè)明確的任務(wù)蟀瞧。但是我們實(shí)際上并不用這個(gè)我們訓(xùn)練的神經(jīng)網(wǎng)絡(luò)來(lái)完成這個(gè)任務(wù)。我們的目的是為了學(xué)習(xí)到隱藏層的權(quán)重条摸。實(shí)際上這些權(quán)重實(shí)際上就是 word vector悦污。所以說(shuō)我們構(gòu)建這個(gè)神經(jīng)網(wǎng)絡(luò)只是個(gè)假任務(wù),真任務(wù)是要它的隱藏層權(quán)重钉蒲。
另一個(gè)你能夠看到這個(gè)trick的地方是非監(jiān)督特征的學(xué)習(xí)切端,你在隱藏層訓(xùn)練一個(gè)auto-encode用來(lái)壓縮輸入的vector。然后在輸出的時(shí)候再進(jìn)行解壓回原樣顷啼。當(dāng)訓(xùn)練好后踏枣,直接去掉輸出層(解壓的部分),只使用隱藏層钙蒙。這是在沒(méi)有標(biāo)簽的訓(xùn)練數(shù)據(jù)的情況下學(xué)習(xí)好的圖片特征的一個(gè)方法茵瀑。
The Fake Task
我們先來(lái)談?wù)勥@個(gè)假任務(wù),然后再反過(guò)來(lái)再看看它是如何間接的給了我們所需的word vector躬厌。
我們打斷這樣來(lái)進(jìn)行訓(xùn)練马昨。首先給定一個(gè)sentence中的一個(gè)word(input word),然后隨機(jī)取一個(gè)這個(gè)word上下文的word扛施。這個(gè)網(wǎng)絡(luò)用來(lái)告訴我們鸿捧,對(duì)于詞表中的每個(gè)單詞,我們隨機(jī)挑一個(gè)“nearby word”疙渣,每個(gè)詞的概率匙奴。
當(dāng)我們提到“nearby”的時(shí)候,實(shí)際上是這個(gè)算法中的窗口大小昌阿。一個(gè)典型的窗口大小是5饥脑,即前后各5個(gè)word,一共10個(gè)words懦冰。
輸出的概率代表了在input word的nearby能夠找到這個(gè)word的可能性大小灶轰。例如你給已經(jīng)訓(xùn)練好的模型輸入一個(gè)單詞‘Soviet’,輸出的各個(gè)單詞刷钢,像‘Union’及‘Russia’這類的單詞的概率要比‘watemelon’這類不相干的單詞要高笋颤。
我們通過(guò)給網(wǎng)絡(luò)輸入一堆訓(xùn)練文本中的單詞對(duì)來(lái)對(duì)其進(jìn)行訓(xùn)練。下圖展示了一些我們從句子”The quick brown fox jumps over the lazy dog.“中提取出來(lái)用來(lái)訓(xùn)練網(wǎng)絡(luò)模型的單詞對(duì)。在這個(gè)例子中伴澄,窗口大小設(shè)置為2赋除,藍(lán)色的word表示input word。
這個(gè)網(wǎng)絡(luò)是用來(lái)統(tǒng)計(jì)單詞對(duì)出現(xiàn)的頻次的非凌。所以举农,加入這個(gè)網(wǎng)絡(luò)輸入很多(“Soviet”, “Union”)的單詞對(duì)以及比較少的 (“Soviet”, “Sasquatch”) 單詞對(duì)。那么當(dāng)訓(xùn)練結(jié)束后敞嗡,我們輸入“Soviet”颁糟,輸出結(jié)果中“Union”的概率要比“Sasquatch”高。
Model Detail
所以這一切到底是如何表示的呢喉悴?
首先棱貌,我們知道我們給神經(jīng)網(wǎng)絡(luò)輸入的是一些文本信息,比如一個(gè)word箕肃。那么我們必須有一個(gè)表示這些word的方式婚脱。所以首先我們得從我們的訓(xùn)練文本里構(gòu)建一個(gè)詞典,我們假設(shè)詞典大小是10000個(gè)不一樣的單詞勺像。
我們打算把input word比如“ants”表示成一個(gè)one-hot vector(比如說(shuō)00001障贸,只有一個(gè)1其他都是0)。我們的每個(gè)vector將有10000個(gè)components咏删, “ants” 這個(gè)單詞對(duì)應(yīng)的位置設(shè)為1惹想,其他的都為0。
這個(gè)網(wǎng)絡(luò)的輸出是一個(gè)vector(也是10000個(gè)components)督函,對(duì)于我們?cè)~典種的每個(gè)單詞嘀粱,都有一個(gè)對(duì)應(yīng)的概率。
下入是我們的網(wǎng)絡(luò)的結(jié)構(gòu)辰狡。
隱藏層沒(méi)有用到激活函數(shù)锋叨,但是輸出層用到了softmax函數(shù),這個(gè)事情我們呆會(huì)再談宛篇。
當(dāng)我們訓(xùn)練這個(gè)網(wǎng)絡(luò)的時(shí)候娃磺,input是一個(gè)one-hot vector表似乎一個(gè)input word,輸出也是一個(gè)one-hot vector表示一個(gè)word叫倍。但是當(dāng)我們進(jìn)行評(píng)估的時(shí)候偷卧,輸出實(shí)際上是一個(gè)概率的分布,一個(gè)bunch的float數(shù)值吆倦,而不是一個(gè)one-hot vector听诸。
The Hidden Layer
在我們的例子種,我們打算學(xué)習(xí)word的300個(gè)特征蚕泽。所以隱藏層是用一個(gè)有10000*300(300個(gè)神經(jīng)元)的矩陣構(gòu)成的晌梨。
Google在他們公布的訓(xùn)練谷歌新聞數(shù)據(jù)的模型里使用了300個(gè)特征。特征的數(shù)目是一個(gè)超參,你得嘗試不同的值來(lái)獲得好的結(jié)果仔蝌。
看看權(quán)重矩陣的行泛领,你會(huì)發(fā)現(xiàn),臥槽敛惊,這個(gè)實(shí)際上就是我們想要的word vectors渊鞋。
所以我們真正的最后的目標(biāo)是獲得這個(gè)隱藏層的權(quán)重矩陣,等訓(xùn)練完成了豆混,我們就把輸出層給扔了篓像!
現(xiàn)在,是時(shí)候回頭看看了皿伺,解決一下遺留的一些問(wèn)題,模型種的一些概念盒粮。
現(xiàn)在鸵鸥,你可能問(wèn)你自己,one-hot vector幾乎所有都為0…那么丹皱,這有什么用呢妒穴?當(dāng)你將1個(gè)1 * 10000的one-hot vector乘上一個(gè)10000 * 300的矩陣時(shí)候。它會(huì)很有效率的選擇1對(duì)應(yīng)的那一行摊崭。如下如所示:
這意味著這個(gè)模型的隱藏層實(shí)際上就像是一個(gè)lookup table讼油。隱藏層的輸出實(shí)際上就是input word的word vector。
The Output Layer
然后代表“ants”的1 * 300的word vector作為輸出層的輸入呢簸。輸出層是一個(gè)softmax回歸分類器矮台。這里有關(guān)于softmax回歸更深入的講解。但是這里的要點(diǎn)是每一個(gè)輸出層的神經(jīng)元會(huì)產(chǎn)生一個(gè)范圍為0到1的數(shù)(每一個(gè)都對(duì)應(yīng)我們字典中的一個(gè)word)根时,并且這些所有的值加起來(lái)和為1瘦赫。
特別的是,每一個(gè)輸出層神經(jīng)元有一個(gè)權(quán)重向量蛤迎,將它乘上word vector确虱,然后代入函數(shù)exp(x)
中。最后替裆,我們?cè)俪运?0000個(gè)輸出節(jié)點(diǎn)的結(jié)果的和校辩,使得所有輸出的和為1。
下圖是計(jì)算單詞“car”的輸出的一個(gè)示意圖辆童。
需要注意的是這個(gè)神經(jīng)網(wǎng)絡(luò)并不知道輸出的word相對(duì)于輸入word的偏移宜咒。它并沒(méi)有學(xué)習(xí)到這個(gè)輸出word是在輸入word的前面或者是后面。假設(shè)說(shuō)我們的訓(xùn)練語(yǔ)料中胸遇,每一個(gè)“York”前面都有一個(gè)單詞“New”荧呐,這個(gè)概率是100%。但是,當(dāng)我們的窗口大小是10倍阐,我們隨機(jī)選擇附近單詞概疆,“New”的概率并不是100%,你可能選擇別的單詞峰搪。
Intuition
好的岔冀,你準(zhǔn)備好更深入的了解這個(gè)網(wǎng)絡(luò)的令人興奮的部分了嗎?
假如兩個(gè)不同的word有著非常類似的上下文概耻,那么我們的模型就會(huì)輸出非常相似的兩個(gè)word vector使套。這個(gè)網(wǎng)絡(luò)輸出相同的上下文預(yù)測(cè)的一種情況就是這兩個(gè)word vector非常相似。所以鞠柄,假如兩個(gè)words有著相似的上下文侦高,那么我們的網(wǎng)絡(luò)就會(huì)傾向于學(xué)習(xí)出兩個(gè)相似的word vector。Ta da!(不知道啥意思haha)
這意味著什么呢厌杜?我認(rèn)為你會(huì)期望說(shuō)像“intelligent”和“smart”這種同義詞會(huì)有著相似的上下文奉呛。或者說(shuō)像“engine”和“transmission”這種相關(guān)的單詞夯尽,可能也會(huì)有相同的上下文瞧壮。
以及,對(duì)于“ant”和“ants”這種有著相似上下文的單詞匙握,這個(gè)網(wǎng)絡(luò)也會(huì)輸出相似的word vector咆槽。
Next Up
你可能會(huì)注意到skip-gram神經(jīng)網(wǎng)絡(luò)有著一個(gè)巨大的權(quán)重。就我們的例子來(lái)看圈纺,300個(gè)特征秦忿,10000個(gè)words,輸入層到隱藏層以及隱藏層到輸出層的權(quán)重都達(dá)到了3M赠堵。訓(xùn)練這個(gè)大dataset代價(jià)比較高的小渊,所以word2vec的作者介紹了一些微調(diào)策略來(lái)使得這個(gè)訓(xùn)練是可行的。接下來(lái)我們就講一講這些茫叭。
Part 2
在這個(gè)部分酬屉,我們主要談一談一些基于basic skip-gram model的改進(jìn),這些改進(jìn)使得模型的訓(xùn)練變得可行揍愁。
上文中我們提到呐萨,這個(gè)網(wǎng)絡(luò)是一個(gè)很大的網(wǎng)絡(luò)。在這么一個(gè)巨大的網(wǎng)絡(luò)里莽囤,跑梯度下降是非常慢的谬擦。更糟糕的是,要訓(xùn)練好這么多的權(quán)重并且避免過(guò)擬合朽缎,你需要非常多的數(shù)據(jù)惨远。百萬(wàn)級(jí)別的權(quán)重谜悟,十億級(jí)別的訓(xùn)練樣本,意味著訓(xùn)練這么一個(gè)模型北秽,完全是在扯淡葡幸。
word2vec的作者在他的論文里提出了三個(gè)創(chuàng)新點(diǎn):
- 在模型中把正常的單詞對(duì)或者短語(yǔ)當(dāng)做一個(gè)“words”;
- 對(duì)那些頻繁出現(xiàn)的單詞進(jìn)行子采樣(subsample)贺氓,來(lái)減少所需要的訓(xùn)練樣本蔚叨;
- 用一個(gè)“ Negative Sampling”的技術(shù)來(lái)改變優(yōu)化目標(biāo),這使得每個(gè)訓(xùn)練樣本只更新模型中一部分的權(quán)重辙培。
值得注意的是subsampling frequent words和Negative Sampling不僅僅減少了運(yùn)算負(fù)擔(dān)蔑水,并且還提升了結(jié)果的質(zhì)量。
Word Pairs and “Phrases”(單詞對(duì)和詞組)
作者指出扬蕊,像“Boston Globe”(一份報(bào)紙的名稱)這種合起來(lái)和分開(kāi)的意思大相徑庭的詞組搀别,最好把它當(dāng)作一個(gè)單詞,不管是在上下文中還是在word vector中厨相。
你可以看看他們公布的在100billion谷歌新聞數(shù)據(jù)上訓(xùn)練的模型的結(jié)果领曼。加入詞組(phrases)使得詞匯量高達(dá)3M。假如你對(duì)這些詞匯感興趣你可以看看這里蛮穿。
我認(rèn)為他們的這種把詞匯當(dāng)作一個(gè)word的方法不是他們論文的主要貢獻(xiàn),我在這里提一下因?yàn)閷?shí)際上方法很直接毁渗。
在每一輪中践磅,他們的工具只看相鄰的兩個(gè)words,但是你可以跑多次灸异,以此來(lái)獲得更多單詞的詞組府适。比如說(shuō),第一輪的時(shí)候肺樟,會(huì)選取New_York檐春,然后再跑一遍,會(huì)選取New_York_City么伯。
這個(gè)工具計(jì)算每?jī)蓚€(gè)連接的words出現(xiàn)的次數(shù)疟暖,然后根據(jù)次數(shù)帶入方程式中來(lái)判斷應(yīng)該把哪些歸類為詞組。這個(gè)方程式是為了避免把那些獨(dú)立的但是經(jīng)常一起出現(xiàn)的word也歸類為詞組田柔。它也比較傾向于把那些低頻word的組合歸類為詞組俐巴,避免諸如“and the”或者“this is”之類的詞組。如果你想更詳細(xì)的了解細(xì)節(jié)硬爆,你可以看這里欣舵。
我曾經(jīng)想過(guò)的一個(gè)替代策略是采用wikipedia articles的標(biāo)題來(lái)作為詞匯。
Subsampling Frequent Words
再Part 1中缀磕,我展示了訓(xùn)練樣本是如何從源文件中產(chǎn)生的缘圈,我會(huì)在這里重復(fù)一下劣光。下面的例子展示了從“The quick brown fox jumps over the lazy dog.”里獲得的一次訓(xùn)練樣本(單詞對(duì))。我在這個(gè)例子中使用的窗口大小為2糟把。高亮的藍(lán)色單詞是輸入單詞绢涡。
對(duì)于那些高頻單詞比如“the”,這里存在兩個(gè)問(wèn)題:
- 當(dāng)我們觀察單詞對(duì)的時(shí)候糊饱,(“fox”, “the”) 并沒(méi)有告訴我們太多關(guān)于“fox”的信息垂寥。“the”幾乎出現(xiàn)在每一個(gè)單詞的上下文中另锋。
- 我們有著太多的 (“the”, …) 這類的單詞對(duì)滞项,我們并不需要那么多來(lái)學(xué)習(xí)出the一個(gè)好的vector。
word2vec采用一種“subsampling”的策略來(lái)解決這個(gè)問(wèn)題夭坪。對(duì)于我們?cè)谟?xùn)練文本中遇到的每一個(gè)單詞文判,我們有一定的幾率會(huì)把它刪掉。這個(gè)概率是和這個(gè)單詞出現(xiàn)的頻率相關(guān)的室梅。
假如我們?cè)O(shè)定的窗口大小為10戏仓,并且我們從文本中移除掉“the”的一個(gè)實(shí)例:
- 當(dāng)我們利用剩下的單詞進(jìn)行訓(xùn)練的時(shí)候,“the”不會(huì)出現(xiàn)在它們的上下文窗口中亡鼠;
- 當(dāng)the是輸入單詞的時(shí)候赏殃,我們會(huì)有著小于10的訓(xùn)練樣本。
思考一下這兩個(gè)結(jié)果對(duì)我們解決上面提出的問(wèn)題有什么幫助间涵。
Sampling rate
word2vec的C代碼中利用一個(gè)方程式來(lái)計(jì)算是否丟棄詞表中的word的概率仁热。
wi是一個(gè)單詞,z(wi)表示這個(gè)單詞出現(xiàn)的次數(shù)相對(duì)于總次數(shù)的比例勾哩。比如抗蠢,“peanut”在包含1billion的語(yǔ)料中出現(xiàn)了1000次,那么z(“peanut”)就是1000/10 0000 0000 = 1/100 0000思劳。
還有一個(gè)參數(shù)叫做“sample”用來(lái)控制subsampling出現(xiàn)的頻率迅矛,默認(rèn)值是0.001。words的“sample”越小表示越容易被丟棄潜叛。
P(wi)表示keeping這個(gè)單詞的概率:
你可以把它畫(huà)出來(lái)來(lái)看看形狀:
沒(méi)有一個(gè)word占整個(gè)語(yǔ)料的比例會(huì)很高秽褒,所以我們來(lái)看看當(dāng)x比較小的時(shí)候是什么樣子的。
這是在這個(gè)函數(shù)中一些關(guān)鍵的點(diǎn)(重申下sample采用的是默認(rèn)的0.001):
你可能會(huì)注意到paper中定義的函數(shù)和C代碼中采用的有些不太一樣钠导,但是我覺(jué)得C代碼中的是更加權(quán)威的版本震嫉。
Negativa Sampling
訓(xùn)練一個(gè)神經(jīng)網(wǎng)絡(luò)指的是拿一個(gè)訓(xùn)練樣本進(jìn)行訓(xùn)練,然后細(xì)微的調(diào)整神經(jīng)元中的權(quán)重牡属,使得對(duì)訓(xùn)練樣本的于此更加精確票堵。換句話說(shuō),每一個(gè)訓(xùn)練樣本對(duì)神經(jīng)網(wǎng)絡(luò)中的所有權(quán)重都有影響逮栅。
就我們前面提到的悴势,巨大的詞匯表意味著神經(jīng)網(wǎng)絡(luò)中巨大的權(quán)重窗宇,這些權(quán)重每次都會(huì)因我們的訓(xùn)練樣本做出輕微改動(dòng),而我們的樣本數(shù)量是十億級(jí)別的特纤。
Negativa Sampling通過(guò)每個(gè)訓(xùn)練樣本只改變某些權(quán)重的方法來(lái)解決這個(gè)問(wèn)題军俊。接下來(lái)我們看看它是怎么工作的。
當(dāng)我們用單詞對(duì) (“fox”, “quick”) 來(lái)訓(xùn)練網(wǎng)絡(luò)的時(shí)候捧存,輸入和輸出都是one-hot vector粪躬。也就是說(shuō),神經(jīng)元的輸出昔穴,對(duì)應(yīng)“quick”的是1镰官,其他的都是0。
采用negative sampling吗货,我們只是隨機(jī)選取少量的“negative” word(比如說(shuō)5個(gè))來(lái)更新它們的權(quán)重泳唠。(“negative” word在這里指的是那些輸出對(duì)應(yīng)為0的單詞)。對(duì)于“positive” word也就是“quick”宙搬,我們?nèi)匀贿M(jìn)行更新笨腥。
paper中說(shuō)選擇5-20個(gè)words在校的數(shù)據(jù)集中工作的很好。在大的數(shù)據(jù)集中勇垛,你可以選擇更少脖母,比如2-5個(gè)。
回憶一下闲孤,輸出層的權(quán)重矩陣是300 * 10000的镶奉。假如我們只更新我們的“positive” word (“quick”),加上5個(gè)隨機(jī)選擇的negative單詞崭放。一共也才6個(gè)神經(jīng)元,1800個(gè)權(quán)重值鸽凶。只占了3M 權(quán)重的0.06%币砂。
在隱藏層中,只有input word對(duì)應(yīng)的權(quán)重進(jìn)行更新玻侥,這個(gè)不管采不采用Negative Sampling都一樣决摧。
Selecting Negative Samples
剛才說(shuō)的5個(gè)“negative samples”怎么確定呢,實(shí)際上不是完全隨機(jī)的凑兰,采用“unigram distribution”的方法來(lái)確定掌桩。
實(shí)際上,選擇一個(gè)word作為negative word的概率是和它出現(xiàn)的頻率相關(guān)的姑食,也就是說(shuō)它出現(xiàn)的頻率越高波岛,那么它就越可能被選中。
在word2vec的C代碼的實(shí)現(xiàn)中音半,你可以看到以下這個(gè)方程式则拷。f(wi)表示wi出現(xiàn)次數(shù)的權(quán)重贡蓖。所以選擇一個(gè)word的概率就是它的權(quán)重除以所有words權(quán)重和。
選擇3/4作為指數(shù)項(xiàng)應(yīng)該是憑經(jīng)驗(yàn)選擇的煌茬,在他們的paper中斥铺,他們說(shuō)這個(gè)選擇比別的效果更好。你可以在google中畫(huà)圖:“plot y = x^(3/4) and y = x” 并且把x的范圍設(shè)定為[0, 1]坛善,就可以看它的形狀了晾蜘。
這個(gè)選擇的方式在C代碼中的實(shí)現(xiàn)挺有趣的。他們有著個(gè)非常大的array眠屎,多大100M個(gè)元素(也就是unigram table)剔交。他們根據(jù)word的index多次填充這個(gè)table,然后一個(gè)word的index在這個(gè)table中出現(xiàn)的次數(shù)等于P(wi) * table_size组力。所以實(shí)際上你選擇一個(gè)negative sample的過(guò)程就是產(chǎn)生一個(gè)從0-100M的隨機(jī)數(shù)省容,然后使用table中對(duì)應(yīng)位置的word。因?yàn)楦哳l單詞在這個(gè)table中出現(xiàn)了多次燎字,所以你有更大的概率選擇它腥椒。
Other Resources
word2vec最詳細(xì)的最準(zhǔn)確的解釋就是它的源代碼了,這篇介紹的作者寫(xiě)了帶更多注釋的版本候衍,在這里笼蛛,或者直接去看源代碼。