本文介绍一种基于神经网络结构的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维的向量,那么隐层可以由一个10000300的矩阵来表示(300个神经元,每个神经元都有一个10000维的权重向量),如下图所示。
竖着看这个隐层的权重矩阵,每一列对应一个神经元中的参数向量,而如果横着看这个权重矩阵,每一行就是一个300维的向量,而这这就是我们需要通过学习得来的词向量!也就是说,10000个单词的向量表示就是这个10000300的矩阵,每行对应一个单词的向量表示。那么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 ) =001。知道了每个单词在语料库中的出现频率之后,那么对于每个单词 w i 的subsampling采样率如下:
该函数有一些有趣的点:
Subsampling虽然能明显地缩小训练神经网络模型时的训练集大小,但是并不能从根本上解决隐层矩阵规模大而带来的计算问题。也就是说,对于训练集中的每个样本,每次训练都需要更新隐层中的所有参数,因此Skip-Gram模型的作者又提出了另外一种方式来优化计算问题。
由于训练神经网络模型为了达到更高的精度,需要通过训练样本中每次细微地调整每个神经元的权重参数,因此每个训练每个训练样本都会微调神经网络中的所有参数。由于SubSampling在极限情况下,对训练集的削减程度不会低于原规模的33%,然而 ,这种程度的削减对于一个字典特别大的训练场景的影响是微弱的。为此作者又提出了一种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对应的权重,那么每次训练对应输出层只需要更新6300个权重,此时更新比例只有6/10000=006%。
上面提到了,针对不同的数据集,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 http://mccormickmlcom/2016/04/19/word2vec-tutorial-the-skip-gram-model/
2 http://mccormickmlcom/2017/01/11/word2vec-tutorial-part-2-negative-sampling/
onehot是从0开始的
one-hot编码是将类别变量转换为机器学习算法中容易处理的一种形式。One-hot是转化为n个特征,是对所有的状态都会进行编码。
title: 自然语言处理综述
date: 2021-11-18 11:03:11
自然语言是指人类日常使用的语言,比如:中文、英语、日语等。自然语言灵活多变,是人类社会的重要组成部分,但它却不能被计算机很好地理解。为了实现用自然语言在人与计算机之间进行沟通,自然语言处理诞生了。自然语言处理(Natural Language Processing, NLP)是一个融合了语言学、计算机科学、数学等学科的领域,它不仅研究语言学,更研究如何让计算机处理这些语言。它主要分为两大方向:自然语言理解(Natural language Understanding, NLU)和自然语言生成(Natural language Generation, NLG),前者是听读,后者是说写。
本文将从自然语言处理的历史与发展讲起,进而分析目前深度学习在自然语言处理领域的研究进展,最后讨论自然语言处理的未来发展方向。
1950年,计算机科学之父图灵提出了“图灵测试”,标志着人工智能领域的开端。而此时,正值苏美冷战,美国政府为了更方便地破译苏联相关文件,大力投入机器翻译的研究,自然语言处理从此兴起。从这之后的一段时期内,自然语言处理主要采用基于规则的方法,这种方法依赖于语言学,它通过分析词法、语法等信息,总结这些信息之间的规则,从而达到翻译的效果。这种类似于专家系统的方法,泛化性差、不便于优化,最终进展缓慢,未能达到预期效果。
到了20世纪80、90年代,互联网飞速发展,计算机硬件也有了显著提升。同时,自然语言处理引入了统计机器学习算法,基于规则的方法逐渐被基于统计的方法所取代。在这一阶段,自然语言处理取得了实质性突破,并走向了实际应用。
而从2008年左右开始,随着深度学习神经网络在图像处理、语音识别等领域取得了显著的成果,它也开始被应用到自然语言处理领域。从最开始的词嵌入、word2vec,到RNN、GRU、LSTM等神经网络模型,再到最近的注意力机制、预训练语言模型等等。伴随着深度学习的加持,自然语言处理也迎来了突飞猛进。
接下来,我将介绍自然语言处理与深度学习结合后的相关进展。
在自然语言中,词是最基本的单元。为了让计算机理解并处理自然语言,我们首先就要对词进行编码。由于自然语言中词的数量是有限的,那就可以对每个词指定一个唯一序号,比如:英文单词word的序号可以是1156。而为了方便计算,通常会将序号转换成统一的向量。简单做法是对单词序号进行one-hot编码,每个单词都对应一个长度为N(单词总数)的向量(一维数组),向量中只有该单词序号对应位置的元素值为1,其它都为0。
虽然使用one-hot编码构造词向量十分容易,但并不是一个较好的方法。主要原因是无法很好地表示词的语义,比如苹果和橘子是相似单词(都是水果),但one-hot向量就无法体现这种相似关系。
为了解决上述问题,Google的Mikolov等人于2013年发表了两篇与word2vec相关的原始论文[1][2]。word2vec将词表示成一个定长的向量,并通过上下文学习词的语义信息,使得这些向量能表达词特征、词之间关系等语义信息。word2vec包含两个模型:跳字模型(Skip-gram)[1] 和连续词袋模型(continuous bag of words,CBOW)[2],它们的作用分别是:通过某个中心词预测上下文、通过上下文预测某个中心词。比如,有一句话"I drink apple juice",Skip-gram模型是用apple预测其它词,CBOW模型则是用其它词预测出apple。
首先介绍CBOW模型,它是一个三层神经网络,通过上下文预测中心词。以某个训练数据"I drink apple juice"为例,可以把apple作为标签值先剔除,将"I drink juice"作为输入,apple作为待预测的中心词。
Skip-gram模型与CBOW类似,也是一个三层神经网络模型。不同在于,它是通过中心词预测上下文,即通过"apple"预测出"I drink juice"。接下来简单介绍Skip-gram模型中各层:
两种模型训练结束后,会取 作为词向量矩阵,第i行就代表词库中第i个词的词向量。词向量可用来计算词之间的相似度(词向量点乘)。比如,输入 I drink _ juice 上下文,预测出中心词为apple、orange的概率可能都很高,原因就是在 中apple和orange对应的词向量十分相似,即相似度高。词向量还可以用于机器翻译、命名实体识别、关系抽取等等。
其实这两种模型的原型在2003年就已出现[3],而Mikolov在13年的论文中主要是简化了模型,且提出了负采样与层序softmax方法,使得训练更加高效。
词向量提出的同时,深度学习RNN框架也被应用到NLP中,并结合词向量取得了巨大成效。但是,RNN网络也存在一些问题,比如:难以并行化、难以建立长距离和层级化的依赖关系。而这些问题都在2017年发表的论文《Attention Is All You Need》[4]中得到有效解决。正是在这篇论文中,提出了Transformer模型。Transformer中抛弃了传统的复杂的CNN和RNN,整个网络结构完全由注意力机制组成。
Transformer最核心的内容是自注意力机制(Self-Attention),它是注意力机制(Attention)的变体。注意力的作用是从大量信息中筛选出少量重要信息,并聚焦在这些信息上,比如:人在看一幅图像时,会重点关注较为吸引的部分,而忽略其它信息,这就是注意力的体现。但注意力机制会关注全局信息,即关注输入数据与输出数据以及中间产物的相关性。而自注意力机制则减少了对外部其它数据的关注,只关注输入数据本身,更擅长捕捉数据内部的相关性。
自注意力机制的算法过程如下:
自注意力机制不仅建立了输入数据中词与词之间的关系,还能并行地高效地计算出每个词的输出。
Transformer的总体架构如下:
它分为两部分:编码器(Encoder)和解码器(Decoder)。
编码器的输入是词向量加上位置编码(表明这个词是在哪个位置),再通过多头自注意力操作(Multi-Head Attention)、全连接网络(Feed Forward)两部分得到输出。其中,多头自注意力就是输入的每个词对应多组q、k、v,每组之间互不影响,最终每个词产生多个输出b值,组成一个向量。编码器是transformer的核心,它通常会有多层,前一层的输出会作为下一层的输入,最后一层的输出会作为解码器的一部分输入。
解码器包含两个不同的多头自注意力操作(Masked Multi-Head Attention和Multi-Head Attention)、全连接网络(Feed Forward)三部分。解码器会运行多次,每次只输出一个单词,直到输出完整的目标文本。已输出的部分会组合起来,作为下一次解码器的输入。其中,Masked Multi-Head Attention是将输入中未得到的部分遮掩起来,再进行多头自注意力操作。比如原有5个输入,但某次只有2个输入,那么q1和q2只会与k1、k2相乘,。
如果深度学习的应用,让NLP有了第一次飞跃。那预训练模型的出现,让NLP有了第二次的飞跃。预训练通过自监督学习(不需要标注)从大规模语料数据中学习出一个强大的语言模型,再通过微调迁移到具体任务,最终达成显著效果。
预训练模型的优势如下:
预训练模型的关键技术有三个:
关于预训练模型的架构,以Bert为例:输入是词的one-hot编码向量,乘上词向量矩阵后,再经过多层transformer中的Encoder模块,最终得到输出。
本文介绍了NLP领域的流行研究进展,其中transformer和预训练模型的出现,具有划时代的意义。但随着预训练模型越来越庞大,也将触及硬件瓶颈。另外,NLP在一些阅读理解、文本推理等任务上的表示,也差强人意。总而言之,NLP领域依旧存在着巨大的前景与挑战,仍然需要大家的长期努力。
[1]Mikolov, T, Sutskever, I, Chen, K, Corrado, G S, & Dean, J (2013) Distributed representations of words and phrases and their compositionality In Advances in neural information processing systems (pp 3111-3119)
[2]Mikolov, T, Chen, K, Corrado, G, & Dean, J (2013) Efficient estimation of word representations in vector space arXiv preprint arXiv:13013781
[3]Yoshua Bengio, R´ejean Ducharme, Pascal Vincent, and Christian Janvin A neural probabilistic language model The Journal of Machine Learning Research, 3:1137–1155, 2003
[4]Vaswani A, Shazeer N, Parmar N, et al Attention is all you need[C]//Advances in neural information processing systems 2017: 5998-6008
[5]Peters M E, Neumann M, Iyyer M, et al Deep contextualized word representations[J] arXiv preprint arXiv:180205365, 2018
[6]Radford A, Narasimhan K, Salimans T, et al Improving language understanding by generative pre-training[J] 2018
[7]Devlin J, Chang M W, Lee K, et al Bert: Pre-training of deep bidirectional transformers for language understanding[J] arXiv preprint arXiv:181004805, 2018
[8]Houlsby N, Giurgiu A, Jastrzebski S, et al Parameter-efficient transfer learning for NLP[C]//International Conference on Machine Learning PMLR, 2019: 2790-2799
字符串-索引变换,就是将某些标签的字符串列编号变成标签索引项。标签索引项序列的取值范围就是
[0,numLabels](这里的numLabels是所有出现的单词去掉重复的词后的总和)。
这里的标签索引项顺序就是按照标签出现的频率来排序的,出现最多的标签索引就是0(倒序)。
如果输入是数值型,先将数值映射到字符串,再对字符串进行索引化 。
与StringIndexer对应,IndexToString是将索引化标签还原成原始的字符串。
使用场景:在通过StringIndexer产生索引化标签,然后使用索引化标签进行训练,最后对预测结果使用IndexToString来获取其原始的标签字符串。
结果显示:
StringIndexer还有一个setHandleInvalid()的方法,通常是因为构建了一个StringIndexer实例,对DataFrame1进行fit后,再对DataFrame2进行transform,DataFrame2中出现了DataFrame1中未曾出现的标签,这时候可以通过设置setHandleInvalid(“skip”)来忽略新标签的行;
当然setHandleInvalid(“keep”)则保留。
不过奇怪的是,在实际工作中,发现fit和transform同一个Dataframe时,也有可能报这个错
可以将离散特征通过one-hot编码映射到欧式空间,而我们常用的距离或相似度的计算都是基于欧式空间的。
将一列标签索引映射到一列二进制向量,最多只会有一个单值(只有一个1)。
如果是有4个标签索引:1,2,3,4
那么对应的One-hot为[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]
结果显示:
注意:有一个方法 setDropLast,是否丢弃最后一个数,默认为true,观察上面的结果发现categoryIndex最大的20,经过OneHot得到的categoryVec为(2,[],[]),最大的categoryIndex被丢弃了。
不过在设置setDropLast(false)后,
欢迎分享,转载请注明来源:品搜搜测评网