[译] Pytorch 官方教程 词嵌入:编码词语与语义
WORD EMBEDDINGS: ENCODING LEXICAL SEMANTICS
词嵌入指的是:将用户词表中每一个单词与一个实数对应,并嵌入到一个密度向量中。在自然语言处理中,绝大多数情况研究的特征都是单词。然而,应该怎样在计算机中表示一个单词呢?一种方案是存储单词每个字母对应的ascii码,但这只能让我们知道我们存储的这个单词由哪些字母组成,并不能表达这个单词具体的含义(或许能从词缀推断出词性、从大小写推断出属性,但这远远不够)。而且,凭什么可以将这些表示组合在一起?
我们设计的神经网络往往是$|V|$(词汇表的长度)维的,但是却需要从神经网络中得到低维、密集的输出(譬如需要预测的标签只有几个),我们要怎样从将数据从高维空间转移到低维空间呢?
不妨试试用one-hot编码来代替ascii码?即,对某个单词w,按以下方式表示:
$$
\overbrace{\left[ 0, 0, \dots, 1, \dots, 0, 0 \right]}^\text{|V| elements}
$$
其中,每个单词都只含有1个’1’(剩余为0),而且每个单词的’1’的位置都不同。
上述方法不仅占用了巨量的空间,而且还有一个致命的弊端:这种方法将每个单词标记为独立的实体,认为他们之间没有关联。
我们真正想要的,是使用一些标记方法,来标记词与词之间的相似关系
。难以理解?且看以下示例。
假设我们正在建立一个语言模型,假设有以下语句:
- The mathematician ran to the store.
- The physicist ran to the store.
- The mathematician solved the open problem.
在我们的训练数据中。
现在,我们读取到了一个在训练数据中从未见过的语句:
- The physicist solved the open problem.
我们的语言模型在这一语句上也许能表现不错,但如果能够将以下两个事实也考虑进去,相信将会更好:
- 我们在训练语句中,发现mathematician以及physicist在句中是相同的成分,换句话说,他们有着一定的语义关系。
- 在新语句中,虽然看到的是physicist,但是我们认为mathematician在句中的成分是和physicist一致的。
由此,推断出physicist在新语句中的拟合度很好。
这正是上述标记词与词之间的相似关系
的真实含义:相似关系指的是语义上的相似,而不是指字符拼写上相似。
这一技术在训练数据和未知的数据之间建立了联系,能有效克服语言学(文本)数据的稀疏性。当然,这基于一个基本假设:出现在相似上下文之中的单词在语义上相关。这也被称为分布式假设。
稠密词嵌入
Getting Dense Word Embeddings
如何获得词嵌入呢?换句话说,我们具体要如何将语义的相似性进行编码?
或许我们可以考虑一些语义属性。例如,is able to run
属性:mathematicians 和 physicists 都能 “run”,因此二者在该属性上都标记为高分。再考虑一些属性,并且为这些属性对不同的单词进行打分。
如果将每个属性视为一个维度,那么我们能将每个单词表示为一个向量(词嵌入向量):
$$
q_\text{mathematician} = \left[ \overbrace{2.3}^\text{can run}, \overbrace{9.4}^\text{likes coffee}, \overbrace{-5.5}^\text{majored in Physics}, \dots \right]
$$
$$
q_\text{physicist} = \left[ \overbrace{2.5}^\text{can run},
\overbrace{9.1}^\text{likes coffee}, \overbrace{6.4}^\text{majored in Physics}, \dots \right]
$$
由此,我们得到了度量单词相似性的一个方法:
$$
\text{Similarity}(\text{physicist}, \text{mathematician}) = q_\text{physicist} \cdot q_\text{mathematician}
$$
按照向量长度标准化后:
$$
\text{Similarity}(\text{physicist}, \text{mathematician}) = \frac{q_\text{physicist} \cdot q_\text{mathematician}}
{| q_\text{physicist} | | q_\text{mathematician} |} = \cos (\phi)
$$
其中,$\phi$ 标记两个向量的夹角。这样一来,极度相似的单词(他们的词嵌入向量指向几乎相同的方向)的similarity值为1,极度不相似的单词(他们的词嵌入向量指向几乎相反的方向)的similarity值为-1,
现在回顾one-hot编码,可以将其看成词嵌入向量的一种特殊情况,每个单词的相似度为0,且为每个单词单独分配了一个唯一的语义属性。
同时,我们称新定义的向量是稠密的,也就是说这些向量的元素绝大多数不为0。
然而, 这些新定义的向量有一个大问题:我们能为相似性的度量,定义成千上万个不同的语义属性,那么到底如何为不同的属性打分呢?
深度学习的核心思想是使计算机利用神经网络自动学习特征的含义,而不是需要程序员来手动设计。那么,为何不将词嵌入作为模型参数,让词嵌入在训练过程中自动更新迭代呢?
这正是我们要做的:我们将设计一些神经网络在原则上能够进行学习的潜在语义属性
。注意,词嵌入可能是难以解释甚至不可解释的。也就是说,虽然在上述例子中,我们能通过手工标记的方法知道mathematicians以及physicists都喜欢咖啡,但是如果我们用一个神经网络去学习这些词嵌入,并且发现mathematicians以及physicists的词嵌入在某个维度上都有着很高的分数,我们也不清楚这个维度到底意味着什么(即不明该维度的语义)。他们在潜在语义属性上相似,但这对我们来说不可解释。
总而言之,词嵌入表示的是单词语义,能够高效地编码与手头任务相关的语义信息。除了语义信息,还能够嵌入其他的信息:词性标签、语义分析树、甚至任意信息!特征嵌入的思想是这一领域的核心。
Pytorch中的词嵌入
Word Embeddings in Pytorch
(部分内容已省略)
在定义词嵌入时,我们需要为每一个单词定义一个索引,这些索引将会成为一个查询表中的键值。
换句话说,词嵌入将被存储为一个$|V|×D $的矩阵,D为词嵌入的维度。我们为某一单词定义的索引i即表示该单词在词嵌入矩阵中的第i行
。下文中,从单词到其索引的映射将被命名为 word_to_ix
。
Pytorch中为词嵌入提供服务的模块是 torch.nn.Embedding
,torch.nn.Embedding
接受两个参数:词汇表长度、词嵌入维度
。
1 | # Author: Robert Guthrie |
1 | word_to_ix = {"hello": 0, "world": 1} |
Out:
tensor([[ 0.6614, 0.2669, 0.0617, 0.6213, -0.4519]],
grad_fn=)
示例:N-Gram 语言模型
An Example: N-Gram Language Modeling
回顾n-gram模型,给定一个单词序列 w,我们需要计算:
$$
P(w_i | w_{i-1}, w_{i-2}, \dots, w_{i-n+1} )
$$
其中 $w_i$ 是w中的第i个单词。
在本例中,我们将计算一些训练样本的损失函数
然后使用反向传播来更新模型参数
。
1 | CONTEXT_SIZE = 2 |
Out:
[([‘When’, ‘forty’], ‘winters’), ([‘forty’, ‘winters’], ‘shall’), ([‘winters’, ‘shall’], ‘besiege’)]
1 | vocab = set(test_sentence) |
Out:
[518.5035681724548, 516.1092879772186, 513.7281634807587, 511.3589131832123, 509.00272035598755, 506.6583275794983, 504.32336044311523, 501.9988875389099, 499.68528985977173, 497.3804793357849]
练习:计算词嵌入:连续词袋模型
Exercise: Computing Word Embeddings: Continuous Bag-of-Words
连续词袋模型(CBOW)是自然语言处理中非常常用的一种语言模型。CBOW通过参考目标单词上下文几个单词来对目标单词进行预测。与语言建模不同的是,CBOW并非顺序模型,也不必一定是概率化的。CBOW通常被用来快速训练词嵌入,并且用这些训练得到的词嵌入来初始化那些更为复杂的词嵌入模型,通常这一过程也被称为预训练词嵌入。CBOW绝大多数情况下能够使模型表现提升数个百分点。
以下定义CBOW模型:
给定目标单词 $w_i$ 以及左右两边大小为 N 的上下文窗口:$w_{i-1},\dots, w_{i-N}$ 和 $w_{i+1},\dots, w_{i+N}$,将上述这些上下文单词记做 $c$ ,CBOW模型尝试最小化以下内容:
$$
-\log p(w_i | C) = -\log \text{Softmax}(A(\sum_{w \in C} q_w) + b)
$$
其中,$q_w$是单词w的词嵌入。
使用Pytorch,完善下面的类,实现这一模型。
提示:
- 考虑需要定义哪些参数/变量
- 明确每步操作要求的形状,需要变换张量形状时,使用
.view()
方法
1 | CONTEXT_SIZE = 2 # 2 words to the left, 2 to the right(考虑目标单词左右2个单词) |
Out:
[([‘We’, ‘are’, ‘to’, ‘study’], ‘about’), ([‘are’, ‘about’, ‘study’, ‘the’], ‘to’), ([‘about’, ‘to’, ‘the’, ‘idea’], ‘study’), ([‘to’, ‘study’, ‘idea’, ‘of’], ‘the’), ([‘study’, ‘the’, ‘of’, ‘a’], ‘idea’)]
1 | class CBOW(nn.Module): |
该练习答案后续更新。
[Translation] 2020/4 Karl