前言

说明:讲解时会对相关文章资料进行思想、结构、优缺点,内容进行提炼和记录,相关引用会标明出处,引用之处如有侵权,烦请告知删除。
转载请注明:DengBoCong

本文并不是深挖Word2vec和Embedding原理公式推导的文章,网上已经有很多针对性的原理讲解文章,大家可以自行了解。本文主要是针对词嵌入的相关概念、原理及模式进行提炼陈列,扫盲和抛砖引玉。

介绍

Embedding就是用一个低维的向量表示一个物体,这个Embedding向量的性质是能使距离相近的向量对应的物体有相近的含义,正是因为Embedding能够用低维向量对物体进行编码还能保留其含义的特点,所以其非常适合用于深度学习。由于我们熟知的one hot encoding、multi hot encoding是一种稀疏向量的编码方式,所以不适合用来深度学习进行特征表示,相反Embedding概括而言,就是一种高效的低维稠密的操作。

词嵌入( word embedding):基于神经网络的分布表示又称为词向量、词嵌入,神经网络词向量模型与其它分布表示方法一样,均基于分布假说,核心依然是上下文的表示以及上下文与目标词之间的关系的建模。

Embedding很早之前就有人研究了,相关资料文章特别的多,不过让Embedding在行内如此流行的功劳还要归功于google的Word2vec。这里需要先说说神经网络语言模型与Word2vec的关系,神经网络语言模型做词向量有以下几种方式:

  • Neural Network Language Model ,NNLM
  • Log-Bilinear Language Model, LBL
  • Recurrent Neural Network based Language Model,RNNLM
  • C&W 模型
  • CBOW( Continuous Bagof-Words)和 Skip-gram 模型

上面几种模型只是个在逻辑概念上的东西,那么具体我们得通过设计将其实现出来,而实现CBOW( Continuous Bagof-Words)和 Skip-gram 语言模型的工具就是Word2vec。

在广告、推荐、搜索等领域,由于用户数据的稀疏性,几乎必然要求在构建DNN之前对user和item进行embedding后才能进行有效的训练,所以诞生一种叫做“item2vec”的方法,感兴趣的可以自行了解,这里不展开讲。

背景知识

  • Matrix Factorization:矩阵分解
    • 简单来讲,MF就是将一个矩阵分解成多个矩阵的乘积,典型的算法有SVD、LSA,是一种常见的技术,在推荐、NLP都有应用。后面你就会知道,在Word2vec中,最终每一个word都会有两个向量:V_word和V_context,假设存在一个矩阵W = V_word * V_context,word2vec也可以理解成是对矩阵W的矩阵分解。
  • Pointwise Mutual Information(PMI):点互信息
    • 指标来衡量两个事物之间的相关性,如下公式中,w和c同时出现的次数/(w出现的次数 + c出现的次数),和MF对比,就多了个常量logk。
  • Cosine similarity:内积空间的两个非零向量之间相似度的量度(这个自己实现也比较好实现,Word2vec用这个计算相似度)
    在这里插入图片描述

这里多说一下余弦相似度计算,下面举个例子:
在这里插入图片描述

keras中的Embedding和Word2vec的区别

其实二者的目标是一样的,都是我们为了学到词的稠密的嵌入表示。只不过学习的方式不一样。Word2vec是无监督的学习方式,利用上下文环境来学习词的嵌入表示,因此可以学到相关词,但是只能捕捉到局部分布信息。而在keras的Embedding层中,权重的更新是基于标签的信息进行学习,为了达到较高的监督学习的效果,会将Embedding作为网络的一层,根据target进行学习和调整。比如LSTM中对词向量的微调。简单来说,Word2vec一般单独提前训练好,而Embedding一般作为模型中的层随着模型一同训练。

CBOW和Skip-gram

CBOW也是统计语言模型的一种,顾名思义就是根据某个词前面的C个词或者前后C个连续的词,来计算某个词出现的概率。Skip-Gram Model相反,是根据某个词,然后分别计算它前后出现某几个词的各个概率。这样讲可能比较抽象,这里借用jalammar的文章里的内容和图进行说明。

CBOW

我们通过找常出现在每个单词附近的词,就能获得它们的映射关系。机制如下:

  • 先是获取大量文本数据
  • 后我们建立一个可以沿文本滑动的窗(例如一个窗里包含三个单词)
  • 利用这样的滑动窗就能为训练模型生成大量样本数据。

当这个窗口沿着文本滑动时,我们就能(真实地)生成一套用于模型训练的数据集。为了明确理解这个过程,我们看下滑动窗是如何处理这个短语的,我们把前两个单词单做特征,第三个单词单做标签:
在这里插入图片描述
如上,以此产生一个样本,然后以此慢慢的滑动下去,就会产生一个很大的数据集。接下来,我们不仅要考虑目标单词的前两个单词,还要考虑其后两个单词,像下面这样。
在这里插入图片描述
通过这种方式,我们实际上构建并训练的模型就如下所示:
在这里插入图片描述
上述的这种架构就被我们称为连续词袋(CBOW)。

Skip-gram

Skip-gram不同的是,它不根据前后文(前后单词)来猜测目标单词,而是推测当前单词可能的前后单词。我们设想一下滑动窗在训练数据时如下图所示(绿框中的词语是输入词,粉框则是可能的输出结果):
在这里插入图片描述
这里粉框颜色深度呈现不同,是因为滑动窗给训练集产生了4个独立的样本
在这里插入图片描述
在移动几组位置之后,我们就能得到一批样本:
在这里插入图片描述
这种方式就被我们称为Skipgram架构。我们可以像下图这样将展示滑动窗的内容。

