第二講:簡單的詞向量表示:word2vec, Glove
How do we represent words?
在處理所有NLP任務的時候,我們首先需要解決非常重要的一個問題(可能是最重要的):用什麼方式将詞組輸入到模型中去。早期的NLP工作并不将詞組作為獨立個體對待(atomic symbols),但現在的問題絕大多數需要這樣一個預處理,來展現詞組之間關聯/相似性和差別。是以我們引入詞向量的概念,如果把詞編碼成詞向量(word vectors),我們很容易從向量的角度去衡量不同的詞之間的關聯與差異(常用的距離測度法,包括Jaccard, Cosine, Euclidean等等,注:距離測度法,即用一個可觀測度量的量來描述一個不能直接觀測度量的量)。
Word Vectors
我們拿英文舉例。
英語中大約有1300萬個詞組(token,自定義字元串,譯作詞組),不過他們全部是獨立的嗎?并不是哦,比如有一些詞組,“Feline貓科動物”和“Cat貓”,“Hotel飯店“和”Motel汽車旅館”,其實有一定的關聯或者相似性在。是以,我們希望用詞向量編碼詞組,使它代表在詞組的N維空間中的一個點(而點與點之間有距離的遠近等關系,可以展現深層一點的資訊)。每一個詞向量的次元都可能會表征一些意義(實體含義),這些意義我們用“聲明speech”來定義。例如,語義次元可以用來表明時态(過去與現在與未來),計數(單數與複數),和性别(男性與女性)。
(a) Discrete representation of word
說起來,詞向量的編碼方式其實挺有講究的, 最簡單的編碼方式叫做one-hot vector:假設我們的詞庫總共有n個詞,那我們開一個1*n的高維向量,而每個詞都會在某個索引index下取到1,其餘位置全部都取值為0.詞向量在這種類型的編碼中如下圖所示:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL9sGRPlXS650MBRVT3V1MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLwQDOwMjNxUTMzADOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
這種詞向量編碼方式簡單粗暴,我們将每一個詞作為一個完全獨立的個體來表達。遺憾的是,這種方式下,我們的詞向量沒辦法給我們任何形式的詞組相似性度量。例如:
(注:hotel和motel是近義詞)
究其根本你會發現,是你開了一個極高次元的空間,然後每個詞語都會占據一個次元,是以沒有辦法在空間中關聯起來。是以我們可能可以把詞向量的次元降低一些,在這樣一個子空間中,可能原本沒有關聯的詞就關聯起來了。
(b)Distributional similarity based representations
通過一個詞語的上下文可以學到這個詞語的很多知識,”You shall know a word by the company it keeps”。這是現代統計NLP很成功的一個觀點。其實這也符合人類的思維習慣,人了解一個詞并不是單純的看這個詞的拼寫來了解它的意思,而是通過上下文來了解其意思。
© Make neighbors represent words
1. Co-occurrence Matrix(共現矩陣)
使用co-occurrence matrix表示單詞,CM有兩種表示法:
• 詞-文檔矩陣(Word-Document Matrix)
它的大小是|V|M,|V|是詞彙表的大小,M是文檔的數目。Word-document的共現矩陣最終會得到泛化的主題(例如體育類詞彙會有相似的标記),這就是淺層語義分析(LSA, Latent Semantic Analysis)。
• 基于視窗的共現矩陣(Windows based Co-occurrence Matrix)
它的大小是|V||V|,這種方法容易探測到單詞的Syntactic and semantic information,windows的選擇一般選5-10之間。一個簡單例子:
• 視窗長度是1(一般是5-10)
• 對稱(左右内容無關)
• 語料樣例:I like deep learning; I like NLP; I enjoy flying
CM存在的問題,
•規模随着語料庫詞彙的增加而增加
•非常高的次元:需要大量的存儲
•過于稀疏,不利于後續分類處理
•模型不夠健壯
解決方案:低維向量
• idea: 将最重要的資訊存儲在固定的,低次元的向量裡:密集向量(dense vector)
• 維數通常是25-1000
那如何降維呢?
2. SVD(奇異值分解)
對共現矩陣X進行奇異值分解。
觀察奇異值(矩陣的對角元素),并根據我們期待保留的百分比來選擇(隻保留前k個次元):
然後我們把子矩陣U1:|V|,1:k視作我們的詞嵌入矩陣。也就是說,對于詞表中的每一個詞,我們都用一個k維的向量來表達了。
對X采用奇異值分解
通過選擇前K個奇異向量來進行降維:
Python中簡單的詞向量SVD分解
• 語料:I like deep learning. I like NLP. I enjoy flying
• 列印U矩陣的前兩列這也對應了最大的兩個奇異值
這兩種方法都能産生詞向量,它們能夠充分地編碼語義和句法的資訊,但同時也帶來了其他的問題:
• 矩陣的次元會經常變化(新的詞語經常會增加,語料庫的大小也會随時變化)。
• 矩陣是非常稀疏的,因為大多數詞并不同時出現。
• 矩陣的次元通常非常高(≈106×106)
• 訓練需要O(n2)的複雜度(比如SVD)
• 需要專門對矩陣X進行特殊處理,以應對詞組頻率的極度不平衡的狀況
當然,有一些辦法可以緩解一下上述提到的問題:
• 忽視諸如“he”、“the” 、“has”等功能詞。
• 使用“傾斜視窗”(ramp window),即:根據檔案中詞組之間的距離給它們的共現次數增加相應的權重。
• 使用皮爾森的相關性(Pearson correlation),将0記為負數,而不是它原來的數值。
Hacks to CM
之前用SVD處理的方法很好,但是在原始的CM中有很多問題。
•功能詞(the,he, has)太多,對文法有很大影響,解決辦法是使用或完全忽略功能詞。
•之前的CM建立方法不合理,很顯然距離單詞越近的詞和這個詞的相關性越高,反之相關性越小,是以我們可以使用一個Ramped windows(斜的窗)來建立CM,類似于用一個weight乘count,距離越遠weight越小反之越大(weight是個bell shape函數);
•用皮爾遜相關系數代替計數,并置負數為0
Interesting semantic patterns emerge in the vectors
至此使用SVD處理就大概講完了,這玩意有啥用呢?這時出現了三個美麗的Patterns。第一個就是用Hierarchical Clustering來聚類行向量可以進行同義詞聚類,這個video上講的比較略,我是通過網上查了半天太查出來這個東東(- -);第二個美麗的pattern就是同義的單詞在word-spaces裡,同義詞靠的近,不同意思的詞靠的遠;第三個美麗的pattern就是相似的semantic pair word之間的向量距離也類似。
problems with SVD
•計算量極大,人類的語料庫有數以trillion的資料,将它儲存到一個矩陣中,然後做SVD恐怕目前最先進的計算機都吃不消;對于n*m的矩陣來說計算的時間複雜度是O(mn^2)。
•對于新詞或者新的文檔很難及時更新;
•相對于其他的DL模型,有着不同的學習架構。
3.基于疊代的方法-word2vec
現在我們退後一步,來嘗試一種新的方法。在這裡我們并不計算和存儲全局資訊,因為這會包含太多大型資料集和數十億句子。我們嘗試建立一個模型,它能夠一步步疊代地進行學習,并最終得出每個單詞基于其上下文的條件機率。
詞語的上下文:一個詞語的上下文是它周圍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)),我們稱之為誤差“反向傳播”法。
通過向量定義詞語的含義
對每個詞組都建立一個dense vector,使得它能夠預測上下文其他單詞(其他單詞也是用向量表示)。
補充:詞向量目前常用的有2種表示方法,one-hot representation和distributed representation。詞向量,顧名思義就是将一個詞表示為向量的形式,一個詞,怎麼可以将其表現為向量呢?最簡單的就是One-hot representation,它是以詞典V中的詞的個數作為向量的次元,按照字典序或某種特定的順序将V排序後,詞w的向量可以表示為: [0,0,1,0,0,…,0],即詞w出現的位置為1,其餘均為0. 可以看到,這種方法表示的詞向量太過于稀疏,次元太高,會引起次元災難,而且非常不利于計算詞之間的相似度。另一種distributed representation可以解決上述問題,它通過訓練将一個詞映射為相對于One-hot representation來說一個比較短的向量,它的表示形式類似于:[0.1,0.34,0.673,0.983]。
■ 學習神經網絡word embeddings的基本思路
定義一個以預測某個單詞的上下文的模型:
p ( c o n t e x t ∣ w t ) = . . . p(context|w_t)=... p(context∣wt)=...
損失函數定義如下:
J = 1 − p ( w − t ∣ w t ) J=1-p(w_{-t}|w_t) J=1−p(w−t∣wt)
這裡的w−t表示wt的上下文(負号通常表示除了某某之外),如果完美預測,損失函數為零。
然後在一個大型語料庫中的不同位置得到訓練執行個體,調整詞向量,最小化損失函數。
■直接學習低次元的詞向量
這其實并不是多麼新潮的主意,很早就有一些研究了:
• Learning representations by back-propagating errors (Rumelhart et al., 1986)
• A neural probabilistic language model (Bengio et al., 2003)
• NLP (almost) from Scratch (Collobert & Weston, 2008)
• A recent, even simpler and faster model: word2vec (Mikolov et al. 2013)
隻不過以前一直沒有引起重視,直到Bengio展示了它的用處之大。後來研究才開始火熱起來,并逐漸出現了更快更工業化的模型。
3.1 語言模型(1-gram,2-gram等等)
首先,我們需要建立一個能給“分詞序列”配置設定機率的模型。我們從一個例子開始:
“The cat jumped over the puddle.”(貓 跳 過 水坑)
一個好的語言模型會給這句話以很高的機率,因為這是一個在文法和語義上完全有效的句子。同樣地,這句”stock boil fish is toy”(股票 煮 魚 是 玩具)就應該有一個非常低的機率 ,因為它是沒有任何意義的。在數學上,我們可以令任意給定的n個有序的分詞序列的機率為:
p ( w 1 , w 2 , . . . w n ) p(w_1,w_2,...w_n) p(w1,w2,...wn)
我們可以采用一進制語言模型。它假定詞語的出現是完全獨立的,于是可以将整個機率拆開相乘: p ( w 1 , w 2 , . . . w n = ∏ i = 1 n p ( w i ) ) p(w_1 ,w_2,...w_n= \prod_{i=1}^n p(w_i)) p(w1,w2,...wn=i=1∏np(wi))
看到這裡,肯定很多同學就要噴了,這不對,詞和詞之間沒有關聯嗎?确實,我們知道一句話中每一個詞語都跟它前面的詞語有很強的依賴關系,忽略這一點的話,一些完全無意義的句子,可能會有很高的機率。咱們稍微改一改,讓一個詞語的機率依賴于它前面一個詞語。我們将這種模型稱作bigram(2-gram,二進制語言模型),表示為: p ( w 1 , w 2 , . . . w n = ∏ i = 2 n p ( w i ∣ w i − 1 ) ) p(w_1 ,w_2,...w_n= \prod_{i=2}^n p(w_i|w_{i-1})) p(w1,w2,...wn=i=2∏np(wi∣wi−1))
看起來還是有點簡單?恩,也對,我們隻考慮一個詞語依賴于其相鄰的一個詞語的關系,而不是考慮其依賴整個句子的情況。别着急,接下來将會看到,這種方法能讓我們有非常顯著的進步。考慮到前面 “詞-詞”矩陣的情況,我們至少可以算出兩個詞語共同出現的機率。但是,舊話重提,這仍然要求儲存和計算一個非常的大資料集裡面的全部資訊。
現在我們了解了“分詞序列”的機率(其實就是N-gram語言模型啦)。
補充:
語言模型可以分為文法型模型和統計語言模型。在實際應用中語言識别、手寫體文字識别、機器翻譯、鍵盤輸入、資訊檢索等研究領域都用到了語言模型。文法型語言模型是人工編制的語言學文法,文法規則來源于語言學家掌握的語言學知識和領域知識,但這種語言模型不能處理大規模真實文本。是以,統計語言模型出現了,并且得到了廣泛的應用,統計語言模型是基于機率的,包括了N元文法模型(N-gram Model)、隐馬爾科夫模型(Hidden Markov Model,簡稱HMM)、最大熵模型(Maximum Entropy Model)。
1、統計語言模型的基本原理
統計語言模型是以機率分布的形式說明了一個字元串出現的機率。假設詞(word)是語言的最小機關,句子S是由一系列的詞w1,w2,…,wk順序構成,則句子S的機率為下: p ( s ) = p ( w 1 ) p ( w 2 ∣ w 1 ) . . . p ( w n ∣ w 1 , w 2 , … , w n − 1 ) = ∏ i = 1 n p ( w i ∣ w 1 , w 2 , . . . w i − 1 ) p(s)=p(w_1)p(w_2|w_1)...p(w_n|w_1 ,w_2 ,…, w_{n−1})=\prod_{i=1}^np(w_i|w_1,w_2,...w_{i-1}) p(s)=p(w1)p(w2∣w1)...p(wn∣w1,w2,…,wn−1)=i=1∏np(wi∣w1,w2,...wi−1)且,上式中約定p(w1|w0)=p(w1).觀察上式可以發現,句子S的機率計算是很複雜的,是以,往往采用一些方法來估計語料庫中句子的機率。
2、主要的統計語言模型
1)、上下文無關模型
上下文無關模型就是詞w1的出現與它所處的環境無關,僅僅是它在語料中出現的機率,即它是n-gram中n=1的情況,但是實際上,這種方法效果并不是很好。
2)、 n-gram模型
n-gram模型是要考慮上下文的。w1出現的是依賴于它之前的n-1個詞的,即需要計算詞表中的每一個n-1元組的機率,此計算量是巨大的,是以實際中,常取n=2 或n=3.
3)、暫時記錄在此
隐馬爾科夫模型(Hidden Markov Model,簡稱HMM)和最大熵模型(Maximum Entropy Model)暫時還沒有深入研究,暫時記錄下來,以後進行補充。
3.2 word2vec
Word2vec主要思想: Predict between every word and its context words!
包含兩個算法:
• Skip-gram (SG): 預測上下文。
• Continuous Bag of Words (CBOW): 預測目标單詞。
以及兩種訓練方法:
• hierarchical softmax: 通過樹結構來定義目标函數,來計算所有詞彙的機率。
• negative sampling: 通過負樣本采樣,來定義目标函數
Skip-gram (SG):
在每次疊代過程中,以一個詞組為中心(center word),預測一個視窗中的上下文詞組。是以模型定義了一個機率分布,這個機率分布就是指給定中心詞組時,上下文詞組出現的機率。我們需要做的就是最大化這個機率分布。
細節:
對每個詞組t=1…T,預測每個詞組半徑為m的視窗内的上下文詞組。
目标函數:對于一個中心詞,最大化上下文任意單詞的機率:
J 0 ( θ ) = ∏ t = 1 T ∏ − m ≤ j ≤ m , j ≠ 0 p ( w t + j ∣ p ( w t ) ; θ ) J^{0}(\theta)=\prod_{t=1}^T\prod_{-m\le{j}\le{m} , j\ne{0}}p(w_{t+j}|p(w_t);\theta) J0(θ)=t=1∏T−m≤j≤m,j̸=0∏p(wt+j∣p(wt);θ)
将其轉換成負的對數似然形式:
J ( θ ) = − 1 T ∑ t = 1 T ∑ − m ≤ j ≤ m , j ≠ 0 l o g p ( w t + j ∣ p ( w t ) ) J(\theta)=-\frac{1}{T}\sum_{t=1}^T\sum_{-m\le{j}\le{m} , j\ne{0}} log p(w_{t+j}|p(w_t)) J(θ)=−T1t=1∑T−m≤j≤m,j̸=0∑logp(wt+j∣p(wt))
目标函數的細節:
• 對于機率分布通常使用的損失: 交叉熵損失(cross-entropy loss)
• 我們的目标是one-hot的 ,它隻是來預測實際出現的詞組。那麼交叉熵損失中僅剩的就是真實類别的負機率。
預測到的某個上下文條件機率 可由softmax得到:
這裡,o是輸出單詞在詞彙表中的下标,c是中心詞的下标, v c v_c vc 是center word vectors, u o u_o uo 是context word vectors。 u o T v c u_o^Tv_c uoTvc 是兩個向量的點積。對于點積, u T v = u ⋅ v = ∑ i = 1 n u i v i u^Tv=u\cdot{v}=\sum_{i=1}^nu_iv_i uTv=u⋅v=∑i=1nuivi ,若u和v比較相似的話,那麼它們的點積更大,是以點積是相似度的一種度量方式。這裡, 表示每個詞組和v的相似程度,然後我們把它放到softmax中。
Softmax function:從實數空間到機率分布的标準映射方法
指數函數可以把實數映射成正數,然後歸一化得到機率。
softmax之所叫softmax,是因為指數函數會導緻較大的數變得更大,小數變得微不足道;這種選擇作用類似于max函數。
■ Skip-gram模型:
從左到右, w t w_t wt是中心詞的one-hot vector,W是中心詞的表示矩陣, v c = W w t v_c=Ww_t vc=Wwt是中心詞的嵌入詞向量(embedded word vector)。 W ′ W' W′是context words的表示矩陣,注意在每個位置都是同一個表示矩陣,也就是說我們隻有一個context word matrix。
從左到右是one-hot向量,乘以center word的W于是找到詞向量,乘以另一個context word的矩陣W’得到對每個詞語的“相似度”,對相似度取softmax得到機率,與答案對比計算損失。
整理上面的圖,得到下圖。
這兩個矩陣都含有V個詞向量,也就是說同一個詞有兩個詞向量,哪個作為最終的、提供給其他應用使用的embeddings呢?有兩種政策,要麼加起來,要麼拼接起來。在CS224n的程式設計練習中,采取的是拼接起來的政策:
# concatenate the input and output word vectors
wordVectors = np.concatenate(
(wordVectors[:nWords,:], wordVectors[nWords:,:]),axis=0)
# wordVectors = wordVectors[:nWords,:] + wordVectors[nWords:,:]
他們管W中的向量叫input vector,W’中的向量叫output vector。
實際上,在原始的CBOW / Skip-gram模型中,任一個詞 w i w_i wi 将得到兩個word embedding(設次元為 n ):作為中心詞時的詞向量,也稱為輸出詞向量 v i ∈ R n × 1 v_i\in{R^{n\times{1}}} vi∈Rn×1 ;以及作為周圍詞時的詞向量,也稱為輸入詞向量 u i ∈ R n × 1 u_i\in{R^{n\times{1}}} ui∈Rn×1 。詞向量的下标和詞的下标相對應,比如說目标詞 w t w_t wt的詞向量就對應為 v t v_t vt 和 u t u_t ut。
訓練模型:計算參數向量的梯度
把所有參數寫進向量θ,對d維的詞向量和大小V的詞表來講,有:
由于上述兩個矩陣的原因,是以θ的次元中有2個。
我們要優化的目标函數為:
損失/目标函數
梯度有了,參數減去梯度就能朝着最小值走了。
梯度下降、SGD
隻有一句比較新鮮,神經網絡喜歡嘈雜的算法,這可能是SGD成功的另一原因。
Continuous Bag of Words Model (CBOW):
連續詞袋模型是根據上下文context words來預測center word。如根據{“The”,”cat”,”over”,”the”,”puddle”}預測中間詞”jumped”。
CBOW示意圖:
損失函數: