版權聲明:本文爲博主原創文章,未經博主容許不得轉載。算法
做者:寒小陽 && 龍心塵
時間:2016年6月
出處:
http://blog.csdn.net/han_xiaoyang/article/details/51567822
http://blog.csdn.net/longxinchen_ml/article/details/51567960
聲明:版權全部,轉載請聯繫做者並註明出處markdown
說明:本文爲斯坦福大學CS224d課程的中文版內容筆記,已獲得斯坦福大學課程@Richard Socher教授的受權翻譯與發表ide
特別鳴謝:@Fantzy同窗對部份內容翻譯的幫助
課堂筆記:第一部分函數
春季2016學習
關鍵詞:天然語言處理(NLP).詞向量(Word Vectors).奇異值分解(Singular Value Decomposition). Skip-gram. 詞組的持續爆(CBOW),負採樣樣本(Negative Sampling)大數據
這是本課程的第一節,咱們會先介紹天然語言處理(NLP)的概念和NLP如今所面對問題;而後開始討論用數學向量表明天然語言詞組的設想。最後咱們會討論現行的詞向量構造方法。優化
在最開始我們先說說什麼是NLP。NLP的目的是設計出算法,讓計算機「懂得」人類的天然語言,從而爲人類執行任務。這些任務分爲幾個難度等級,例如網站
容易的任務:ui
中等難度的任務:
比較有挑戰的任務:
在處理全部NLP任務的時候,咱們首先須要解決很是重要的一個問題(多是最重要的):用什麼方式將詞組輸入到模型中去。簡單的NLP問題可能並不須要將詞組做爲獨立個體對待(atomic symbols),但如今的問題絕大多數須要這樣一個預處理,來體現詞組之間關聯/類似性和區別。因此咱們引入詞向量的概念,若是把詞編碼成詞向量,咱們很容易從向量的角度去衡量不一樣的詞之間的關聯與差別(經常使用的距離測度法,包括Jaccard, Cosine, Euclidean等等,注:距離測度法,即用一個可觀測度量的量來描述一個不能直接觀測度量的量)。
咱們拿英文舉例。
英語中大約有1300萬個詞組(token,自定義字符串,譯做詞組),不過他們所有是獨立的嗎?並非哦,好比有一些詞組,「Feline貓科動物」和「Cat貓」,「Hotel賓館「和」Motel汽車旅館」,其實有必定的關聯或者類似性在。所以,咱們但願用詞向量編碼詞組,使它表明在詞組的N維空間中的一個點(而點與點之間有距離的遠近等關係,能夠體現深層一點的信息)。每個詞向量的維度均可能會表徵一些意義(物理含義),這些意義咱們用「聲明speech」來定義。例如,語義維度能夠用來代表時態(過去與如今與將來),計數(單數與複數),和性別(男性與女性)。
提及來,詞向量的編碼方式其實挺有講究的。我們從最簡單的看起,最簡單的編碼方式叫作one-hot vector:假設咱們的詞庫總共有n個詞,那咱們開一個1*n的高維向量,而每一個詞都會在某個索引index下取到1,其他位置所有都取值爲0.詞向量在這種類型的編碼中以下圖所示:
究其根本你會發現,是你開了一個極高維度的空間,而後每一個詞語都會佔據一個維度,所以沒有辦法在空間中關聯起來。所以咱們可能能夠把詞向量的維度下降一些,在這樣一個子空間中,可能本來沒有關聯的詞就關聯起來了。
這是一種構造詞嵌入(即詞向量)的方法,咱們首先會遍歷全部的文本數據集,而後統計詞出現的次數,接着用一個矩陣X來表示全部的次數狀況,緊接着對X進行奇異值分解獲得一個USVT的分解。而後用U的行(rows)做爲全部詞表中詞的詞向量。對於矩陣X,咱們有幾種選擇,我們一塊兒來比較一下。
最初的想法是,咱們猜想相互關聯的詞組同時出如今相同的文件中的機率很高。例如,「銀行」、「債券」、「股票」、「錢」等均可能出如今一塊兒。可是,「銀行」、「章魚」、「香蕉」和「曲棍球」可能不會一直一塊兒出現。基於這個想法,咱們創建一個詞組文檔矩陣X,具體是這麼作的:遍歷海量的文件,每次詞組i出如今文件j中時,將Xij的值加1。不過你們可想而知,這會是個很大的矩陣R|V|×M,並且矩陣大小還和文檔個數M有關係。因此我們最好想辦法處理和優化一下。
咱們仍是用同樣的邏輯,不過換一種統計方式,把矩陣X記錄的詞頻變成一個相關性矩陣。咱們先規定一個固定大小的窗口,而後統計每一個詞出如今窗口中次數,這個計數是針對整個語料集作的。可能說得有點含糊,我們一塊兒來看個例子,假定咱們有以下的3個句子,同時咱們的窗口大小設定爲1(把原始的句子分拆成一個一個的詞):
1. I enjoy flying.
2. I like NLP.
3. I like deep learning.
由此產生的計數矩陣以下:
而後咱們對X作奇異值分解,觀察觀察奇異值(矩陣的對角元素),並根據咱們期待保留的百分比來進行階段(只保留前k個維度):
而後咱們把子矩陣U1:|V|,1:k視做咱們的詞嵌入矩陣。也就是說,對於詞表中的每個詞,咱們都用一個k維的向量來表達了。
對X採用奇異值分解
經過選擇前K個奇異向量來進行降維:
這兩種方法都能產生詞向量,它們可以充分地編碼語義和句法的信息,但同時也帶來了其餘的問題:
固然,有一些辦法能夠緩解一下上述提到的問題:
不過緩解終歸只是緩解,我們須要更合理地解決這些問題,這也就是咱們立刻要提到的基於迭代的方法。
如今咱們退後一步,來嘗試一種新的方法。在這裏咱們並不計算和存儲全局信息,由於這會包含太多大型數據集和數十億句子。咱們嘗試建立一個模型,它可以一步步迭代地進行學習,並最終得出每一個單詞基於其上下文的條件機率。
詞語的上下文:
一個詞語的上下文是它周圍C個詞之內的詞。若是C=2,句子"The quick brown fox jumped over the lazy dog"中單詞"fox"的上下文爲 {"quick", "brown", "jumped", "over"}.
咱們想創建一個機率模型,它包含已知和未知參數。每增長一個訓練樣本,它就能從模型的輸入、輸出和指望輸出(標籤),多學到一點點未知參數的信息。
在每次迭代過程當中,這個模型都可以評估其偏差,並按照必定的更新規則,懲罰那些致使偏差的參數。這種想法能夠追溯到1986年(Learning representations by back-propagating errors. David E. Rumelhart, Geoffrey E. Hinton, and Ronald J.Williams (1988)),咱們稱之爲偏差「反向傳播」法。
首先,咱們須要創建一個能給「分詞序列」分配機率的模型。咱們從一個例子開始:
"The cat jumped over the puddle."(貓 跳 過 水坑)
一個好的語言模型會給這句話以很高的機率,由於這是一個在語法和語義上徹底有效的句子。一樣地,這句」stock boil fish is toy」(股票 煮 魚 是 玩具)就應該有一個很是低的機率 ,由於它是沒有任何意義的。在數學上,咱們能夠令任意給定的n個有序的分詞序列的機率爲:
有種模型是以{「The」, 「cat」, ’over」, 「the’, 「puddle」}爲上下文,可以預測或產生它們中心的詞語」jumped」,叫作連續詞袋模型。
上面是最粗粒度的描述,我們來深刻一點點,看點細節。
首先,咱們要創建模型的一些已知參數。它們就是將句子表示爲一些one-hot向量,做爲模型的輸入,我們記爲x(c)吧。模型的輸出記爲y(c)吧。由於連續詞袋模型只有一個輸出,因此其實咱們只需記錄它爲y。在咱們上面舉的例子中,y就是咱們已經知道的(有標籤的)中心詞(如本例中的」jumped」)。
好了,已知參數有了,如今咱們一塊兒來定義模型中的未知參數。咱們創建兩矩陣,V∈Rn∗|V|和U∈R|V|∗n。其中的n是能夠任意指定的,它用來定義咱們「嵌入空間」(embedding space)的維度。V是輸入詞矩陣。當詞語wi(譯註:wi是隻有第i維是1其餘維是0的one-hot向量)做爲模型的一個輸入的時候,V的第i列就是它的n維「嵌入向量」(embedded vector)。咱們將V的這一列表示爲vi。相似的,U是輸出矩陣。當wj做爲模型輸出的時候,U的第j行就是它的n維「嵌入向量」。咱們將U的這一行表示爲uj。要注意咱們實際上對於每一個詞語wi學習了兩個向量。(做爲輸入詞的向量vi,和做爲輸出詞的向量uj)。
連續詞袋模型(CBOM)中的各個記號:
那這個模型是如何運做的呢?咱們把整個過程拆分紅如下幾步:
用一幅圖來表示就是下面這個樣子:
經過上面說的種種步驟,咱們知道有了矩陣U、V整個過程是如何運做的,那咱們怎樣找到U和V呢?——咱們須要有一個目標函數。一般來講,當咱們試圖從已知機率學習一個新的機率時,最多見的是從信息論的角度尋找方法來評估兩個機率分佈的差距。其中廣受好評又普遍應用的一個評估差別/損失的函數是交叉熵:
結合咱們當下的例子,y只是一個one-hot向量,因而上面的損失函數就能夠簡化爲:
咱們用c表示y這個one-hot向量取值爲1的那個維度的下標。因此在咱們預測爲準確值的狀況下y^c=1。因而損失爲 −1 log(1) = 0。因此對於一個理想的預測值,由於預測獲得的機率分佈和真實機率分佈徹底同樣,所以損失爲0。如今讓咱們看一個相反的狀況,也就是咱們的預測結果很是不理想,此時y^c=0.01。計算獲得的損失爲−1 log(0.01) ≈ 4.605,損失很是大,本來這纔是標準結果,但是你給了一個很是低的機率,所以會拿到一個很是大的loss 。可見交叉熵爲咱們提供了一個很好的衡量兩個機率分佈的差別的方法。因而咱們最終的優化函數爲:
很上面提到的模型對應的另外一種思路,是以中心的詞語」jumped」爲輸入,可以預測或產生它周圍的詞語」The」, 「cat」, ’over」, 「the」, 「puddle」等。這裏咱們叫」jumped」爲上下文。咱們把它叫作Skip-Gram 模型。
這個模型的創建與連續詞袋模型(CBOM)很是類似,但本質上是交換了輸入和輸出的位置。咱們令輸入的one-hot向量(中心詞)爲x(由於它只有一個),輸出向量爲y(j)。U和V的定義與連續詞袋模型同樣。
Skip-Gram 模型中的各個記號:
對應到上面部分,咱們能夠把Skip-Gram 模型的運做方式拆分紅如下幾步:
用一幅圖來表示這個過程以下:
咱們再次觀察一下目標函數,注意到對整個單詞表|V|求和的計算量是很是巨大的,任何一個對目標函數的更新和求值操做都會有O(|V|)的時間複雜度。咱們須要一個思路去簡化一下,咱們想辦法去求它的近似。
對於每一步訓練,咱們不去循環整個單詞表,而只是抽象一些負面例子就夠了!咱們能夠從一個噪聲分佈(Pn(w))中抽樣,其機率分佈與單詞表中的頻率相匹配。爲了將描述問題的公式與負面抽樣相結合,咱們只須要更新咱們的:
Mikolov ET AL.在他的《Distributed Representations of Words and Phrases and their Compositionality》中提出了負面抽樣。雖然負面抽樣是基於Skip-Gram 模型,它其實是對一個不一樣的目標函數進行最優化。考慮一個「詞-上下文」對(w,c),令P(D = 1|w, c)爲(w, c)來自於語料庫的機率。相應的,P(D = 0|w, c) 則是不來自於語料庫的機率。咱們首先對P(D = 1|w, c)用sigmoid函數建模:
注意這裏的D˜表示「錯誤的」或者「負面的」語料庫,像句子」stock boil fish is toy」就是從這樣的語料庫來的。不天然的句子應該有比較低的發生機率,咱們能夠從詞庫中隨機採樣來產生這樣的「負面的」語料庫。咱們的新目標函數就變成了:
在這裏{u˜k|k=1,⋯,K}是從(Pn(w))中抽樣取到的。須要多說一句的是,雖然關於怎麼樣最好地近似有許多討論和研究,可是工做效果最好的彷佛是指數爲3/4的一元語言模型。至於爲何是3/4,下面有幾個例子來幫助你們感性地理解一下:
你看,通過3/4這樣一個指數處理,」Bombastic」(少見)被採樣的機率是以前的3倍,而「is」這個詞(多見)被採樣的機率只是稍微增加了一點點。