stablediffusion Embeddings是什么放那里_word2vec


我发现embeddings是机器学习中最有趣的概念之一。如果你曾经使用过Siri、谷歌助手、Alexa、谷歌翻译,甚至是下一个带有单词预测功能的智能手机键盘,那么你很可能已经从这个已经成为自然语言处理模型核心的想法中受益了。在过去的几十年里,在神经模型中使用embeddings已经有了相当大的发展,譬如最近发展的BERT和GPT2这样的考虑了上下文环境的词嵌入( word embeddings)模型。

Word2vec是一种高效创建词嵌入的方法,从2013年开始使用。但是,除了作为单词嵌入方法的实用功能之外,它的一些概念已经被证明在创建推荐引擎和理解数据方面是有效的,甚至在商业、非语言任务中也是如此。Airbnb、阿里巴巴(Alibaba)、Spotify和Anghami等公司都受益于此,并将其用于生产,以支持新的推荐引擎。

在这篇文章中,我们将讨论嵌入的概念,以及使用word2vec生成嵌入的机制。但是让我们从一个例子开始来熟悉使用向量来表示事物。你知道一个包含五个数字(一个向量)的列表可以代表你的性格吗?

Personality Embeddings: What are you like?(性格嵌入:你是一个什么样的人)

stablediffusion Embeddings是什么放那里_语言模型_02


想象一下,我的内向/外向分数是38/100。我们可以这样画:

stablediffusion Embeddings是什么放那里_word2vec_03


我们把范围调整到-1到1之间:

stablediffusion Embeddings是什么放那里_滑动窗口_04


只从这一条信息你能够知道这个人的性格吗?并不会。人是复杂的。让我们再增加一个维度——测试一个人的另一个特征的分数。

stablediffusion Embeddings是什么放那里_滑动窗口_05


我已经隐藏了我们正在绘制的性格特征,这样你就会习惯于不知道每个维度代表什么——但仍然可以从一个人的性格向量表示中获得很多价值。现在我们可以说这个向量部分代表了我的人格。当你想把另外两个人和我做比较时,这种表现的有用之处就来了。比如我被一辆公交车撞了,我需要一个性格相似的人来代替我。在下面的图中,这两个人中谁更像我?

stablediffusion Embeddings是什么放那里_word2vec_06


在处理向量时,计算相似度分数的常用方法是 cosine_similarity

stablediffusion Embeddings是什么放那里_滑动窗口_07


然而,两个维度并不足以捕捉到足够的关于不同人的信息。几十年的心理学研究得出了五大特征(以及大量的子特征)。所以让我们用这五个维度来进行比较:

stablediffusion Embeddings是什么放那里_word2vec_08


五维的问题使得我们失去了在二维空间中画整齐的小箭头的能力。这是机器学习中一个常见的挑战,我们经常不得不在高维空间中思考。好在cosine_similarity仍然有效。它适用于任何数量的维度:

stablediffusion Embeddings是什么放那里_word2vec_09


在这一节的最后,我们提出两个中心思想:

  1. 我们可以将人(和事物)表示为数字的向量(这对机器来说很好!)
  2. 我们可以很容易地计算出向量之间的相似程度。

Word Embeddings(词嵌入)

有了这样的理解,我们可以继续查看训练好的词向量示例(也称为词嵌入),并开始查看它们的一些有趣属性。

这是一个嵌入词“King”(GloVe 基于维基百科训练):

stablediffusion Embeddings是什么放那里_语言模型_10


它是一个50个数的列表。我们不能通过观察这些值来得出什么结论。但是让我们把它形象化一点这样我们就可以其他的向量比较了。让我们把所有这些数字放在一行:

stablediffusion Embeddings是什么放那里_语言模型_11


让我们根据单元格的值对它们进行颜色编码(接近2的单元格为红色,接近0的单元格为白色,接近-2的单元格为蓝色):

stablediffusion Embeddings是什么放那里_语言模型_12


我们将继续忽略这些数字,只查看表示单元格值的颜色。现在让我们对比一下King和其他单词:

stablediffusion Embeddings是什么放那里_数据集_13


看看“Man”和“Woman”是如何比“king”更相似的?这说明了一些事情。这些向量表示形式捕获了相当多的这些单词的信息/语义/关联。

下面是另一个例子列表(通过垂直扫描列来寻找具有相似颜色的列进行比较):

stablediffusion Embeddings是什么放那里_语言模型_14


