2019-CS224n-Assignment2

個人原文:2019-CS224n-Assignment2html

此次複習cs224n主要是先熟悉python和pytorch,方便以後進行論文復現等工做,同時也回顧一下模型和數學公式推導,找找感受。python

解答:理解詞向量(23分)

咱們先快速回顧一下word2vec算法,它的核心思想是「一個詞的含義取決於它周圍的詞」。具體來講,咱們有一箇中心詞(center word) c,和這個詞 c 周圍上下文構成的窗口,這個窗口內的除了 c 以外的詞叫作外圍詞(outside words)。好比下圖中,中心詞是「banking」,窗口大小爲2,因此上下文窗口是:「turning」、」into「、」crises「和」as「。web

mark

Skip-gram模型(word2vec的一種實現)目的是習得機率分佈 P(O|C)。這樣一來,就能計算給定的一個詞 o 和詞 c 的機率 P(O=o|C=c)(意爲,在已知詞 c 出現的狀況下,詞 o 出現的機率), c 是中心詞,o 是外圍詞。算法

在word2vec中,這個條件機率分佈是經過計算向量點積(dot-products),再應用naive-softmax函數獲得的:shell

mark

這裏, u_o 向量表明外圍詞,v_c 向量表明中心詞。爲了包含這些向量,咱們有兩個矩陣 \boldsymbol{U}\boldsymbol{V}\boldsymbol{U} 的列是外圍詞, \boldsymbol{V} 的列是中心詞,這兩矩陣都有全部詞 w \in Vocabulary 的表示 。網絡

對於詞 c 和詞 o,損失函數爲對數概率:app

mark

能夠從交叉熵的角度看這個損失函數。真實值爲 \boldsymbol{y} ,是一個獨熱向量,預測值 \boldsymbol{\hat{y}} 是由公式(1)計算獲得。具體來講, \boldsymbol{y} 若是是第k個單詞,那麼它的第k維爲1,其他維都是0,而 \boldsymbol{\hat{y}} 的第k維表示這是第k個詞的機率大小。ide

問題(a) (3分)

證實公式(2)給出的naive-softmax的損失函數,和 \boldsymbol{y}\boldsymbol{\hat{y}} 的交叉熵損失函數是同樣的,均以下所示(答案控制在一行)函數

mark

答:優化

由於除了 o 以外的詞都不在窗口內,因此只有詞 o 對損失函數有貢獻

問題(b) (5分)

計算損失函數 \boldsymbol{J}_{naive-softmax}(v_c, o, \boldsymbol{U}) 對中心詞 v_c 的偏導數,用 \boldsymbol{y}\boldsymbol{\hat{y}}\boldsymbol{U} 來表示。

答:

爲了方便表述,對於該外圍詞 o 咱們設:

x_o = u_o^T v_ct_o =exp(x_o)s_o=\sum_{w \in Vocab} exp(x_w)\hat{y_o} = g _o=\frac{t_o}{s_o} ,下面對 x_o 求導

J = -log(\hat{y_o})=-ln(g_o) (這裏的log蘊含意思是ln)

t_o'= t_o = e^{x_o}s' = e^{x_o}

g_o' =\frac{t_o's_o -t_os'_o}{s_o^2} = g_o (1-g_o)

\frac{\partial{J}}{\partial{x_o}} = \frac{\partial{J}}{\partial{g_o}} · \frac{\partial{g_o}}{\partial{x_o}} = \hat{y_o} - y_o

則對 v_c 的導數爲:

\frac{\partial{J}}{\partial{v_c}}=\frac{\partial{J}}{\partial{x_o}} · \frac{\partial{x_o}}{\partial{v_c}} = (\hat{y_o} - y_o)  · u^T,引入矩陣得:

\boldsymbol{J}_{native-softmax}=(v_c, o, \boldsymbol{U}) = (\hat{y} - y) · \boldsymbol{U}

問題(c) (5分)

