斯坦福深度學習與自然語言處理課程是Richard Socher今年開的課程。他是德國人,本來學習的是機器視覺。在斯坦福大學博士畢業,師從Andrew Ng和Chris Channing學習機器學習和NLP,畢業後也成爲一個大牛。本人小白一枚,花了好長時間才消化了課程的視頻和課件,爲了防止以後忘記,在這裏紀錄一下。
先放上該課程的官網鎮樓:http://cs224d.stanford.edu/syllabus.html
還有一個專門提供NLP資料的網站:http://www.52nlp.cn
課程的官網課件和筆記我會在每次看完後上傳到CSDN,可以免費下載(lecture2的課件後來發現要一個積分才能下載,想改成免費但是CSDN貌似改不了)
Lecture1 沒有什麼乾貨,不寫了。
Lecture2 詞矢量
計算機如何表示單詞的含義呢?普遍的做法是像WordNet(這究竟是個什麼,調研之後再補上)一樣用分類的方法表示從屬關係和同義關係。但是這樣的做法有很多侷限,例如生詞和新詞就無法表示,並且需要大量的人力去建造和維護,最關鍵的是無法準確度量詞語之間的相似度,於是詞語的離散表示(discrete representation)應運而生。
在向量空間裏,一個向量通常有1個1和很多0(剩下的應該都是0),維度從20K(語音)到13M(Google1T)不等,這種表示方式我們稱爲”one-hot”表示。但是這種表示方法有個問題,假設
motel=[0000001000000]
hotel=[0000100000000],則
You shall know a word by the company it keeps
——J.R.Firth 1957:11
詞矢量的基本假設: 假設相似的詞總是有相似的上下文
於是我們使用上下文來表示一個單詞。用上下文表示詞語有兩種方法:用整個文檔的詞表示當前單詞,和使用有限長窗口內的詞表示當前單詞,究竟應該選用哪種方案呢?
整個文檔VS窗口
- 使用文檔的話,詞-文檔的共現矩陣會使得大衆話題有相似的輸入,導致進一步的隱藏語義分析
- 使用窗口的話可以讓我們同時保留句法(POS)和語法信息
所以此後我們使用基於窗口的方法用上下文表示詞矢量。窗的長度通常爲5-10。
在這裏,我們令窗長爲1,計算對稱的共現矩陣。
Example corpus:
- I like learning.
- I like NLP.
- I enjoy flying.
得到的共現矩陣見pdf第8頁
共現矩陣的問題是隨着字典的變大而變大,需要很高維的存儲,並且在後續的分類模型中會有稀疏問題,所以需要進行降維。如何用最重要的若干信息來生成密集的向量呢?
SVD分解
SVD分解就是把一個
簡單的python編程在pdf第12頁中有。我自己寫了一個python小程序,自帶求共現矩陣功能。完整代碼:
import numpy as np
import matplotlib.pyplot as plt
la=np.linalg
sentence=[[],[],[]]
sentence[0]=["I","like","deep","learning","."]
sentence[1]=["I","like","NLP","."]
sentence[2]=["I","enjoy","flying","."]
wordset=sentence[0]+sentence[1]+sentence[2]
vocabulary=sentence[0]
def count(x,y):
count=0
for i in range(0,3):
if x in sentence[i] and y in sentence[i]:
if np.fabs(sentence[i].index(y)-sentence[i].index(x))==1:
count+=1
return count
for i in wordset:
if not i in vocabulary:
vocabulary.append(i)
lenth=len(vocabulary)
X=np.zeros((lenth,lenth))
for i in range(0,lenth):
for j in range(0,lenth):
X[i][j]=count(vocabulary[i],vocabulary[j])
print X
U,s,Vh=la.svd(X,full_matrices=False)
print U,s,Vh
fig=plt.figure()
for i in xrange(lenth):
plt.text(U[i,0],U[i,1],vocabulary[i])
plt.xlim(-0.8,0.3)
plt.ylim(-0.6,0.6)
plt.show()
上圖爲程序運行的結果,可以看到詞的座標位置和課件上的並不一樣。說明了結果與詞的排列順序有關,不同順序共現矩陣不同,效果不同。爲了效果起見,應該將詞的順序按照在文檔中出現的頻率降序排列。
Hacks to X(共現矩陣):
對於像(the,he,she)這樣的功能詞,出現頻率太高,解決方法:
- 使用min(X,t),t~100的方法限制最高頻率
- 直接忽略
- 用pearson correction 而不是直接統計次數,將負值設爲0
- 使用有斜坡的窗使靠近的詞更高比重(感覺就像DSP裏的漢寧窗和漢命窗等)
。。。
SVD分解的問題:
對於一個n*m的矩陣,計算複雜度是
所以有了新的思路:直接學習低維詞矢量
word2vec
word2vec主要思想
- 並非直接計算共現次數,而是預測每個詞周圍的詞
- 與Golve很相似
- 更快更容易適應新文檔和在單詞里加入新詞
具體細節
目標函數:給定當前中心詞,最大化上下文中所有的詞的log概率
對於
其中,v和v’分別是一個單詞的”輸入”和”輸出”詞矢量,即每個詞有兩個向量。輸入向量很好理解,就是作爲中心詞時的詞矢量。一開始我並不懂“輸出”詞矢量是什麼鬼,看到Lecture3才明白,原來就是該詞在變成非中心詞時更新後的矢量。
例如 I like to run, 當like作爲中心詞時,它當前的詞矢量爲”輸入”詞矢量
梯度的推導
基礎知識:
∂xTa∂x=∂aTx∂x=a - Chain rule!
dydx=dydududx
推導開始:
有木有很神奇!在當前中心詞C下週圍詞O的log概率的梯度爲,周圍詞O的”輸出“詞矢量減去,在中心詞C下所有詞X的概率乘X的”輸出“詞矢量之和(即所有”輸出“詞矢量的期望)。
雖然化成這種形式之後很方便計算,可以使用梯度下降法(SGD)求解,但是因爲每次更新都需要計算所有詞的概率和詞矢量,這個目標函數在大詞彙的字典並不適用,因爲尺度太大訓練太慢!
解決思路:
- 進行近似
- 定義負預測(negative prediction)(對於在上下文中不出現的單詞,只採樣幾個,從而把注意力集中在大多數的正預測上)目前不是很懂這個負預測是什麼,有什麼作用,之後搞懂裏再補上
在word2vec裏發現的線性關係:
-句法上
-語義上
講義裏還有很多圖片,這裏不貼了
Lecture3 預告
- details to implement word2vec
- word embedding matrix
- advantages of low dimensional word vectors