其中,有几件事需要指出:

  1. 所有这些不同的单词中间都有一个红色的直柱。它们在那个维度上是相似的(但我们并不知道每个维度代表什么)
  2. 你可以看到“woman”和“girl”在很多地方都很相似。" man “和” boy "也是一样
  3. “boy”和“girl”也有相似之处,但不同于“woman”或“man”。这些可能是对青春模糊概念的编码吗?答案是可能的。
  4. 除了最后一个字,其余的字都是表示人的字。我添加了一个对象(water)来显示类别之间的差异。例如,您可以看到蓝色的列一直向下,并在嵌入“water”之前停止。
  5. 在某些地方,“king”和“queen”彼此相似,却又截然不同。这些可能是对于皇室这一概念的模糊编码吗?

Analogies( 类比)

一个著名的例子展示了嵌入的一个令人难以置信的特性,那就是类比的概念。我们可以用词嵌入向量进行加法和减法,并得出有趣的结果。最著名的例子是公式:“king”-“man”+“woman”:

stablediffusion Embeddings是什么放那里_word2vec_15


我们可以像我们之前做的那样可视化这个类比:

stablediffusion Embeddings是什么放那里_数据集_16


但是在我们学习word2vec之前,我们需要先看看词嵌入的概念基础:神经语言模型。

Language Modeling(语言模型)

如果你想举一个NLP应用程序的例子,最好的例子之一就是智能手机键盘的下一个单词预测功能。这是一个数十亿人每天使用数百次的功能。

stablediffusion Embeddings是什么放那里_语言模型_17


下一个单词预测是一个可以通过语言模型来解决的任务。语言模型可以获取单词列表(假设有两个单词),并尝试预测紧随其后的单词。

在上面的屏幕截图中,我们可以把这个模型看作是接受了这两个绿色单词(thou shalt)并返回了一个建议列表(“not”是可能性最大的一个)的模型:

stablediffusion Embeddings是什么放那里_语言模型_18


我们可以把这个模型想象成这个黑盒子:

stablediffusion Embeddings是什么放那里_数据集_19


但实际上,该模型并不只输出一个单词。它实际上输出它所知道的所有单词的概率分数(模型的“vocabulary”,范围从几千到100多万单词)。然后,键盘应用程序必须找到得分最高的单词,并将它们呈现给用户。

stablediffusion Embeddings是什么放那里_word2vec_20


经过训练后,早期的神经语言模型(Bengio 2003)计算出一个预测分为三个步骤:

stablediffusion Embeddings是什么放那里_word2vec_21


当我们讨论embeddings时,第一步对我们来说是最相关的。训练过程的结果之一是这个矩阵包含了我们词汇表中每个单词的embeddings。在预测的时候,我们只需要查找输入词的embeddings,然后用它们来计算预测:

stablediffusion Embeddings是什么放那里_滑动窗口_22


现在让我们转到training过程来学习更多关于这个embedding矩阵是如何开发出来的。

Language Model Training(语言模型训练)

训练他们(前提是我们有大量的文本)。可以考虑我们身边的所有书籍、文章、维基百科的内容和其他形式的文本数据。相比其他需要许多手工制作的特征和专门收集的数据的机器学习模型有所不同。
词嵌入是通过观察接下来可能会出现哪些词语来得到。它的原理是这样的:

  1. 我们获得了大量的文本数据(例如,所有Wikipedia文章)。然后
  2. 我们有一个窗口(比如说,三个单词),我们可以滑动它来查看所有的文本。
  3. 通过滑动窗口来为我们的模型生成训练样本

    当这个窗口在文本上滑动时,我们(实际上)生成一个用于训练模型的数据集。让我们看看滑动窗口如何处理这个短语:
    当我们开始时,窗口在句子的前三个单词上:

    我们把前两个词作为特征,第三个词作为标签:

    然后我们滑动窗口到下一个位置,创建第二个样本:

    很快,我们就有了一个更大的数据集,其中的单词往往出现在不同的单词对之后:

look-both-ways

预言你在之前的文章中所了解的,请在下面的空白处填上:

stablediffusion Embeddings是什么放那里_滑动窗口_23


我在这里给出的上下文是空白单词之前的五个单词(以及前面提到的“bus”)。我相信大多数人会猜“bus”这个词。但如果我再给你一条信息——在空格后加一个词,你的答案会改变吗?

stablediffusion Embeddings是什么放那里_word2vec_24


这完全改变了空白处应该填什么单词。我猜测大多数人会认为“red”这个词现最容易出现在空白处。我们从中学到的是,特定单词前后的单词都有信息价值。事实证明,同时考虑两个方向(我们猜测的单词的左边和右边的单词)可以得到更好的单词嵌入。让我们看看如何调整我们训练模型的方式来考虑这一点。

Skipgram

不仅仅是只看目标词之前的两个词,我们也可以看它之后的两个词。

stablediffusion Embeddings是什么放那里_word2vec_25


如果我们这样做,我们实际building和训练模型的数据集将是这样的:

stablediffusion Embeddings是什么放那里_数据集_26


这在word2vec模型中被叫做Continuous Bag of Words。

另一个architecture不是根据上下文(在它之前和之后的单词)猜测一个单词,而是尝试使用当前单词猜测邻近的单词。我们可以把它在训练文本上滑动的窗口想象成这样:

stablediffusion Embeddings是什么放那里_word2vec_27


粉色方框有不同的色调,因为这个滑动窗口实际上在我们的训练数据集中创建了四个单独的样本:

stablediffusion Embeddings是什么放那里_word2vec_28


我们称这个方法为:skipgram。我们可以把滑动窗口可视化成如下:

stablediffusion Embeddings是什么放那里_数据集_29


这将把这四个样本添加到我们的训练数据集:

stablediffusion Embeddings是什么放那里_数据集_30


然后滑动窗口到下一个位置:

stablediffusion Embeddings是什么放那里_语言模型_31


这就产生了下面四个例子:

stablediffusion Embeddings是什么放那里_滑动窗口_32


在经过多次的移动之后,我们便有了如下的例子:

stablediffusion Embeddings是什么放那里_word2vec_33

Revisiting the training process(回顾训练过程)

现在我们有了使用skipgram模型从现有的运行文本(running text)中提取的训练数据集,让我们看看如何使用它来训练一个基本的神经语言模型来预测相邻近的单词。

stablediffusion Embeddings是什么放那里_滑动窗口_34


我们从数据集中的第一个示例开始。我们使用这个特征并喂给(feed to)未经训练的模型,要求它预测一个合适的邻近词。

stablediffusion Embeddings是什么放那里_滑动窗口_35


该模型执行这三个步骤并输出一个预测向量(为其词汇表中的每个单词分配一个概率)。由于模型是未经训练的,在这个阶段它的预测肯定是错误的。但是没关系。我们知道它应该猜出哪个单词——也就是我们当前用于训练模型的行中的label/output:

stablediffusion Embeddings是什么放那里_数据集_36


模型预测正确的值离我们还有多远?现在我们使用这两个向量相减,得到一个误差向量:

stablediffusion Embeddings是什么放那里_语言模型_37


这个error向量现在可以用来更新模型,所以下一次,它更有可能猜测 not会作为它的输出

stablediffusion Embeddings是什么放那里_数据集_38


这就是训练的第一步。我们继续对数据集中的下一个样本进行相同的处理,然后是下一个,直到我们覆盖了数据集中的所有样本。这就是训练的一个epoch。我们重复做了几个epoch,然后我们就有了我们训练过的模型,我们可以从中提取embedding矩阵,并将其用于任何其他应用程序。

Negative Sampling(负采样)

回忆一下这个神经语言模型是怎样经过三个步骤去计算出预测值的:

stablediffusion Embeddings是什么放那里_word2vec_39


从计算的角度来看,第三步是非常昂贵的,特别是我们知道我们将对数据集中的每个训练样本执行一次(很容易执行数千万次)。那么我们需要做点什么来提高性能呢?

一种方法是把我们的目标分成两个步骤:

  1. 生成高质量的词嵌入(不要担心下一个词的预测)。
  2. 使用这些高质量的嵌入来训练语言模型(来做下一个单词的预测)。
    我们将专注于第一步。在这篇文章中,我们将关注embeddings.要使用高性能模型生成高质量的embeddings,我们可以将模型的任务从预测相邻单词切换到:

stablediffusion Embeddings是什么放那里_滑动窗口_40


将其切换到一个模型,该模型同时接受输入和输出,并输出一个表示它们是否是邻居的分数(0表示“不是邻居”,1表示“邻居”)。

stablediffusion Embeddings是什么放那里_数据集_41


这个简单的转换将我们需要的模型从神经网络转换为逻辑回归模型——因此计算变得更加简单和快速。

这个转换需要我们转换数据集的结构——标签现在是一个值为0或1的新列。它们都是1,因为我们一开始添加的所有单词都是邻居。

stablediffusion Embeddings是什么放那里_数据集_42


这现在可以以惊人的速度计算——在几分钟内处理数百万个例子。但我们需要填补一个漏洞。如果我们所有的例子都是正面的(目标:1),那么我们就有可能得到一个总是返回1的“超级智慧”模型——达到100%的准确性,但什么也学不到,并生成垃圾embeddings。

stablediffusion Embeddings是什么放那里_滑动窗口_43


为了解决这个问题,我们需要将负样本引入到我们的数据集——负样本就是那些不是相邻词的样本。我们的模型需要为这些负样本返回0。现在,这是模型必须努力解决的一个挑战——但仍然以惊人的速度。

stablediffusion Embeddings是什么放那里_语言模型_44


但是我们要给输出填什么才好呢?我们从词汇表中随机抽取单词:

stablediffusion Embeddings是什么放那里_语言模型_45


这个想法是受到Noise-contrastive estimation [pdf]启发.。我们将实际信号(相邻词的积极例子)与噪声(随机选择的非相邻词)进行对比。这很好的权衡了计算效率和统计效率。

Skipgram with Negative Sampling (SGNS)

现在我们已经讨论了word2vec中的两个中心思想:作为一对,它们被称为带负抽样的skipgram模型。

stablediffusion Embeddings是什么放那里_数据集_46

Word2vec Training Process(Word2vec训练过程)

既然我们已经建立了skipgram和负抽样(negative sampling)的两个中心思想,我们就可以进一步研究实际的word2vec训练过程了。

在训练过程开始之前,我们对我们训练模型的文本进行预处理。在这一步中,我们将确定词汇表的大小(我们将其称为vocab_size,假设它为10,000)以及这个词汇表哪些包含了哪些单词。

在训练阶段的开始,我们创建两个矩阵——一个嵌入(Embedding)矩阵和一个Context(上下文)矩阵。这两个矩阵在我们的词汇表中每个单词都有一个Embedding(因此vocab_size是它们的一个维度)。第二个维度是我们希望每个嵌入的长度(embedding_size, 300是一个常见的维度值,但是我们在本文前面已经看到了一个维度为50的例子)。

stablediffusion Embeddings是什么放那里_语言模型_47


在训练过程的开始,我们用随机值初始化这些矩阵。然后我们开始训练。在每个训练步骤中,我们取一个正例和它相关的负例。我们来看第一组:

stablediffusion Embeddings是什么放那里_word2vec_48


现在我们有四个单词:输入单词not和输出/上下文单词:thou(实际的邻居)、aaron和taco(负例)。我们继续查找它们的Content—对于输入,我们访问Embedding矩阵。对于上下文单词,我们访问Content矩阵(即使两个矩阵都对词汇表中的每个单词进行了嵌入)。

stablediffusion Embeddings是什么放那里_数据集_49


然后,我们取输入embedding与每个上下文embedding的点积。在每种情况下,都会产生一个数字,这个数字表示输入和上下文embedding的相似性:

stablediffusion Embeddings是什么放那里_word2vec_50


现在我们需要一种方法来把这些分数变成类似于概率的东西——我们需要它们都是正的,值在0和1之间。我们使用sigmoid函数:

stablediffusion Embeddings是什么放那里_数据集_51


现在,我们可以将sigmoid操作的输出作为这些示例的模型输出。你可以看到taco得分最高,aaron得分最低,在sigmoid函数使用前后都是如此。

现在,未经训练的模型已经做出了预测,并看到我们有一个实际的目标标签进行比较,让我们计算一下模型预测的误差有多大。为此,我们只需从目标标签中减去sigmoid分数。

stablediffusion Embeddings是什么放那里_语言模型_52


接下来是“机器学习”的“学习”部分。现在,我们可以使用这个错误分数来调整not、thou、aaron和taco的embeddings,以便下一次进行计算时,结果将更接近目标分数。

stablediffusion Embeddings是什么放那里_滑动窗口_53


这就是训练步骤。我们在每一步迭代中得到了更好的嵌入词(not,thou,aaron,and taco)。紧接着又进入下一个步骤(下一个positive sample和它相关的negative samples),并再次进行相同的过程。

stablediffusion Embeddings是什么放那里_word2vec_54


当我们多次遍历整个数据集时,embeddings 将继续得到改进。然后,我们可以停止培训过程,丢弃上下文矩阵(Context matrix),并使用Embeddings矩阵作为下一个任务的预训练embeddings。

Window Size and Number of Negative Samples(窗口大小和负例样本的数量)

word2vec训练过程中的两个关键超参数是窗口大小和负样本数量。

stablediffusion Embeddings是什么放那里_滑动窗口_55


不同的窗口大小可以更好地完成不同的任务。

stablediffusion Embeddings是什么放那里_语言模型_56


negative samples的数量是训练过程中的另一个因素。原文规定5-20是一个很好的negative samples数量。它还指出,当您拥有足够大的数据集时,2-5似乎就足够了。Gensim默认为5个negative samples。

Conclusion

我希望你现在对词嵌入和word2vec算法有感觉。我还希望现在当你读到一篇提到“skip gram with negative sampling”(SGNS)的论文(就像顶部的推荐系统论文)时,你能更好地理解这些概念。一如既往,所有的反馈都是值得赞赏的。