計算損失函數 \boldsymbol{J}_{naive-softmax}(v_c, o, \boldsymbol{U}) 對上下文窗口內的詞 w 的偏導數,考慮兩種狀況,即 w 是外圍詞 o,和 w 不是 o,用 \boldsymbol{y}\boldsymbol{\hat{y}}v_c 來表示。

答:

在問題(b)基礎上,對 x_w=u_w^Tv_c 求導。

w \not =o 時:

t_o'=0s_o'=e^{x_w}

g_o' = \frac{0-t_os'_o}{s_o^2}=- \frac{e^{x_o}}{s_o} · \frac{e^{x_w}}{s_o}=-g_o ·g_w

w = o 時,由問題(b)得:

g_o'=g_o(1-g_o)

綜合上述兩種狀況,因此有:

\frac{\partial{J}}{\partial{x_w}}=-\sum_{i \in Vocab}y_i\frac{\partial log(g_i)}{\partial{x_w}}

=  -y_w(1-g_w) + \sum_{i \not=w}y_ig_w

= -y_w+g_w\sum_{i \in Vocab}y_i

= g_w-y_w

\frac{\partial{J}}{\partial{u_w}} = (\hat{y}-y)·v_c

問題(d) (3分)

sigmoid函數如公式(4)所示

mark

請計算出它對於 \boldsymbol{x} 的導數, \boldsymbol{x} 是一個向量

答:

\sigma(x)'=\sigma(x)(1-\sigma(x))

問題(e) (4分)

如今咱們考慮負採樣的損失函數。假設有K個負樣本,表示爲 w_1, w_2, ..., w_K,它們對應的向量爲 u_1, u_2, ..., u_K,外圍詞 o \not\in \{w_1, w_2, ..., w_K\},則外圍詞 o 在中心詞是 c 時產生的損失函數如公式(5)所示。

mark

根據該損失函數,從新計算問題(b)、問題(c)的偏導數,用 \boldsymbol{u}_o\boldsymbol{v}_c\boldsymbol{u}_k 來表示。

完成計算後,簡要解釋爲何這個損失函數比naive-softmax效率更高。

注意:你能夠用問題(d)的答案來幫助你計算導數

答:

(略,詳見代碼)

提示:

  • 詞庫從 Vocab 變成了這K+1個詞

  • 在求內層導數的時候用了sigmoid函數

問題(f) (3分)

假設中心詞是 c = w_t,上下文窗口是 [w_{t-m}, ..., w_{t-1}, w_t, w_{t+1}, ..., w_{t+m}]m 是窗口大小,回顧skip-gram的word2vec實現,在該窗口下的總損失函數是:

mark

這裏,\boldsymbol{J}(\boldsymbol{v}_c, w_{t+j}, \boldsymbol{U}) 是外圍詞 w_{t+j} 在中心詞 c=w_t 下產生的損失,損失函數能夠是naive-softmax或者是neg-sample(負採樣),這取決於具體實現。

計算:

(i) 損失函數對 \boldsymbol{U} 的偏導數

(ii) 損失函數對 \boldsymbol{v}_c 的偏導數

(iii) 損失函數對 \boldsymbol{u}_ww \not= c )的偏導數

答:

(略,詳見代碼)

提示:把上下文窗口全部詞的損失加起來便可

代碼:實現word2vec(20分)

點擊 此處 下載代碼,python版本 >= 3.5,須要安裝numpy,你利用conda來配置環境:

conda env create -f env.yml
conda activate a2
複製代碼

寫完代碼後,運行:

conda deactivate
複製代碼

問題(a) (12分)

首先,實現 word2vec.py 裏的 sigmoid函數,要支持向量輸入。接着實現同一個文件裏的 softmax 、負採樣損失和導數。而後實現skip-gram的損失函數和導數。所有作完以後,運行python word2vec.py來檢查是否正確。

答:

sigmoid

沒什麼好講的,numpy會本身廣播,最終獲得向量輸出

s = 1 / (1 + np.exp(-x))
複製代碼

