word2vec实战专利数据的简单介绍
Word2Vec原理详解
自然语言是一套用来表达含义的复杂系统。在这套系统中,词是表义的基本单元。顾名思义,词向量是用来表示词的向量,也可被认为是词的特征向量或表征。把词映射为实数域向量的技术也叫词嵌入(word embedding)。近年来,词嵌入已逐渐成为自然语言处理的基础知识。
跳字模型假设基于某个词来生成它在文本序列周围的词。举个例子,假设文本序列是“the” “man” “loves” “his” “son”。以“loves”作为中心词,设背景窗口大小为2。如图1所示,跳字模型所关心的是,给定中心词“loves”,生成与它距离不超过2个词的背景词“the” “man” “his” “son”的条件概率,即
假设给定中心词的情况下,背景词的生成是相互独立的,那么上式可以改写成
虽然开篇说了one-hot不行,但是我们不要忽略一个事实,计算机没办法识别“字符”,所有的数据必须转化成二进制的编码形式。
大家已经注意到,我们已经到了Hidden Layer到Output Layer这一层了,简单来看就是隐藏层和输出层进行全连接,然后是一个softmax,输出概率。过程比较简单,一个Forward Propagation,一个Backward Propagation。
在跳字模型中,每个词被表示成两个 维向量,用来计算条件概率。假设这个词在词典中索引为 ,当它为中心词时向量表示为 ,而为背景词时向量表示为 。设中心词 在词典中索引为 ,背景词 ,在词典中索引为 ,给定中心词生成背景词的条件概率可以通过对向量内积做softmax运算而得到:
其中词典索引集 。假设给定一个长度为 的文本序列,设时间步 的词为 。假设给定中心词的情况下背景词的生成相互独立,当背景窗口大小为 时,跳字模型的似然函数即给定任一中心词生成所有背景词的概率
这里小于1和大于 的时间步可以忽略。
这样就可以计算出每个中心词推断背景词的概率,而我们在输入的时候给出了背景词的向量,此时只需要更大化背景词的输出概率即可。 基于这样的想法,我们会想到极大化似然估计的方式。但是一个函数的更大值往往不容易计算,因此,我们可以通过对函数进行变换,从而改变函数的增减性,以便优化。这等价于最小化以下损失函数:
最小化损失函数,我们最容易想到的就是梯度下降法。在使用梯度下降法之前,我们要把我们的损失函数定义出来,毕竟上面的式子是一个概率,下面把softmax的计算结果带入得到:
损失函数已经得到了,我们的目标就是最小化它,优化它之前我们要搞清楚我们的参数是谁?每错,我们的参数是中心词和背景词,那对于这样的一个函数显然是非凸函数,因此,我们要做一个假设,假设在对中心词权重更新时,背景词的权重是固定的,然后在以同样的方式来更新背景词的权重。
这里就计算出来了中心词的梯度,可以根据这个梯度进行迭代更新。对于背景词的更新是同样的 *** ,
当 时,即通过中心词 我们可以正确预测上下文词 时,不需要调整 ,反之,则相应调整 。
但是要注意背景词的个数不是唯一的,所以更新的时候要逐个更新,幅图辅助理解。
连续词袋模型与跳字模型类似。与跳字模型更大的不同在于,连续词袋模型假设基于某中心词在文本序列前后的背景词来生成中心词。在同样的文本序列“the” “man” “loves” “his” “son”里,以“loves”作为中心词,且背景窗口大小为2时,连续词袋模型关心的是,给定背景词“the” “man” “his” “son”生成中心词“loves”的条件概率(如图2所示),也就是
因为连续词袋模型的背景词有多个,我们将这些背景词向量取平均,然后使用和跳字模型一样的 *** 来计算条件概率。设 和 分别表示词典中索引为 的词作为背景词和中心词的向量(注意符号的含义与跳字模型中的相反,假设输入向量为 ,输出向量为 )。设中心词 在词典中索引为 ,背景词 在词典中索引为 ,那么给定背景词生成中心词的条件概率
为了让符号更加简单,我们记 ,且 ,那么上式可以简写成
给定一个长度为 的文本序列,设时间步t的词为 ,背景窗口大小为 。连续词袋模型的似然函数是由背景词生成任一中心词的概率
训练连续词袋模型同训练跳字模型基本一致。连续词袋模型的更大似然估计等价于最小化损失函数
注意到
通过微分,我们可以计算出上式中条件概率的对数有关任一背景词向量 的梯度
中心词的梯度同理可得,
同跳字模型不一样的一点在于,我们一般使用连续词袋模型的背景词向量作为词的表征向量。
预训练模型综述--Albert,xlnet,bert,word2vec
Albert,xlnet,bert,word2vec
通过预训练模型实现迁移学习,迁移学习本质上是在一个数据集上训练模型,然后对该模型进行调整,以在不同的数据集上执行不同的自然语言处理功能。
1. word2vec
线性模型 :
很神奇的地方,从而也说明高维空间映射的词向量可以很好体现真实世界中token之间的关系。如:king-man = queen-woman
负采样 :
由于训练词向量模型的目标不是为了得到一个多么精准的语言模型,而是为了获得它的副产物——词向量。所以要做到的不是在几万几十万个token中艰难计算softmax获得更优的那个词(就是预测的对于给定词的下一词),而只需能做到在几个词中找到对的那个词就行,这几个词包括一个正例(即直接给定的下一词),和随机产生的噪声词(采样抽取的几个负例),就是说训练一个sigmoid二分类器,只要模型能够从中找出正确的词就认为完成任务。
这种负采样思想也应用到之后的BERT里,只不过从word-level变成sentence-level,这样能获取句子间关联关系。
缺点是上下文无关(static):
因而为了让句子有一个整体含义(context),大家会在下游具体的NLP任务中基与词向量的序列做encoding操作。
下面是一个比较表格,模型不细讲了,预测目标这里的next word下一个词,是所有传统语言模型都做的事——寻找下一个词填什么。
BERT模型进一步增加词向量模型泛化能力,充分描述字符级、词级、句子级甚至句间关系特征。
真正的双向encoding:
Masked LM,类似完形填空,尽管仍旧看到所有位置信息,但需要预测的词已被特殊符号代替,可以放心双向encoding。
Transformer做encoder实现上下文相关(context):
使用transformer而不是bi-LSTM做encoder,可以有更深的层数、具有更好并行性。并且线性的Transformer比lstm更易免受mask标记影响,只需要通过self-attention减小mask标记权重即可,而lstm类似黑盒模型,很难确定其内部对于mask标记的处理方式。
提升至句子级别:
学习句子/句对关系表示,句子级负采样。首先给定的一个句子,下一句子正例(正确词),随机采样一句负例(随机采样词),句子级上来做二分类(即判断句子是当前句子的下一句还是噪声),类似word2vec的单词级负采样。
二、BERT细则
这里主要介绍BERT的三个亮点Masked LM、transformer、sentence-level。
1. Masked Language Model
原本叫cloze test,是完形填空的意思。
随机mask语料中15%的token,然后将masked token 位置输出的最终隐层向量送入softmax,来预测masked token。
这样输入一个句子,每次只预测句子中大概15%的词,所以BERT训练很慢。。。(但是google设备NB。。)
而对于盖住词的特殊标记,在下游NLP任务中不存在。因此,为了和后续任务保持一致,作者按一定的比例在需要预测的词位置上输入原词或者输入某个随机的词。如:my dog is hairy
2. Transformer —— attention is all you need
Transformer模型是2018年5月提出的,可以替代传统RNN和CNN的一种新的架构,用来实现机器翻译,论文名称是attention is all you need。无论是RNN还是CNN,在处理NLP任务时都有缺陷。CNN是其先天的卷积操作不很适合序列化的文本,RNN是其没有并行化,很容易超出内存限制(比如50tokens长度的句子就会占据很大的内存)。
下面左图是transformer模型一个结构,分成左边Nx框框的encoder和右边Nx框框的decoder,相较于RNN+attention常见的encoder-decoder之间的attention(上边的一个橙色框),还多出encoder和decoder内部的self-attention(下边的两个橙色框)。每个attention都有multi-head特征。最后,通过position encoding加入没考虑过的位置信息。
下面从multi-head attention,self-attention, position encoding几个角度介绍。
multi-head attention:
将一个词的vector切分成h个维度,求attention相似度时每个h维度计算。由于单词映射在高维空间作为向量形式,每一维空间都可以学到不同的特征,相邻空间所学结果更相似,相较于全体空间放到一起对应更加合理。比如对于vector-size=512的词向量,取h=8,每64个空间做一个attention,学到结果更细化。
self-attention:
每个词位的词都可以无视方向和距离,有机会直接和句子中的每个词encoding。比如上面右图这个句子,每个单词和同句其他单词之间都有一条边作为联系,边的颜色越深表明联系越强,而一般意义模糊的词语所连的边都比较深。比如:law,application,missing,opinion。。。
position encoding:
因为transformer既没有RNN的recurrence也没有CNN的convolution,但序列顺序信息很重要,比如你欠我100万明天要还和我欠你100万明天要还的含义截然不同。。。
transformer计算token的位置信息这里使用正弦波↓,类似模拟信号传播周期性变化。这样的循环函数可以一定程度上增加模型的泛化能力。
但BERT直接训练一个position embedding来保留位置信息,每个位置随机初始化一个向量,加入模型训练,最后就得到一个包含位置信息的embedding(简单粗暴。。),最后这个position embedding和word embedding的结合方式上,BERT选择直接相加。
3. sentence-level representation
在很多任务中,仅仅靠encoding是不足以完成任务的(这个只是学到了一堆token级的特征),还需要捕捉一些句子级的模式,来完成SLI、QA、dialogue等需要句子表示、句间交互与匹配的任务。对此,BERT又引入了另一个极其重要却又极其轻量级的任务,来试图把这种模式也学习到。
句子级负采样
句子级别的连续性预测任务,即预测输入BERT的两端文本是否为连续的文本。训练的时候,输入模型的第二个片段会以50%的概率从全部文本中随机选取,剩下50%的概率选取之一个片段的后续的文本。 即首先给定的一个句子(相当于word2vec中给定context),它下一个句子即为正例(相当于word2vec中的正确词),随机采样一个句子作为负例(相当于word2vec中随机采样的词),然后在该sentence-level上来做二分类(即判断句子是当前句子的下一句还是噪声)。
句子级表示
BERT是一个句子级别的语言模型,不像ELMo模型在与下游具体NLP任务拼接时需要每层加上权重做全局池化,BERT可以直接获得一整个句子的唯一向量表示。它在每个input前面加一个特殊的记号[CLS],然后让Transformer对[CLS]进行深度encoding,由于Transformer是可以无视空间和距离的把全局信息encoding进每个位置的,而[CLS]的更高隐层作为句子/句对的表示直接跟softmax的输出层连接,因此其作为梯度反向传播路径上的“关卡”,可以学到整个input的上层特征。
segment embedding
对于句对来说,EA和EB分别代表左句子和右句子;对于句子来说,只有EA。这个EA和EB也是随模型训练出来的。
如下图所示,最终输入结果会变成下面3个embedding拼接的表示。
首先,XLNet 是一个类似 BERT 的模型,而不是完全不同的模型。但这是一个非常有前途和潜力的。总之,XLNet是一种通用的自回归预训练 *** 。
那么什么是自回归(AR)语言模型?
AR语言模型是一种使用上下文词来预测下一个词的模型。但是在这里,上下文单词被限制在两个方向,前向或后向。
AR 语言模型的优势是擅长生成式自然语言处理任务。 因为在生成上下文时,通常是前向的。AR 语言模型很自然地适用于此类 NLP 任务。
但AR语言模型有一些缺点,它只能使用前向上下文或后向上下文,这意味着它不能同时使用前向和后向上下文。
自回归语言模型有优点有缺点,缺点是只能利用上文或者下文的信息,不能同时利用上文和下文的信息,当然,貌似ELMO这种双向都做,然后拼接看上去能够解决这个问题,因为融合模式过于简单,所以效果其实并不是太好。它的优点,其实跟下游NLP任务有关,比如生成类NLP任务,比如文本摘要,机器翻译等,在实际生成内容的时候,就是从左向右的,自回归语言模型天然匹配这个过程。而Bert这种DAE模式,在生成类NLP任务中,就面临训练过程和应用过程不一致的问题,导致生成类的NLP任务到目前为止都做不太好。
与 AR 语言模型不同,BERT 被归类为自动编码器(AE)语言模型。
AE 语言模型旨在从损坏的输入重建原始数据。
损坏的输入意味着我们在预训练阶段用 [MASK] 替换原始词 into 。目标是预测 into 得到原始句子。
AE 语言模型的优势是,它可以从向前和向后的方向看到上下文。
但 AE 语言模型也有其缺点。它在预训练中使用 [MASK] ,但这种人为的符号在调优时在真实数据中并不存在,会导致预训练-调优的差异。[MASK] 的另一个缺点是它假设预测(掩蔽的)词 在给定未屏蔽的 词 的情况下彼此独立。例如,我们有一句话“它表明住房危机已经变成银行危机”。我们掩蔽“银行业”和“危机”。在这里注意,我们知道掩蔽的“银行业”和“危机”包含彼此的隐含关系。但 AE 模型试图预测“银行业”给予未掩蔽的 词,并预测“危机”分别给出未掩蔽的 词。它忽略了“银行业”与“危机”之间的关系。换句话说,它假设预测(掩蔽)的标记彼此独立。但是我们知道模型应该学习预测(掩蔽)词之间的这种相关性来预测其中一个词。
作者想要强调的是,XLNet 提出了一种让 AR 语言模型从双向上下文中学习的新 *** ,以避免 MASK *** 在 AE 语言模型中带来的缺点。
XLNet的出发点就是:能否融合自回归LM和DAE LM两者的优点。就是说如果站在自回归LM的角度,如何引入和双向语言模型等价的效果;如果站在DAE LM的角度看,它本身是融入双向语言模型的,如何抛掉表面的那个[Mask]标记,让预训练和Fine-tuning保持一致。当然,XLNet还讲到了一个Bert被Mask单词之间相互独立的问题,我相信这个不太重要,原因后面会说。当然,我认为这点不重要的事情,纯粹是个人观点,出错难免,看看就完了,不用较真。
AR 语言模型只能向前或向后使用上下文,那么如何让它从双向上下文中学习呢?
语言模型包括两个阶段,即预训练阶段和调优阶段。XLNet 专注于预训练阶段。在预训练阶段,它提出了一个名为排列语言建模的新目标。我们可以从这个名称知道基本思想,它使用排列。
这里我们举一个例子来解释。序列的次序是 [x1, x2, x3, x4] 。这种序列的所有排列如下。
因此对于这 4 个词的([图片上传失败...(image-c7a4e0-1570519576567)]
)句子,有 24([图片上传失败...(image-d738b7-1570519576567)]
)个排列。
情景是我们想要预测 x3 。因此在 24 个排列中有 4 种模式,分别 x3 位于第 1 位,第 2 位,第 3 位,第 4 位。
当然,上面讲的仍然是基本思想。难点其实在于具体怎么做才能实现上述思想。首先,需要强调一点,尽管上面讲的是把句子X的单词排列组合后,再随机抽取例子作为输入,但是,实际上你是不能这么做的,因为Fine-tuning阶段你不可能也去排列组合原始输入。所以,就必须让预训练阶段的输入部分,看上去仍然是x1,x2,x3,x4这个输入顺序,但是可以在Transformer部分做些工作,来达成我们希望的目标。具体而言,XLNet采取了Attention掩码的机制,你可以理解为,当前的输入句子是X,要预测的单词Ti是第i个单词,前面1到i-1个单词,在输入部分观察,并没发生变化,该是谁还是谁。但是在Transformer内部,通过Attention掩码,从X的输入单词里面,也就是Ti的上文和下文单词中,随机选择i-1个,放到Ti的上文位置中,把其它单词的输入通过Attention掩码隐藏掉,于是就能够达成我们期望的目标(当然这个所谓放到Ti的上文位置,只是一种形象的说法,其实在内部,就是通过Attention Mask,把其它没有被选到的单词Mask掉,不让它们在预测单词Ti的时候发生作用,如此而已。看着就类似于把这些被选中的单词放到了上文Context_before的位置了)。具体实现的时候,XLNet是用“双流自注意力模型”实现的,细节可以参考论文,但是基本思想就如上所述,双流自注意力机制只是实现这个思想的具体方式,理论上,你可以想出其它具体实现方式来实现这个基本思想,也能达成让Ti看到下文单词的目标。
上面说的Attention掩码,我估计你还是没了解它的意思,我再用例子解释一下。Attention Mask的机制,核心就是说,尽管当前输入看上去仍然是x1-x2-x3-x4,但是我们已经改成随机排列组合的另外一个顺序x3-x2-x4-x1了,如果用这个例子用来从左到右训练LM,意味着当预测x2的时候,它只能看到上文x3;当预测x4的时候,只能看到上文x3和x2,以此类推……这样,比如对于x2来说,就看到了下文x3了。这种在输入侧维持表面的X句子单词顺序,但是其实在Transformer内部,看到的已经是被重新排列组合后的顺序,是通过Attention掩码来实现的。如上图所示,输入看上去仍然是x1,x2,x3,x4,可以通过不同的掩码矩阵,让当前单词Xi只能看到被排列组合后的顺序x3-x2-x4-x1中自己前面的单词。这样就在内部改成了被预测单词同时看到上下文单词,但是输入侧看上去仍然维持原先的单词顺序了。关键要看明白上图右侧那个掩码矩阵,我相信很多人刚开始没看明白,因为我刚开始也没看明白,因为没有标出掩码矩阵的单词坐标,它的坐标是1-2-3-4,就是表面那个X的单词顺序,通过掩码矩阵,就能改成你想要的排列组合,并让当前单词看到它该看到的所谓上文,其实是掺杂了上文和下文的内容。这是attention mask来实现排列组合的背后的意思。
ALBERT相比于BERT的改进
ALBERT也是采用和BERT一样的Transformer的encoder结果,激活函数使用的也是GELU,在讲解下面的内容前,我们规定几个参数,词的embedding我们设置为E,encoder的层数我们设置为L,hidden size即encoder的输出值的维度我们设置为H,前馈神经 *** 的节点数设置为4H,attention的head个数设置为H/64。
在ALBERT中主要有三个改进方向。
1、对Embedding因式分解(Factorized embedding parameterization)
在BERT中,词embedding与encoder输出的embedding维度是一样的都是768。但是ALBERT认为,词级别的embedding是没有上下文依赖的表述,而隐藏层的输出值不仅包括了词本生的意思还包括一些上下文信息,理论上来说隐藏层的表述包含的信息应该更多一些,因此应该让HE,所以ALBERT的词向量的维度是小于encoder输出值维度的。
在NLP任务中,通常词典都会很大,embedding matrix的大小是E×V,如果和BERT一样让H=E,那么embedding matrix的参数量会很大,并且反向传播的过程中,更新的内容也比较稀疏。
结合上述说的两个点,ALBERT采用了一种因式分解的 *** 来降低参数量。首先把one-hot向量映射到一个低维度的空间,大小为E,然后再映射到一个高维度的空间,说白了就是先经过一个维度很低的embedding matrix,然后再经过一个高维度matrix把维度变到隐藏层的空间内,从而把参数量从O(V×H) O(V×H)O(V×H)降低到了O(V×E+E×H) O(V×E+E×H)O(V×E+E×H),当EH时参数量减少的很明显。
下图是E选择不同值的一个实验结果,尴尬的是,在不采用参数共享优化方案时E设置为768效果反而好一些,在采用了参数共享优化方案时E取128效果更好一些。
2、跨层的参数共享(Cross-layer parameter sharing)
在ALBERT还提出了一种参数共享的 *** ,Transformer *** 享参数有多种方案,只共享全连接层,只共享attention层,ALBERT结合了上述两种方案,全连接层与attention层都进行参数共享,也就是说共享encoder内的所有参数,同样量级下的Transformer采用该方案后实际上效果是有下降的,但是参数量减少了很多,训练速度也提升了很多。
下图是BERT与ALBERT的一个对比,以base为例,BERT的参数是108M,而ALBERT仅有12M,但是效果的确相比BERT降低了两个点。由于其速度快的原因,我们再以BERT xlarge为参照标准其参数是1280M,假设其训练速度是1,ALBERT的xxlarge版本的训练速度是其1.2倍,并且参数也才223M,评判标准的平均值也达到了更高的88.7
除了上述说了训练速度快之外,ALBERT每一层的输出的embedding相比于BERT来说震荡幅度更小一些。下图是不同的层的输出值的L2距离与cosine相似度,可见参数共享其实是有稳定 *** 参数的作用的。
3、句间连贯(Inter-sentence coherence loss)
BERT的NSP任务实际上是一个二分类,训练数据的正样本是通过采样同一个文档中的两个连续的句子,而负样本是通过采用两个不同的文档的句子。该任务主要是希望能提高下游任务的效果,例如NLI自然语言推理任务。但是后续的研究发现该任务效果并不好,主要原因是因为其任务过于简单。NSP其实包含了两个子任务,主题预测与关系一致性预测,但是主题预测相比于关系一致性预测简单太多了,并且在MLM任务中其实也有类型的效果。
这里提一下为啥包含了主题预测,因为正样本是在同一个文档中选取的,负样本是在不同的文档选取的,假如我们有2个文档,一个是娱乐相关的,一个是新中国成立70周年相关的,那么负样本选择的内容就是不同的主题,而正样都在娱乐文档中选择的话预测出来的主题就是娱乐,在新中国成立70周年的文档中选择的话就是后者这个主题了。
在ALBERT中,为了只保留一致性任务去除主题识别的影响,提出了一个新的任务 sentence-order prediction(SOP),SOP的正样本和NSP的获取方式是一样的,负样本把正样本的顺序反转即可。SOP因为实在同一个文档中选的,其只关注句子的顺序并没有主题方面的影响。并且SOP能解决NSP的任务,但是NSP并不能解决SOP的任务,该任务的添加给最终的结果提升了一个点。
4、移除dropout
除了上面提到的三个主要优化点,ALBERT的作者还发现一个很有意思的点,ALBERT在训练了100w步之后,模型依旧没有过拟合,于是乎作者果断移除了dropout,没想到对下游任务的效果竟然有一定的提升。这也是业界之一次发现dropout对大规模的预训练模型会造成负面影响。
参考链接:
彻底搞懂BERT
什么是 XLNet,为何它会超越 BERT?
XLNet:运行机制及和Bert的异同比较
一文揭开ALBERT的神秘面纱
不懂word2vec,还敢说自己是做NLP?
word2vec模型之Skip-Gram Model
本文介绍一种基于神经 *** 结构的Word2Vec模型,Word2Vec是目前NLP领域的基础知识,这里仅对Word2Vec模型中的Skip-Gram模型进行详细介绍。
Skip-Gram神经 *** 模型是一种非常简单的神经 *** 结构,是一个仅有一个Hidden Layer的神经 *** 结构。Skip-Gram模型的训练过程可以视作一个“Fake Task(伪任务)”,为何称之为“Fake Task”?是因为训练该模型的目的并不是将训练好的模型用于任何的分类任务,而是为了学习得到隐层的权重矩阵,而通过这些矩阵我们会得到想要的单词的特征向量,总体框架入下图所示。下面详细介绍这个Skip-Gram模型的训练过程。
给定一个特定的word作为输入,我们从该word的附近随机挑选一个word,该 *** 模型会告诉我们词汇表中的每个单词出现在“附近”的概率。这里的“附近”指的是在特定window size范围内。输出概率与在输入词附近找到每个单词的可能性有关。这里,我们使用文本中指定window size内的word pair(inputword,outputword)来训练神经 *** 模型。word pairs的获取方式如下图所示。
这里详细介绍一下Skip-Gram模型的训练过程。首先,神经 *** 模型只接受数值型的输入,故不能直接将每个单词直接输入到一个神经 *** 中,故而需要一种针对神经 *** 模型的单词表示方式,为此需要针对训练集中的所有不同的单词构建一个词汇表(vocabulary),然后将词汇表中的每个单词以 One-Hot编码 的方式进行表示。比如,现在有一个大小为10000的词汇表,我们需要为每个单词构建一个One-Hot向量,要求每个单词对应的当前单词的位置为1,其他所有位置为0,因此我们会得到10000个长度为10000的向量,其中每个向量都只有一个位置为1。神经 *** 的输出是一个10000维的向量,表示针对输入单词,词汇表中所有的单词出现在输入单词附近的预测概率。如下图所示:
上述的神经 *** 结构隐层中的神经元没有激活函数,但输出层的每个神经元使用了softmax函数。训练的过程使用word pair(inputword,outputword),输入是一个One-Hot的向量,输出的也是一个表示输出单词的One-Hot的向量。但是当在一个输入词在训练好的 *** 上计算时,输出的向量实际上是一个概率分布,并不是一个One-Hot向量。因为每个输出的单元使用了 Softmax ,且没有激活函数。
同样的针对上述问题,有10000个单词,假设需要为每个单词学习一个300维的向量,那么隐层可以由一个10000*300的矩阵来表示(300个神经元,每个神经元都有一个10000维的权重向量),如下图所示。
竖着看这个隐层的权重矩阵,每一列对应一个神经元中的参数向量,而如果横着看这个权重矩阵,每一行就是一个300维的向量,而这这就是我们需要通过学习得来的词向量!也就是说,10000个单词的向量表示就是这个10000*300的矩阵,每行对应一个单词的向量表示。那么Skip-Gram最终的目的就是学习这个隐层的权重矩阵。而为什么针对词汇表里的单词要进行One-Hot编码,这里解释一下。如下图所示,如果我们用一个One-Hot向量乘以这个权重矩阵,那么得出的向量结果就是对应单词的特征表示。这意味着这个模型的隐层实际上只是作为一个查找表,而隐层的输出则是输入的单词的“词向量(word vector)”。
输出层为softmax回归分类器,每个输出神经元(词汇表中的每个单词都有一个对应的输出神经元)将产生0到1之间的输出,所有这些输出值的总和将等于1。具体来说,每个输出神经元都有一个权重向量,它将权重向量与隐层中的向量相乘,然后将指数函数应用于结果。最后,为了使输出之和达到1,我们将这个结果除以来自所有10,000个输出节点的结果之和。如下图所示:
如果两个不同的单词有非常相似的“上下文”(也就是说,它们周围可能出现什么单词),那么该模型应当为这两个单词输出非常相似的结果。 *** 输出这两个单词相似上下文预测的一种表达形式就是这两个单词的单词向量相似。换言之,如果两个单词有相似的上下文,那么该 *** 就有能力为这两个单词出学习相似的单词向量!
以上部分介绍了Skip-Gram模型的具体实现思路,接下来会针对Skip-Gram在实际训练中的一些问题进行优化。通过分析上述的Skip-Gram神经 *** 模型,可以发现一个问题,由于需要为每个单词学习一个固定长度的向量表示,因此以上面的例子为例,当需要训练10000个单词的300维的向量表示时,我们需要计算出300万个权重值。而在更大的数据集上,这样的训练过程是十分缓慢的,基本上不可行,因此Skip-Gram的作者针对这个问题提出了几种解决方案。常用的方案有Subsampling frequent words和Negative Sampling,接下来会详细介绍这两种解决方案。
Subsampling主要目的是通过削减训练集的训练样本数来降低训练代价。由于在文本中,许多单词出现的频率很高,这就导致了这个单词对应的word pair (inputword,outputword)在训练集中的数量会非常多,因此需要针对这些高频词进行二次采样以降低这些高频词在训练集中的规模。具体采样策略如下:
假设 w i 表示词汇表中的第 i 个单词, z(w i ) 表示该词在语料库中出现的频率。例如一个单词 w i 在大小为10000的语料库中出现的次数为100,那么 z(w i ) =0.01。知道了每个单词在语料库中的出现频率之后,那么对于每个单词 w i 的subsampling采样率如下:
该函数有一些有趣的点:
Subsampling虽然能明显地缩小训练神经 *** 模型时的训练集大小,但是并不能从根本上解决隐层矩阵规模大而带来的计算问题。也就是说,对于训练集中的每个样本,每次训练都需要更新隐层中的所有参数,因此Skip-Gram模型的作者又提出了另外一种方式来优化计算问题。
由于训练神经 *** 模型为了达到更高的精度,需要通过训练样本中每次细微地调整每个神经元的权重参数,因此每个训练每个训练样本都会微调神经 *** 中的所有参数。由于SubSampling在极限情况下,对训练集的削减程度不会低于原规模的3.3%,然而 ,这种程度的削减对于一个字典特别大的训练场景的影响是微弱的。为此作者又提出了一种Negative Sampling的方式。
Negative Sampling通过让每个训练样本只修改一小部分权重(而不是 *** 中的全部权重)来解决计算量特别大的问题。接下来可以看一下Negative Sampling的工作原理。
正常情况下,我们对每个单词语料训练神经 *** 模型,模型的输出是一个one-hot的向量。在Negative Sampling时,我们随机选择若干个(假设5个)negative word去更新对应的权重,(这里Negative word 对应的时One-Hot向量中值为0的单词,而我们的目标单词可以理解为Positive word,即对应One-Hot向量中值为1的单词)。
回想一下,我们的模型输出层有个300×10000的权重矩阵,如果每个训练样本只更新5个negative word和当前的positive word对应的权重,那么每次训练对应输出层只需要更新6*300个权重,此时更新比例只有6/10000=0.06%。
上面提到了,针对不同的数据集,Negative Sampling会选择2-20个negative word,下面介绍一下如何挑选这个Negative word。首先针对一个语料库,每次Negative Sampling挑选出的样本的可能性取决于该样本在语料库中出现的频数。
其中 f ( w i )表示单词 w i 在语料库中出现的频数。作者在他们的论文中指出,他们尝试了这个公式的一些变体,其中表现更好的是将每个单词出现的频数提高到3/4次方。如下所示:
处理一些样本之后会发现,与简单的公式相比,这个公式有增加不太频繁单词的概率和减少更频繁单词的概率的趋势。以上就是对Negative Sampling的一些简单描述。
Word Pairs and “Phrases”的主要思想是将经常成对出现或者某个短语当成一个Word,以此来降低整个训练过程中的计算复杂度。该 *** 在自然语言处理中有很大的应用场景。
参考:
1.
2.
究竟什么是Word2vec
1.相似词查找
2.词的特征扩充 在term weight 里很有用
3.关系挖掘
4.序列点击数据的分析
5.相关词挖掘 用在品牌词和品牌相似词挖掘中
7.作为系列的初始化输入特征
8,模型简单,效率高,易调参。
Word2Vec教程-Skip-Gram模型
原文: Word2Vec Tutorial - The Skip-Gram Model
skip-gram实际上是非常简单的神经 *** 模型形式;我认为任何所有微小的调整和变化都会使解释困扰。
我们进一步看,你可能在机器学习使用Word2Vec时用到下面一个技巧:使用一个隐藏层的简单神经 *** 来执行某个任务,但是接下来我们将不会在训练模型任务时使用那样的神经 *** ,而是仅仅是使用它来学习隐层神经 *** 的权重,在Word2Vec中指的是“词向量”。
现在我们需要讨论一下这种“伪”任务,我们要构建并运行神经 *** ,然后我们间接地获得到的后面所需的词向量。
我们要训练skip-gram神经 *** 做以下任务:给出一个句子中间的某个单词(输入词),观察输入单词旁边的单词并随机选择一个。而我们训练的神经 *** 将告诉我们词汇表中每个单词被选作为“邻近单词”(nearby word)的概率。
输出概率与输入单词与每个词汇表单词邻近程度相关。举例来说,训练的神经 *** 的输入单词为“苏联”,那么像“联盟”和“俄罗斯”的输出概率将会远大于像“西瓜”和“袋鼠”不相关单词的概率。
我们将通过“喂养”在训练文档中找到的“单词对”(word pair)来训练神经 *** 。下面的例子显示了一些训练样本(单词对),句子为“The quick brown fox jumps over the lazy dog.”,窗口大小为2,蓝色突出显示的是输入单词。
思考下,这些单词应该怎么被表示哪?
首先,我们不能够将单词作为一个字符串输入到神经 *** ,所以我们需要一种方式去表示单词。为了达到目的,我们从训练文档中创建一个单词词汇表,假如我们现在有一个具有10000个不同单词的词汇表。
我们将输入单词比如“蚂蚁”(ants)表示为一个one-hot向量,这种向量有10000个元素(词汇表中的每个单词都被表示为这种形式)。1 的位置对应该词在词典中的位置,其他全为0。
下面是我们神经 *** 的结构:
在隐藏层中没有使用激活函数,而在输出层使用了softmax,我们稍后在讨论这个原因。
假如,我们要学习有关词向量的300个特征(比如词性,语义等等),那么隐藏层结构将会表示为一个权重矩阵:10000行(代表着词汇表中的每个单词)和300列(代表每一个隐层的神经单元)。
现在你可能反问自己,-“one hot向量几乎全部是0,那么它的作用是什么呢?”如果你将一个1×10000 one hot向量乘以10000×300的矩阵,那么就会有效地选中矩阵中与1对应的行。下面是一个例子:
这就意味着模型中的隐藏层其实运作为一个单词查找表,隐藏层的输出为输入单词的“词向量”。
隐藏层产生的 1×300 的词向量将会传送到输出层,这个输出层是一个softmax regressio分类器,其要领就是每一个输出神经单元将会产生一个介于0到1的输出,并且所有输出值的和为1。
每个输出单元有一个权重矩阵,然后与来自隐藏层的词向量相乘,然后对结果运用 exp(x) 函数。最后,为了将输入结果加起来为1,我们将结果除以10000个输出节点的所有之和。
下面是单词“car”输出单元的计算。
到这里,我们来进一步了解下skip gram model。如果有两个不同的单词非常相似的“上下文”(就是,出现在这个两个单词周围的词语非常相似),对于这两个单词模型会输出非常相似的结果。如果两个单词的词向量非常相似,那么模型预测输出来的上下文也将是非常相似。
什么是所谓的两个单词有非常相似的上下文?我猜你想到近义词,比如“intelligent”和“ *** art”。或者是单词是非常相关的,比如“tran *** ission”和“engine”
你可能注意到 skip-gram 神经 *** 将包含一个非常大的weights向量。例如,一个带有300个特征,含有10000词的词汇表,那么在隐藏层和输出增将会产生3百万维的weights向量。在如此巨大的数据集训练代价将会是非常高的,接下来我们将会讲下word2vec作者优化的措施
【Word2Vec Resources】
Word2Vec教程-Negative Sampling 负采样
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。