天天看點

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

第二講:簡單的詞向量表示: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.詞向量在這種類型的編碼中如下圖所示:

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

這種詞向量編碼方式簡單粗暴,我們将每一個詞作為一個完全獨立的個體來表達。遺憾的是,這種方式下,我們的詞向量沒辦法給我們任何形式的詞組相似性度量。例如:

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

(注:hotel和motel是近義詞)

究其根本你會發現,是你開了一個極高次元的空間,然後每個詞語都會占據一個次元,是以沒有辦法在空間中關聯起來。是以我們可能可以把詞向量的次元降低一些,在這樣一個子空間中,可能原本沒有關聯的詞就關聯起來了。

(b)Distributional similarity based representations

通過一個詞語的上下文可以學到這個詞語的很多知識,”You shall know a word by the company it keeps”。這是現代統計NLP很成功的一個觀點。其實這也符合人類的思維習慣,人了解一個詞并不是單純的看這個詞的拼寫來了解它的意思,而是通過上下文來了解其意思。

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

© 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

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

CM存在的問題,

•規模随着語料庫詞彙的增加而增加

•非常高的次元:需要大量的存儲

•過于稀疏,不利于後續分類處理

•模型不夠健壯

解決方案:低維向量

• idea: 将最重要的資訊存儲在固定的,低次元的向量裡:密集向量(dense vector)

• 維數通常是25-1000

那如何降維呢?

2. SVD(奇異值分解)

對共現矩陣X進行奇異值分解。

觀察奇異值(矩陣的對角元素),并根據我們期待保留的百分比來選擇(隻保留前k個次元):

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

然後我們把子矩陣U1:|V|,1:k視作我們的詞嵌入矩陣。也就是說,對于詞表中的每一個詞,我們都用一個k維的向量來表達了。

對X采用奇異值分解

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

通過選擇前K個奇異向量來進行降維:

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

Python中簡單的詞向量SVD分解

• 語料:I like deep learning. I like NLP. I enjoy flying

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

• 列印U矩陣的前兩列這也對應了最大的兩個奇異值

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

這兩種方法都能産生詞向量,它們能夠充分地編碼語義和句法的資訊,但同時也帶來了其他的問題:

• 矩陣的次元會經常變化(新的詞語經常會增加,語料庫的大小也會随時變化)。

• 矩陣是非常稀疏的,因為大多數詞并不同時出現。

• 矩陣的次元通常非常高(≈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之間的向量距離也類似。

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove
cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove
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,使得它能夠預測上下文其他單詞(其他單詞也是用向量表示)。

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

補充:詞向量目前常用的有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∏n​p(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∏n​p(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∏n​p(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),預測一個視窗中的上下文詞組。是以模型定義了一個機率分布,這個機率分布就是指給定中心詞組時,上下文詞組出現的機率。我們需要做的就是最大化這個機率分布。

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

細節:

對每個詞組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(θ)=−T1​t=1∑T​−m≤j≤m,j̸​=0∑​logp(wt+j​∣p(wt​))

目标函數的細節:

• 對于機率分布通常使用的損失: 交叉熵損失(cross-entropy loss)

• 我們的目标是one-hot的 ,它隻是來預測實際出現的詞組。那麼交叉熵損失中僅剩的就是真實類别的負機率。

預測到的某個上下文條件機率 可由softmax得到:

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

這裡,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 uoT​vc​ 是兩個向量的點積。對于點積, 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=1n​ui​vi​ ,若u和v比較相似的話,那麼它們的點積更大,是以點積是相似度的一種度量方式。這裡, 表示每個詞組和v的相似程度,然後我們把它放到softmax中。

Softmax function:從實數空間到機率分布的标準映射方法

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

指數函數可以把實數映射成正數,然後歸一化得到機率。

softmax之所叫softmax,是因為指數函數會導緻較大的數變得更大,小數變得微不足道;這種選擇作用類似于max函數。

■ Skip-gram模型:

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

從左到右, 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得到機率,與答案對比計算損失。

整理上面的圖,得到下圖。

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

這兩個矩陣都含有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的詞表來講,有:

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

由于上述兩個矩陣的原因,是以θ的次元中有2個。

我們要優化的目标函數為:

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

損失/目标函數

梯度有了,參數減去梯度就能朝着最小值走了。

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

梯度下降、SGD

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

隻有一句比較新鮮,神經網絡喜歡嘈雜的算法,這可能是SGD成功的另一原因。

Continuous Bag of Words Model (CBOW):

連續詞袋模型是根據上下文context words來預測center word。如根據{“The”,”cat”,”over”,”the”,”puddle”}預測中間詞”jumped”。

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

CBOW示意圖:

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

損失函數:

cs224n第二講:簡單的詞向量表示:word2vec, Glove第二講:簡單的詞向量表示:word2vec, Glove

繼續閱讀