Skipgram with Negative Sampling (SGNS)

现在我们已经从现有的文本中获得了Skipgram模型的训练数据集,接下来让我们看看如何使用它来训练一个能预测相邻词汇的自然语言模型。从数据集中的第一个样本开始。我们将特征输入到未经训练的模型,让它预测一个可能的相邻单词。
在这里插入图片描述
该模型会执行三个步骤并输入预测向量(对应于单词表中每个单词的概率)。因为模型未经训练,该阶段的预测肯定是错误的。但是没关系,我们知道应该猜出的是哪个单词——这个词就是我训练集数据中的输出标签:
在这里插入图片描述
目标单词概率为1,其他所有单词概率为0,这样数值组成的向量就是“目标向量”。模型的偏差有多少?将两个向量相减,就能得到偏差向量:
在这里插入图片描述
现在这一误差向量可以被用于更新模型了,所以在下一轮预测中,如果用not作为输入,我们更有可能得到thou作为输出了。
在这里插入图片描述
这其实就是训练的第一步了。我们接下来继续对数据集内下一份样本进行同样的操作,直到我们遍历所有的样本。这就是一轮(epoch)了。我们再多做几轮(epoch),得到训练过的模型,于是就可以从中提取嵌入矩阵来用于其他应用了。但是真正的Word2vec在上面的基本流程上,还有一些关键思想:

  • 负样本采样:我们需要在数据集中引入负样本 - 不是邻居的单词样本。我们的模型需要为这些样本返回0,这些单词是从词汇表中随机抽取的单词,这个想法的灵感来自噪声对比估计。

Word2vec训练流程

在训练过程开始之前,我们预先处理我们正在训练模型的文本。在这一步中,我们确定一下词典的大小(我们称之为vocab_size,比如说10,000)以及哪些词被它包含在内。

在训练阶段的开始,我们创建两个矩阵——Embedding矩阵和Context矩阵。这两个矩阵在我们的词汇表中嵌入了每个单词(所以vocab_size是他们的维度之一)。第二个维度是我们希望每次嵌入的长度(embedding_size——300是一个常见值,但我们在前文也看过50的例子)。
在这里插入图片描述
在训练过程开始时,我们用随机值初始化这些矩阵。然后我们开始训练过程。在每个训练步骤中,我们采取一个相邻的例子及其相关的非相邻例子。我们来看看我们的第一组:
在这里插入图片描述
现在我们有四个单词:输入单词not和输出/上下文单词: thou(实际邻居词),aaron和taco(负面例子)。我们继续查找它们的嵌入——对于输入词,我们查看Embedding矩阵。对于上下文单词,我们查看Context矩阵(即使两个矩阵都在我们的词汇表中嵌入了每个单词)。
在这里插入图片描述
然后,我们计算输入嵌入与每个上下文嵌入的点积。在每种情况下,结果都将是表示输入和上下文嵌入的相似性的数字。
在这里插入图片描述
现在我们需要一种方法将这些分数转化为看起来像概率的东西——我们需要它们都是正值,并且 处于0到1之间。sigmoid这一逻辑函数转换正适合用来做这样的事情啦。
在这里插入图片描述
现在我们可以将sigmoid操作的输出视为这些示例的模型输出。您可以看到taco得分最高,aaron最低,无论是sigmoid操作之前还是之后。

既然未经训练的模型已做出预测,而且我们确实拥有真实目标标签来作对比,那么让我们计算模型预测中的误差吧。为此我们只需从目标标签中减去sigmoid分数。
在这里插入图片描述
现在,我们可以利用这个错误分数来调整not、thou、aaron和taco的嵌入,使我们下一次做出这一计算时,结果会更接近目标分数。训练步骤到此结束。我们从中得到了这一步所使用词语更好一些的嵌入(not,thou,aaron和taco)。我们现在进行下一步(下一个相邻样本及其相关的非相邻样本),并再次执行相同的过程。当我们循环遍历整个数据集多次时,嵌入会继续得到改进。然后我们就可以停止训练过程,丢弃Context矩阵,并使用Embeddings矩阵作为下一项任务的已被训练好的嵌入。

最后

word2vec训练过程中的两个关键超参数是窗口大小和负样本的数量。
在这里插入图片描述
不同的任务适合不同的窗口大小。一种启发式方法是,使用较小的窗口大小(2-15)会得到这样的嵌入:两个嵌入之间的高相似性得分表明这些单词是可互换的(注意,如果我们只查看附近距离很近的单词,反义词通常可以互换——例如,好的和坏的经常出现在类似的语境中)。使用较大的窗口大小(15-50,甚至更多)会得到相似性更能指示单词相关性的嵌入。在实际操作中,你通常需要对嵌入过程提供指导以帮助读者得到相似的”语感“。Gensim默认窗口大小为5(除了输入字本身以外还包括输入字之前与之后的两个字)。
在这里插入图片描述
本的数量是训练训练过程的另一个因素。原始论文认为5-20个负样本是比较理想的数量。它还指出,当你拥有足够大的数据集时,2-5个似乎就已经足够了。Gensim默认为5个负样本。

参考资料: