NLP-Assignment2
Assignment2
解答:理解词向量(23分)
我们先快速回顾一下word2vec算法,它的核心思想是“一个词的含义可以由它周围的词来表示”。具体来说,我们有一个中心词(center word) c,和这个词 c 周围上下文构成的窗口,这个窗口内的除了 c 之外的词叫做外围词(outside words)。比如下图中,中心词是“banking”,窗口大小为2,所以上下文窗口是:“turning”、”into“、”crises“和”as“。
Skip-gram模型(word2vec比较常用的一种实现,另一种是cbow)目的是学习概率分布 。这样一来,就能计算给定的一个词 和词 的概率 (即,在已知词 出现的情况下,词 出现的概率), 其中 是中心词, 是窗口中非中心的外围词。
在word2vec中,这个条件概率分布是通过计算向量点积(dot-products),再应用naive-softmax函数得到的:
这里,向量代表外围词,向量代表中心词。为了包含这些向量,我们有两个矩阵 和 。 的列是外围词, 的列是中心词,这两矩阵都有所有词的表示 。
对于词 和词 ,损失函数为对数几率:
可以从交叉熵的角度看这个损失函数。真实值为 ,是一个独热向量,预测值 计算得到。具体来说, 如果是第k个单词,那么它的第k维为1,其余维都是0,而 的第k维表示这是第k个词的概率大小。
问题(a) (3分)
证明公式(2)给出的naive-softmax的损失函数,和
答:因为除了
问题(b) (5分)
计算损失函数
答:
问题(c) (5分)
计算损失函数
答:
问题(d) (3分)
sigmoid函数如公式所示
答:
计算雅克比矩阵可得
问题(e) (4分)
现在我们考虑负采样的损失函数。假设有K个负样本,表示为
完成计算后,简要解释为什么这个损失函数比naive-softmax效率更高。
注意:你可以用问题(d)的答案来帮助你计算导数
答:
原始的损失函数中需要求指数和,很容易溢出,负采样的损失函数能很好地规避这个问题。
词库从 𝑉𝑜𝑐𝑎𝑏 变成了K+1个词
在求内层导数的时候用了sigmoid函数
问题(f) (3分)
假设中心词是
计算:
损失函数对
的偏导数损失函数对
的偏导数损失函数对
的偏导数
$$
代码:实现word2vec(20分)
点击 此处 下载代码,python版本 >= 3.5,需要安装numpy,你利用conda来配置环境:
1 |
|
写完代码后,运行:
1 |
|
问题(a) (12分)
首先,实现 word2vec.py 里的 sigmoid函数,要支持向量输入。接着实现同一个文件里的 softmax 、负采样损失和导数。然后实现skip-gram的损失函数和导数。全部做完之后,运行python word2vec.py来检查是否正确。
答:
sigmoid
numpy具备广播特性,最终得到向量输出
1 |
|
naiveSoftmaxLossAndGradient
这个模型其实就是一个三层的前馈神经网络,只需要注意维度即可,注释里已经标记出了维度。
需要注意的是,单词表示是在行,而不是列。
1 |
|
negSamplingLossAndGradient
与native-softmax不同的是:
- 只选取K个非外围词作为负样本,加上1个正确的外围词,共K+1个输出
- 最后一层使用sigmoid输出,而不是softmax
注意,反向传播得到的是这K+1个词的梯度,所以需要挨个更新到 梯度矩阵 中去
1 |
|
skipgram
遍历所有的外围词,求和损失函数
1 |
|
问题(b) (4分)
完成sgd.py文件的SGD优化器,运行python sgd.py来检查是否正确。
答:
sgd
调用函数得到损失值和梯度,更新即可
1 |
|
问题(c) (4分)
至此所有的代码都写完了,接下来是下载数据集,这里我们使用Stanform Sentiment Treebank(SST)数据集,它可以用在简单的语义分析任务中去。通过运行 sh get_datasets.sh 可以获得该数据集,下载完成后运行 python run.py 即可。
注意:训练的时间取决于代码是否高效(即便是高效的实现,也要跑接近一个小时)
经过40,000次迭代后,最终结果会保存到 word_vectors.png 里。
答:
- 在上图中可以观察到,male->famale 和 king -> queen 这两条向量是平行的
- (women, famale),(enjoyable,annoying) 这些含义接近的词距离很近
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!