浅谈word embedding

1,694 阅读10分钟

这是我参与2022首次更文挑战的第16天,活动详情查看:2022首次更文挑战


1 Featurized representation: word embedding

1.1 从one-hot说起

 Man  Woman  King  Queen  Apple  Oran (5391)(9853)(4914)(7157)(456)(6257)[0000100][0000010][0001000][0000010][0100000][0000100]\begin{array}{cccccc} &\text { Man } & \text { Woman } & \text { King } & \text { Queen } & \text { Apple } & \text { Oran } \\ &(5391) & (9853) & (4914) & (7157) & (456) & \left(6257\right) \\ & \left[\begin{array}{c} 0 \\0 \\0 \\0 \\\vdots \\1 \\ \vdots \\0 \\ 0 \end{array}\right] & \left[\begin{array}{c} 0 \\0 \\0 \\0 \\0 \\ \vdots \\1 \\ \vdots \\0 \end{array}\right] & {\left[\begin{array}{c} 0 \\0 \\0 \\ \vdots \\1 \\ \vdots \\0 \\0 \\0 \end{array}\right]} & {\left[\begin{array}{c} 0 \\0 \\0 \\0 \\0 \\ \vdots \\ 1 \\ \vdots \\0 \end{array}\right]} & {\left[\begin{array}{c} 0 \\ \vdots \\1 \\ \vdots \\0 \\0 \\0 \\0 \\0 \end{array}\right]} & \left[\begin{array}{c} 0 \\0 \\0 \\0 \\ \vdots \\1 \\ \vdots \\0 \\0 \end{array}\right] \end{array}

之前简单的文本预处理都是使用one-hot向量来表示词汇表,简单来说就是将文本制作成一个词汇表。我们之前说的是假设那个词汇表的长度为1万,也就是说我们将会有1万个one-hot向量。每一个向量的长度是1万。将每个单词所在的位置标注为1,其余都为0。

比如以man为例。它在单词表中的位置是5391。那么第5391个one-hot向量O5391O_{5391}就表示man,并且这个向量的长度为1万,它的第5391位数字是1,其余的数字都是0。

但是使用one-hot向量存在一个问题就是说它的模型泛化能力会很差。举个例子:

I want a glass of orange ______ .

I want a glass of apple______ .

常人眼里如果你第一个空里边填上“juice”,那很便宜的,你第二个空也可以填“juice”。

但是如果你使用one-hot向量,模型不知道orange和apple是类似的东西。所以它并不能轻易的把apple后边也填上juice。

这就用到了word embedding,对特征进行表征。

1.2 词汇表征

简单来说就是提取词汇的一些特征对其进行打分。然后使用这些特征来表示某个词汇。比如我们上边用外号的项链表示的Man、Woman、King、Queen、Apple、Orange就可以转化为下边这个样子:

 Man (5391) Woman (9853) King (4914) Queen (7157) Apple (456) Orange (6257) Gender 110.950.970.000.01 Royal 0.010.020.930.950.010.00 Age 0.030.020.70.690.030.02 Food 0.040.010.020.010.950.97 ... ..................\begin{array}{c|cccccc} & \begin{array}{c} \text { Man } \\ (5391) \end{array} & \begin{array}{c} \text { Woman } \\ (9853) \end{array} & \begin{array}{c} \text { King } \\ (4914) \end{array} & \begin{array}{c} \text { Queen } \\ (7157) \end{array} & \begin{array}{c} \text { Apple } \\ (456) \end{array} & \begin{array}{c} \text { Orange } \\ (6257) \end{array} \\ \hline \text { Gender } & -1 & 1 & -0.95 & 0.97 & 0.00 & 0.01 \\ \text { Royal } & 0.01 & 0.02 & 0.93 & 0.95 & -0.01 & 0.00 \\ \text { Age } & 0.03 & 0.02 & 0.7 & 0.69 & 0.03 & -0.02 \\ \text { Food } & 0.04 & 0.01 & 0.02 & 0.01 & 0.95 & 0.97\\ \text { ... } & ... & ... & ... & ... & ... & ... \end{array}

在这里呢我们对每一个词汇进行word embedding,假设我们提取了300个特征,但是在上面的表格里我们只展示前4个。

还是以man为例。这里我们可以看到它和woman对比。他们俩的性别属性分别是-1和1。至于权力这一栏的打分只有0.01。对比king和queen来说更接近于0。毕竟man和woman两个单词来看是看不出来他们的权利的。自然这两个单词也看不出来年龄和食物等特征。所以打分都很接近于0。

经过word embedding处理之后,我们可以将其转化为word embedding的向量。man就从O5391O_{5391}变为e5391e_{5391}