naiveSoftmaxLossAndGradient

這個模型其實就是一個三層的前饋神經網絡(詳解),只須要注意維度便可,註釋裏已經標記出了維度。

須要注意的是,單詞表示是在行,而不是列。

# forward
a, W, target = centerWordVec, outsideVectors, outsideWordIdx
a = a.reshape((a.shape[0], 1))
# assume N words, V dimentions, so
# a.shape == (V, 1) W.shape == (N, V)

z = np.dot(W, a) # (N, 1)
preds = softmax(z.reshape(-1)).reshape(-1, 1) # (N, 1)

loss = -np.log(preds[target])


# backprop
delta = preds.copy() # (N, 1)
delta[target] -= 1.0

gradCenterVec = np.dot(W.T, delta) # (V, 1)

gradOutsideVecs = np.dot(delta, a.T) # (N, V)

gradCenterVec = gradCenterVec.flatten() # (V, )
複製代碼

negSamplingLossAndGradient

與native-softmax不一樣的是:

  • 只選取K個非外圍詞(負樣本,可能有重複詞),外加1個正確的外圍詞,共K+1個輸出
  • 最後一層使用sigmoid輸出,而不是softmax

注意,反向傳播獲得的是這K+1個詞的梯度,因此須要挨個更新到 梯度矩陣 中去

### Please use your implementation of sigmoid in here.

# indices might have same index
# extract W
W = np.zeros((len(indices), outsideVectors.shape[1]))
for i in range(len(indices)):
    W[i] = outsideVectors[indices[i]]

# forward
a = centerWordVec
a = a.reshape((a.shape[0], 1))

z = np.dot(W, a) # (K+1, 1)
preds = sigmoid(z)

# backprop
y = np.zeros((preds.shape[0], 1))
y[0] = 1 # index 0 is target

loss = -(y*np.log(preds) + (1 - y)*np.log(1 - preds)).sum()

delta = preds - y
gradCenterVec = np.dot(W.T, delta) # (V, 1)
gradW = np.dot(delta, a.T) # (K+1, V)
gradCenterVec = gradCenterVec.flatten()

# apply gradW into gradOutsideVecs
gradOutsideVecs = np.zeros_like(outsideVectors)
for i in range(len(indices)):
    oi = indices[i]
    gradOutsideVecs[oi] += gradW[i]
複製代碼

skipgram

遍歷全部的外圍詞,求和損失函數

ci = word2Ind[currentCenterWord]
vc = centerWordVectors[ci]

for o in outsideWords:
    oi = word2Ind[o]
    loss_, gradVc, gradUo = word2vecLossAndGradient(vc, oi, outsideVectors, dataset)
    gradCenterVecs[ci] += gradVc
    gradOutsideVectors += gradUo
    loss += loss_
複製代碼

問題(b) (4分)

完成sgd.py文件的SGD優化器,運行python sgd.py來檢查是否正確。

sgd

調用函數獲得損失值和梯度,更新便可

loss, grad = f(x)
x = x - step*grad
複製代碼

問題(c) (4分)

至此全部的代碼都寫完了,接下來是下載數據集,這裏咱們使用Stanform Sentiment Treebank(SST)數據集,它能夠用在簡單的語義分析任務中去。經過運行 sh get_datasets.sh 能夠得到該數據集,下載完成後運行 python run.py 便可。

注意:訓練的時間取決於代碼是否高效(即使是高效的實現,也要跑接近一個小時)

通過40,000次迭代後,最終結果會保存到 word_vectors.png 裏。

答:

mark

  • 注意看,male->famale 和 king -> queen 這兩條向量是平行的
  • (women, famale),(enjoyable,annoying) 這些詞距離很近

參考

[1] CS224n: Natural Language Processing with Deep Learning, 2019-03-14. web.stanford.edu/class/cs224….

[2] CS224n Assignment 1, 2019-03-14. www.hankcs.com/nlp/cs224n-…

本站公眾號
   歡迎關注本站公眾號,獲取更多信息