前言
本课程由Christopher Manning, Richard Socher 领衔主讲
Stanford课程主页:http://web.stanford.edu/class/cs224n/
中英双语字幕网课链接:http://www.mooc.ai/course/494
从词义说起
用分类资源(taxonomic resources),例如WordNet来处理词义。
什么是WordNet?
WordNet是普林斯顿大学认知科学实验室与计算机系联合开发的一个英语词库,收录了超过十万个实词。
在WordNet中,意义相近的单词组成一个同义词组(Synset),而同义词组之间则以上-下义,同义-反义,整体-部分以及蕴含等语义关系连接在一起,构成一个由同义词组作为结点,语义关系作为边的网状结构。
from nltk.corpus import wordnet as wn
panda = wn.synset('panda.n.01')
hyper = lambda s : s.hypernyms()
list(panda.closure(hyper))
P.S. 如果以上代码不能成功跑出来需要重新安装nltk库:https://blog.csdn.net/gggggertie/article/details/80148765
以上代码执行后的结果为:
[Synset('procyonid.n.01'), Synset('carnivore.n.01'), Synset('placental.n.01'),
Synset('mammal.n.01'), Synset('vertebrate.n.01'), Synset('chordate.n.01'),
Synset('animal.n.01'), Synset('organism.n.01'), Synset('living_thing.n.01'),
Synset('whole.n.02'), Synset('object.n.01'), Synset('physical_entity.n.01'),
Synset('entity.n.01')]
更加详细的wordnet使用方法可参照:https://blog.csdn.net/King_John/article/details/80252594
WordNet的缺点
- 会忽略其中微小的差别(e.g. good, expert是同义词,但存在差别)
- 没有更新新的词汇进去
- 主观的
- 需要人力去维护
- 很难计算词汇的相似度
存在的问题
涵盖的范围
传统NLP(几乎所有,除了现代深度学习和80年代的神经网络)
现象
用原子符号(atomic symbols)来表示单词,即用one-hot向量(独热编码)来表示。it is a localist representation.
问题
- 维度会非常大;
- 没有表示出词汇间的内在联系(did not give any inherent notion of similarity),这存在于传统机器学习算法中
解决方法:分布相似性
构造能够表示单词含义的向量,那么单词向量之间点乘的结果就是两个单词的相似度(similarity)
分布相似性(distributional similarity)的定义
是关于语义的概念,即可以通过单词出现的上下文来描述词汇的意思。
e.g. 通过找到’banking’的例句,我们可以得到’banking’常出现的上下文,得到经常和它一起出现的’governments’, ‘debt problems’, ‘regulations’, ‘Europe’,这样我们就可以用这些词来表示单词’banking’的含义。
通过为每一个单词构造出一个密集向量,我们可以预测这个单词出现的上下文。
Word2vec
词嵌入模型
词嵌入模型(word embedding model): 用中心词汇预测它上下文的词汇,或预测给定单词的上下文单词出现的概率。
损失函数J可以用来计算出预测的准确率, 其中
W
t
W_t
Wt表示中心词汇t,
W
−
t
W_{-t}
W−t表示围绕在t中心词周围的其他词汇。训练模型的目标就是要最小化损失函数。
词汇的向量表示的概念在1986年被第一次提出,但没有被重视。
相关论文:
• 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)
主要内容
Word2vec是Google在2013年推出的NLP工具,主要用途是预测每一个单词和它上下文的词汇(predict between every word and its context words)。
基础算法之一:Skip-grams(SG)
概念:在每一个估算的步骤中取一个词作为中心词汇,尝试预测它在一定窗口大小(window size)下的上下文单词。这个模型将定义一个概率分布——以这个词为中心词汇的情况下,某个单词在它上下文出现的概率;训练模型的过程就是选取词汇的向量表示来让概率分布值最大化。对一个词汇,只有一个概率分布。
目标函数:
J
′
(
θ
)
=
∏
t
=
1
T
∏
−
m
≤
j
≤
m
,
j
≠
0
P
(
W
t
+
j
∣
W
t
)
J'(\theta) = \prod_{t=1}^{T}\prod_{-m\le j \le m,j \ne 0}P(W_{t+j} \mid W_t)
J′(θ)=t=1∏T−m≤j≤m,j̸=0∏P(Wt+j∣Wt)
为了方便计算,将求积转化为求和,也就是对该函数进行取对数的计算,可以得到负的对数似然,即模型的负对数分布:
J
(
θ
)
=
−
1
T
∑
t
=
1
T
∑
−
m
≤
j
≤
m
,
j
≠
0
log
p
(
W
t
+
j
∣
W
t
)
J(\theta) = -\frac{1}{T} \sum^T_{t=1} \sum_{-m\le j \le m,j \ne 0}\log {p(W_{t+j} \mid W_t)}
J(θ)=−T1t=1∑T−m≤j≤m,j̸=0∑logp(Wt+j∣Wt)
在这里,
θ
\theta
θ指的是词汇的向量表示,也是每个词汇向量表示的唯一参数;这里的
1
T
\frac{1}{T}
T1 相当于对每一个词汇进行归一化处理,避免计算整个语料库的概率;-是为了将最大化转为最小化,如果你喜欢最大化,你也可以不加。
P.S. 来自prof: 几个超参,例如窗口大小、容差系数都是可以调试的,但现在我们先将它当作常数。
Softmax概率分布:
p
(
o
∣
c
)
=
e
x
p
(
u
o
T
v
c
)
∑
w
=
1
v
e
x
p
(
u
w
T
v
c
)
p(o \mid c) = \frac{exp({u_o}^T v_c)}{\sum_{w=1}^{v} exp({u_w}^Tv_c)}
p(o∣c)=∑w=1vexp(uwTvc)exp(uoTvc)
c和o都代表单词在词汇表空间中的索引,
u
o
u_o
uo和
v
c
v_c
vc是向量。
由于
u
T
v
=
u
⋅
v
=
∑
i
=
1
n
u
i
v
i
u^Tv=u\cdot v=\sum_{i=1}^n u_iv_i
uTv=u⋅v=∑i=1nuivi,所以有:
p
i
=
e
u
i
∑
j
e
u
j
p_i=\frac{e^{u_i}}{\sum_je^{u_j}}
pi=∑jeujeui
每一个单词都有两个向量表示,作为中心词汇时和作为上下文词汇时,两个互相独立,互不影响。
接下来是教授的一张抽象的SG完全解析图:
训练模型
我们将模型的所有参数(即所有单词的两种向量表示)的集合定义为
θ
\theta
θ:
然后,我们用梯度下降法来训练,求梯度的过程:
对
log
p
(
o
∣
c
)
=
log
e
x
p
(
u
o
T
v
c
)
∑
w
=
1
v
e
x
p
(
u
w
T
v
c
)
\log p(o \mid c) = \log \frac{exp({u_o}^T v_c)}{\sum_{w=1}^{v} exp({u_w}^Tv_c)}
logp(o∣c)=log∑w=1vexp(uwTvc)exp(uoTvc)求偏导,有:
∂
∂
v
c
log
e
x
p
(
u
o
T
v
c
)
⎵
(
1
)
−
log
∑
w
=
1
v
e
x
p
(
u
w
T
v
c
)
⎵
(
2
)
\frac{\partial}{\partial v_c}\underbrace{\log exp({u_o}^Tv_c)}_{(1)}-\underbrace{\log \sum_{w=1}^vexp({u_w}^Tv_c)}_{(2)}
∂vc∂(1)
logexp(uoTvc)−(2)
logw=1∑vexp(uwTvc)
拆分成两部分求解:
(
1
)
=
∂
∂
v
c
u
o
T
v
c
=
u
o
(1) = \frac{\partial}{\partial v_c} {u_o}^Tv_c = u_o
(1)=∂vc∂uoTvc=uo
第二部分运用链式法则:
终于来到了优化,这里用的是梯度下降法:
首先full-batch的:
所以写成代码,也就是:
while True:
theta_grad = evaluate_gradient(J,corpus,theta)
theta = theta - alpha * theta_grad
这里注意 alpha 的取值,太大容易错过最小值
为了减少训练时间,一般采用随机梯度下降(SGD),先进行采样,粗略估计梯度,这样能快上几个数量级:
while True:
window = sample_window(corpus)
theta_grad = evaluate_gradient(J,window,theta)
theta = theta - alpha * theta_grad
后续还有关于CBOW的讲解,在Lecture 03.