使用了word embedding之后,我们可以正更直观的感受到词汇之间的相似度。

1.3 可视化

下面这张图呢就是word embedding的可视化。

挑选了几个单词,因为我们是提取了300个特征,所以我们将一个三维的空间映射到二维空间上,进行一个非线性的映射。最后将它们显示到这个图片上。我们可以清楚的看到意思相近的词它们分布的位置更接近。

image.png

2 如何使用word embedding

2.1 举个栗子

假设你现在使用“Sally Johnson is an orange farmer”这个句子进行命名实体识别(Named Entity recognition),对其中的人名进行识别。

image.png

可以看到正确的输出结果应该是在Sally Johnson那个位置输出的都是1,其余的部分输出都是0。因为可以识别出能橘子果农主语是人名。

轻易地,如果你换一个句子:“Robert Lin is an apple farmer”。

你的模型因为知道“orange”和“apple”之间是类似的词,所以可以很轻易的推测出“Robert Lin”也是人名。

假设你现在在测试集里遇到了一个不太常见的词“durian cultivator” 榴莲培育者。

“Robert Lin is an durian cultivator.”

甚至可能你的训练集里都没有出现这两个词。

如果你已经有一个学好的word embedding,那它就可以告诉你的模型,这个榴莲和苹果是差不多的东西,这个培育者和农民是差不多的东西。那你的模型依旧可以轻松地识别出Robert Lin可能是人名。

通过大量的无标签文本学习出来的word embedding,可以让你使用迁移学习来应用到你的只有少量标签的数据集中。

2.2 Transfer learning and word embeddings

  1. Learn word embeddings from large text corpus. (1-100B words) (Or download pre-trained embedding online.)
  2. Transfer embedding to new task with smaller training set. (say, 100k words)
  3. Optional: Continue to finetune the word embeddings with new data.

实际应用中分为三个步骤,word embedding、迁移、微调。有的甚至都不用微调。

3 特性

word embedding有一个有趣的特性,就是它能够帮助实现类比推理。

举个栗子

在这里我们依旧使用上一节用到的这个例子表格:

 Man (5391) Woman (9853) King (4914) Queen (7157) Apple (456) Orange (6257) Gender 110.950.970.000.01 Royal 0.010.020.930.950.010.00 Age 0.030.020.70.690.030.02 Food 0.040.010.020.010.950.97 ... ..................\begin{array}{c|cccccc} & \begin{array}{c} \text { Man } \\ (5391) \end{array} & \begin{array}{c} \text { Woman } \\ (9853) \end{array} & \begin{array}{c} \text { King } \\ (4914) \end{array} & \begin{array}{c} \text { Queen } \\ (7157) \end{array} & \begin{array}{c} \text { Apple } \\ (456) \end{array} & \begin{array}{c} \text { Orange } \\ (6257) \end{array} \\ \hline \text { Gender } & -1 & 1 & -0.95 & 0.97 & 0.00 & 0.01 \\ \text { Royal } & 0.01 & 0.02 & 0.93 & 0.95 & -0.01 & 0.00 \\ \text { Age } & 0.03 & 0.02 & 0.7 & 0.69 & 0.03 & -0.02 \\ \text { Food } & 0.04 & 0.01 & 0.02 & 0.01 & 0.95 & 0.97\\ \text { ... } & ... & ... & ... & ... & ... & ... \end{array}
  • 现在我们提出一个问题:

    man对应于woman。那么king应该对应于什么?

  • 讲道理我们应该知道答案:

    Queen

使用word embedding就可以实现自动的推理。

上一节我们说的是提取了300个特征,在这里我们依旧只用前4个特征。

  • Man:
e5391=[10.010.030.09]e_{5391} = \left[\begin{array}{c}-1\\0.01\\0.03\\0.09 \end{array}\right]
  • Woman:
e9853=[10.020.020.01]e_{9853} = \left[\begin{array}{c}1\\0.02\\0.02\\0.01 \end{array}\right]
  • King:
e4914=[0.950.930.700.02]e_{4914}= \left[\begin{array}{c}-0.95\\0.93\\0.70\\0.02 \end{array}\right]
  • Queen:
e7157=[0.970.950.690.01]e_{7157}= \left[\begin{array}{c}0.97\\0.95\\0.69\\0.01 \end{array}\right]

现在对其做减法我们可以发现一个有趣的事情:

emanewoman=e5391e9853=[10.010.030.09][10.020.020.01][2000]e_{man}-e_{woman} = e_{5391}-e_{9853} = \left[\begin{array}{c}-1\\0.01\\0.03\\0.09 \end{array}\right] - \left[\begin{array}{c}1\\0.02\\0.02\\0.01 \end{array}\right] \approx \left[\begin{array}{c} -2 \\0\\0\\0 \end{array}\right]

同样:

ekingequeen=e4914e7157=[0.950.930.700.02][0.970.950.690.01][2000]e_{king}-e_{queen} = e_{4914}-e_{7157} = \left[\begin{array}{c}-0.95\\0.93\\0.70\\0.02 \end{array}\right] -\left[\begin{array}{c}0.97\\0.95\\0.69\\0.01 \end{array}\right] \approx \left[\begin{array}{c} -2 \\0\\0\\0 \end{array}\right]

此外:

eappleeorange=e456e6257=[0.000.010.030.95][0.010.000.020.97][0000]e_{apple}-e_{orange} = e_{456}-e_{6257} = \left[\begin{array}{c}0.00\\-0.01\\0.03\\0.95 \end{array}\right] -\left[\begin{array}{c}0.01\\0.00\\-0.02\\0.97 \end{array}\right] \approx \left[\begin{array}{c} 0 \\0\\0\\0 \end{array}\right]

从上面这个三个式子中我们可以得出man 和woman的主要区别在性(gender)这一项上。King和queen的区别也主要是在性别这一项上。在这4个特征上都没有什么区别。因为他们无所谓性别、权利、年龄,并且他们都是食物。

算法

“man对应于woman。那么king应该对应于什么?”

对于上面这个问题,我们如何将其应用到算法之中呢。

emanewomanekinge?e_{man}-e_{woman} \approx e_{king}-e_{?}

回到我们下面这张图里:

image.png

还记得我们之前说的是抽取了300个特征。然后将这300个特征通过非线性映射映射到二维平面图上。 image.png

上一小部分做了两个计算,有man减woman,用king减queen。他们的计算结果都是第一维度上是2,其他维度都是0。可视化之后就是上图这个样子。

我们要做的计算就是:

emanewoman+ekinge?e_{man}-e_{woman} + e_{king}\approx e_{?}

argmaxsim(emanewoman+eking,e?)argmax \quad sim(e_{man}-e_{woman} + e_{king}, e_{?})

补充!

我们是使用t-SNE算法加300维的向量映射到二维平面上。该步骤进行的是一个非线性映射。所以我们要知道。因为属性差异而造成的区别在图片上显示向量方向是一样的,比如man和woman 、king 和queen。但是如果在图片上。向量箭头的方向是一样的,并不能代表它们两个的差异属性是一样的。比如one和three,他们不是一男一女。

image.png

常用相似度函数

argmaxsim(emanewoman+eking,e?)argmax \quad sim(e_{man}-e_{woman} + e_{king}, e_{?})

前面说了我们最终要计算的是这个公式,那我们要使用哪个相似度函数呢。

对这个的计算我们一般是用余弦相似度或者使用欧式距离。

余弦相似度:

sin(u,v)=uvu2v2\sin (u, v)=\frac{u^{\top} v}{\|u\|_{2}\|v\|_{2}}

欧式距离:

sin(u,v)=uv2\sin (u, v)=\|u-v\|^{2}

在不同的空间上。度量。计算的方法是不同的。在这里我们比较常用这两种。

4 Embedding matrix

4.1 什么是Embedding matrix

在模型学习的过程中,其实是将one-hot的那一堆向量转换成了一个词嵌入的矩阵。将输入层中的每个词分别映射至一个低维、稠密的实值特征矩阵中。也就是说你最终得到的应该是一个word embedding的矩阵,而不是每一个词汇的embedding向量。

还是接续我们前面的例子,假设你的词典长度是1万。现在你做word embedding选择300个特征。

如下图,那你最后得到的应该是一个300×10000维度的矩阵EE

image.png

我们称这个矩阵为word embedding的大矩阵EE

 Man (5391) Woman (9853) Gender 11 Royal 0.010.02 Age 0.030.02 Food 0.040.01 ... ......\begin{array}{c|cccccc} & \begin{array}{c} \text { Man } \\ (5391) \end{array} &\begin{array}{c} \text { Woman } \\ (9853) \end{array} \\ \hline \text { Gender } & -1 & 1 \\ \text { Royal } & 0.01 & 0.02 \\ \text { Age } & 0.03 & 0.02 \\ \text { Food } & 0.04 & 0.01\\ \text { ... } & ... & ... \end{array}

对应表格看第5391位是man,在embedding矩阵中也是位于5391列。

4.2 从Embedding matrix中获取单词的词嵌入向量

4.2.1 方法一

在one-hot向量中,向量的长度为单词表的长度。向量中该单词在字母表中的位置为1,其余的数字都为0。

所以想要获取。某一个单词的word embedding向量,我们只需要将one-hot的向量乘以我们的word embedding的矩阵即可。

公式如下:

[E]300×10000×[o5391]10000×1=[e5391]300×1[E]_{300\times10000} \times [o_{5391}]_{10000 \times 1} = [e_{5391}]_{300 \times 1}

这样我们就可以取到对应位置上的那个单词的e向量。

我们来举个简单的例子。

[100010001]×[100]=[100]\begin{bmatrix} 1 &0 &0 \\ 0 &1 &0 \\ 0 &0 &1 \end{bmatrix} \times \begin{bmatrix} 1 \\ 0 \\ 0 \end{bmatrix} = \begin{bmatrix} 1 \\ 0 \\ 0 \end{bmatrix}

4.2.2 方法二

上面那个理论上讲方法是通的,但是实际应用中并不那么用。

实际应用中一般是使用一个词向量层。词向量层也可以理解为一个查找表(Look-up Table),获取词向量的过程,也就是根据词的索引从查找表中找出对应位置的向量的过程。也就是使用某些特定的检索方法来直接在word embedding中进行查找,找到对应位置的向量即可。

实际操作中你绝对不会使用一个10000长度的word embedding,因为确实有点短。所以说你接触到的应该是一个非常大的矩阵。如果一个大矩阵在乘以一个超级长的one-hot的向量进行相乘的话,它的计算开销是非常大的。


4.3 如何得到词嵌入矩阵EE

前面我们讲了word embedding。但是如何才能学习得到呢?

实践证明,建立语言模型是学习word embedding的好方法1


下面我们就建立语言模型来尝试一下如何进行句子预测填充。从中学习一下如何使用神经网络学习得到word embedding矩阵。

Iwantaglassoforange.434396651385261635257I \quad want \quad a\quad glass\quad of\quad orange\quad \underline{\quad\quad\quad\quad\quad}. \\\quad \\ 4343 \quad 9665 \quad 1 \quad 3852 \quad 6163 \quad 5257\quad\quad\quad\quad\quad\quad\quad\quad

进行句子预测。我们现在把已经有的这个句子每个单词都标上了序号。

 I o4343Ee4343 want o9665Ee9665 a o1Ee1 glass o3852Ee3852 of o6163Ee6163 orange o6257Ee6257\begin{array}{llllll} \text { I } & o_{4343} & \longrightarrow & E & \longrightarrow & e_{4343} \\ \text { want } & o_{9665} & \longrightarrow & E &\longrightarrow & e_{9665} \\ \text { a } & o_{1} & \longrightarrow & E& \longrightarrow & e_{1} \\ \text { glass } & o_{3852} & \longrightarrow & E& \longrightarrow & e_{3852} \\ \text { of } & o_{6163} & \longrightarrow & E& \longrightarrow & e_{6163}\\ \text { orange } & o_{6257} & \longrightarrow & E & \longrightarrow & e_{6257}\\ \end{array}

我们由one-hot向量oo学习得到word embedding矩阵EE,再通过word embedding矩阵和one-hot向量相乘。得到对应单词的word embedding向量ee

我们将得到的embedding向量放入到神经网络语言模型当中。再经过一个softmax层。然后这个softmax层会在你的单词表中找到一个最为可信的答案作为输出。

image.png

现在分析一下其中的维度。

  • [o]10000×1[o]_{10000\times 1}

  • [E]300×10000[E]_{300\times 10000}

  • [e]300×1[e]_{300\times 1}

  • [h]6300×1[h]_{6*300 \times 1}

    h是经过神经网络拼接处理的,就是要预测句子的第七个单词,把句子的前六个单词拼接起来放入神经网络进行处理。

就是在实际操作的过程中,由于句子的长度不同,所以并不是每次把前面的所有内容都拼接起来。而是选择一个大小窗口来进行滑动预测。

比如设置只考虑前面4个单词。那么到了神经网络计算的这一步,H就会变为长度1200。而不是1800。

image.png

就这样使用神经网络对其进行训练。在算法的激励下,你的网络会不断进行数据调整。最终Orange、Apple、Durian、Strawberry、Watermelon短单词都会学到相近的特征值。

这就是学习获得word embedding矩阵EE的方法之一。

这说明这个例子中我们使用的窗口是选取前4个单词。也有其他选取上下文的方式,比如空缺周围的几个单词、空缺之后的几个单词。

适应的是一种skip-gram的模型思想,之后我们会再做详细介绍。


  1. Neural Probabilistic Language Models | SpringerLink