深度学习与自然语言处理(1)_斯坦福cs224d Lecture 1
作者:寒小陽 && 龍心塵
時間:2016年6月
出處:http://blog.csdn.net/han_xiaoyang/article/details/51567822
http://blog.csdn.net/longxinchen_ml/article/details/51567960
聲明:版權所有,轉載請聯系作者并注明出處
說明:本文為斯坦福大學CS224d課程的中文版內容筆記,已得到斯坦福大學課程@Richard Socher教授的授權翻譯與發表
特別鳴謝:@Fantzy同學對部分內容翻譯的幫助
課堂筆記:第一部分
春季2016
關鍵詞:自然語言處理(NLP).詞向量(Word Vectors).奇異值分解(Singular Value Decomposition). Skip-gram. 連續詞袋(CBOW),負采樣樣本(Negative Sampling)
這是本課程的第一節,我們會先介紹自然語言處理(NLP)的概念和NLP現在所面對問題;然后開始討論用數學向量代表自然語言詞組的設想。最后我們會討論現行的詞向量構造方法。
1. 自然語言處理簡介
在最開始咱們先說說什么是NLP。NLP的目的是設計出算法,讓計算機“懂得”人類的自然語言,從而為人類執行任務。這些任務分為幾個難度等級,例如
容易的任務:
- 語法檢查
- 關鍵詞搜索
- 查找同義詞
中等難度的任務:
- 從網站,文件或其他來源中提取信息
比較有挑戰的任務:
- 機器翻譯(例如:中譯英)
- 語意分析(提問者說的意思是什么)
- 指代分析(例如. “他”或“它”在一個特定文件中指的是什么)
- 回答問題(例如.回答“Jeopardy Questions”一種涉及人類社會各個方面的綜藝問答)
在處理所有NLP任務的時候,我們首先需要解決非常重要的一個問題(可能是最重要的):用什么方式將詞組輸入到模型中去。簡單的NLP問題可能并不需要將詞組作為獨立個體對待(atomic symbols),但現在的問題絕大多數需要這樣一個預處理,來體現詞組之間關聯/相似性和區別。所以我們引入詞向量的概念,如果把詞編碼成詞向量,我們很容易從向量的角度去衡量不同的詞之間的關聯與差異(常用的距離測度法,包括Jaccard, Cosine, Euclidean等等,注:距離測度法,即用一個可觀測度量的量來描述一個不能直接觀測度量的量)。
2.詞向量
我們拿英文舉例。
英語中大約有1300萬個詞組(token,自定義字符串,譯作詞組),不過他們全部是獨立的嗎?并不是哦,比如有一些詞組,“Feline貓科動物”和“Cat貓”,“Hotel賓館“和”Motel汽車旅館”,其實有一定的關聯或者相似性在。因此,我們希望用詞向量編碼詞組,使它代表在詞組的N維空間中的一個點(而點與點之間有距離的遠近等關系,可以體現深層一點的信息)。每一個詞向量的維度都可能會表征一些意義(物理含義),這些意義我們用“聲明speech”來定義。例如,語義維度可以用來表明時態(過去與現在與未來),計數(單數與復數),和性別(男性與女性)。
說起來,詞向量的編碼方式其實挺有講究的。咱們從最簡單的看起,最簡單的編碼方式叫做one-hot vector:假設我們的詞庫總共有n個詞,那我們開一個1*n的高維向量,而每個詞都會在某個索引index下取到1,其余位置全部都取值為0.詞向量在這種類型的編碼中如下圖所示:
這種詞向量編碼方式簡單粗暴,我們將每一個詞作為一個完全獨立的個體來表達。遺憾的是,這種方式下,我們的詞向量沒辦法給我們任何形式的詞組相似性權衡。例如:
(whotel)Twmotel=(whotel)Twcat=0
(注:這里 W?1是 W的逆矩陣,它們有關系:W?1?W=1,注意到hotel和motel是近義詞)
究其根本你會發現,是你開了一個極高維度的空間,然后每個詞語都會占據一個維度,因此沒有辦法在空間中關聯起來。因此我們可能可以把詞向量的維度降低一些,在這樣一個子空間中,可能原本沒有關聯的詞就關聯起來了。
3.基于SVD的方法
這是一種構造詞嵌入(即詞向量)的方法,我們首先會遍歷所有的文本數據集,然后統計詞出現的次數,接著用一個矩陣X來表示所有的次數情況,緊接著對X進行奇異值分解得到一個USVT的分解。然后用U的行(rows)作為所有詞表中詞的詞向量。對于矩陣X,我們有幾種選擇,咱們一起來比較一下。
3.1 詞-文檔矩陣
最初的想法是,我們猜測相互關聯的詞組同時出現在相同的文件中的概率很高。例如,“銀行”、“債券”、“股票”、“錢”等都可能出現在一起。但是,“銀行”、“章魚”、“香蕉”和“曲棍球”可能不會一直一起出現。基于這個想法,我們建立一個詞組文檔矩陣X,具體是這么做的:遍歷海量的文件,每次詞組i出現在文件j中時,將Xij的值加1。不過大家可想而知,這會是個很大的矩陣R|V|×M,而且矩陣大小還和文檔個數M有關系。所以咱們最好想辦法處理和優化一下。
3.2 基于窗口的共現矩陣X
我們還是用一樣的邏輯,不過換一種統計方式,把矩陣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個奇異向量來進行降維:
這兩種方法都能產生詞向量,它們能夠充分地編碼語義和句法的信息,但同時也帶來了其他的問題:
- 矩陣的維度會經常變化(新的詞語經常會增加,語料庫的大小也會隨時變化)。
- 矩陣是非常稀疏的,因為大多數詞并不同時出現。
- 矩陣的維度通常非常高(≈106×106)
- 訓練需要O(n2)的復雜度(比如SVD)
- 需要專門對矩陣X進行特殊處理,以應對詞組頻率的極度不平衡的狀況
當然,有一些辦法可以緩解一下上述提到的問題:
- 忽視諸如“he”、“the” 、“has”等功能詞。
- 應用“傾斜窗口”(ramp window),即:根據文件中詞組之間的距離給它們的共現次數增加相應的權重。
- 使用皮爾森的相關性(Pearson correlation),將0記為負數,而不是它原來的數值。
不過緩解終歸只是緩解,咱們需要更合理地解決這些問題,這也就是我們馬上要提到的基于迭代的方法。
4.基于迭代的方法
現在我們退后一步,來嘗試一種新的方法。在這里我們并不計算和存儲全局信息,因為這會包含太多大型數據集和數十億句子。我們嘗試創建一個模型,它能夠一步步迭代地進行學習,并最終得出每個單詞基于其上下文的條件概率。
詞語的上下文: 一個詞語的上下文是它周圍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)),我們稱之為誤差“反向傳播”法。
4.1 語言模型(1-gram,2-gram等等)
首先,我們需要建立一個能給“分詞序列”分配概率的模型。我們從一個例子開始:
"The cat jumped over the puddle."(貓 跳 過 水坑)
一個好的語言模型會給這句話以很高的概率,因為這是一個在語法和語義上完全有效的句子。同樣地,這句”stock boil fish is toy”(股票 煮 魚 是 玩具)就應該有一個非常低的概率 ,因為它是沒有任何意義的。在數學上,我們可以令任意給定的n個有序的分詞序列的概率為:
我們可以采用一元語言模型。它假定詞語的出現是完全獨立的,于是可以將整個概率拆開相乘:
P(w1,w2,w3...wn)=∏i=1NP(wi)
看到這里,肯定很多同學就要噴了,這不對,詞和詞之間沒有關聯嗎?確實,我們知道一句話中每一個詞語都跟它前面的詞語有很強的依賴關系,忽略這一點的話,一些完全無意義的句子,可能會有很高的概率。咱們稍微改一改,讓一個詞語的概率依賴于它前面一個詞語。我們將這種模型稱作bigram(2-gram,二元語言模型),表示為:
P(w1,w2,w3...wn)=∏i=2NP(wi|wi?1)
看起來還是有點簡單?恩,也對,我們只考慮一個詞語依賴于其相鄰的一個詞語的關系,而不是考慮其依賴整個句子的情況。別著急,接下來將會看到,這種方法能讓我們有非常顯著的進步。考慮到前面 “詞-詞”矩陣的情況,我們至少可以算出兩個詞語共同出現的概率。但是,舊話重提,這仍然要求儲存和計算一個非常的大數據集里面的全部信息。
現在我們理解了“分詞序列”的概率(其實就是N-gram語言模型啦),讓我們觀察一些能夠學習到這些概率的例子。
4.2 連續詞袋模型(CBOM)
有種模型是以{“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)中的各個記號:
- wi:單詞表V中的第i個單詞
- v∈Rn?|V|:輸入詞矩陣
- vi:V的第i列,單詞wi的輸入向量
- u∈R|V|?n:輸出詞矩陣
- ui:U的第i行,單詞wi的輸出向量
那這個模型是如何運作的呢?我們把整個過程拆分成以下幾步:
用一幅圖來表示就是下面這個樣子:
通過上面說的種種步驟,我們知道有了矩陣U、V整個過程是如何運作的,那我們怎樣找到U和V呢?——我們需要有一個目標函數。通常來說,當我們試圖從已知概率學習一個新的概率時,最常見的是從信息論的角度尋找方法來評估兩個概率分布的差距。其中廣受好評又廣泛應用的一個評估差異/損失的函數是交叉熵:
H(y? ,y)=?∑j=1|V|yjlog(y? j)
結合我們當下的例子,y只是一個one-hot向量,于是上面的損失函數就可以簡化為:
H(y??,y)=?yilog(y??i)
我們用c表示y這個one-hot向量取值為1的那個維度的下標。所以在我們預測為準確值的情況下y??c=1。于是損失為 ?1 log(1) = 0。所以對于一個理想的預測值,因為預測得到的概率分布和真實概率分布完全一樣,因此損失為0。現在讓我們看一個相反的情況,也就是我們的預測結果非常不理想,此時y??c=0.01。計算得到的損失為?1 log(0.01) ≈ 4.605,損失非常大,原本這才是標準結果,可是你給了一個非常低的概率,因此會拿到一個非常大的loss 。可見交叉熵為我們提供了一個很好的衡量兩個概率分布的差異的方法。于是我們最終的優化函數為:
我們用梯度下降法去更新每一個相關的詞向量uc和vj 。
4.3 Skip-Gram 模型
很上面提到的模型對應的另一種思路,是以中心的詞語”jumped”為輸入,能夠預測或產生它周圍的詞語”The”, “cat”, ’over”, “the”, “puddle”等。這里我們叫”jumped”為上下文。我們把它叫做Skip-Gram 模型。
這個模型的建立與連續詞袋模型(CBOM)非常相似,但本質上是交換了輸入和輸出的位置。我們令輸入的one-hot向量(中心詞)為x(因為它只有一個),輸出向量為y(j)。U和V的定義與連續詞袋模型一樣。
Skip-Gram 模型中的各個記號:
- wi:單詞表V中的第i個單詞
- v∈Rn?|V|:輸入詞矩陣
- vi:V的第i列,單詞wi的輸入向量
- u∈R|V|?n:輸出詞矩陣
- ui:U的第i行,單詞wi的輸出向量
對應到上面部分,我們可以把Skip-Gram 模型的運作方式拆分成以下幾步:
用一幅圖來表示這個過程如下:
像連續詞袋模型一樣,我們需要為模型設定一個目標/損失函數。不過不同的地方是我們這里需要引入樸素貝葉斯假設來將聯合概率拆分成獨立概率相乘。如果你之前不了解它,可以先跳過。這是一個非常強的條件獨立性假設。也就是說只要給出了中心詞,所有的輸出詞是完全獨立的。
我們可以用隨機梯度下降法去更新未知參數的梯度。
4.4 負面抽樣(Negative Sampling)
我們再次觀察一下目標函數,注意到對整個單詞表|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函數建模:
現在我們需要建立一個新的目標函數。如果(w, c)真是來自于語料庫,目標函數能夠最大化P(D = 1|w, c)。反之亦然。我們對這兩個概率采用一個簡單的最大似然法。(這里令θ為模型的參數,在我們的例子中,就是對應的U和V。)
注意這里的D?表示“錯誤的”或者“負面的”語料庫,像句子”stock boil fish is toy”就是從這樣的語料庫來的。不自然的句子應該有比較低的發生概率,我們可以從詞庫中隨機采樣來產生這樣的“負面的”語料庫。我們的新目標函數就變成了:
logσ(u(c?m+j)T.vc)+∑k=1Klogσ(?u?Tk.vc)
在這里{u?k|k=1,?,K}是從(Pn(w))中抽樣取到的。需要多說一句的是,雖然關于怎么樣最好地近似有許多討論和研究,但是工作效果最好的似乎是指數為3/4的一元語言模型。至于為什么是3/4,下面有幾個例子來幫助大家感性地理解一下:
is:0.93/4=0.92constitution:0.093/4=0.16bombastic:0.013/4=0.032
你看,經過3/4這樣一個指數處理,”Bombastic”(少見)被采樣的概率是之前的3倍,而“is”這個詞(多見)被采樣的概率只是稍微增長了一點點。
總結
以上是生活随笔為你收集整理的深度学习与自然语言处理(1)_斯坦福cs224d Lecture 1的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQLite 3.38.0 现已正式发布
- 下一篇: 项目交付的问题