版权声明:本文为博主原创文章,未经博主容许不得转载。算法
做者:寒小阳 && 龙心尘
时间:2016年6月
出处:
http://blog.csdn.net/han_xiaoyang/article/details/51567822
http://blog.csdn.net/longxinchen_ml/article/details/51567960
声明:版权全部,转载请联系做者并注明出处markdown
说明:本文为斯坦福大学CS224d课程的中文版内容笔记,已获得斯坦福大学课程@Richard Socher教授的受权翻译与发表ide
特别鸣谢:@Fantzy同窗对部份内容翻译的帮助
课堂笔记:第一部分函数
春季2016学习
关键词:天然语言处理(NLP).词向量(Word Vectors).奇异值分解(Singular Value Decomposition). Skip-gram. 词组的持续爆(CBOW),负采样样本(Negative Sampling)大数据
这是本课程的第一节,咱们会先介绍天然语言处理(NLP)的概念和NLP如今所面对问题;而后开始讨论用数学向量表明天然语言词组的设想。最后咱们会讨论现行的词向量构造方法。优化
在最开始我们先说说什么是NLP。NLP的目的是设计出算法,让计算机“懂得”人类的天然语言,从而为人类执行任务。这些任务分为几个难度等级,例如网站
容易的任务:ui
中等难度的任务:
比较有挑战的任务:
在处理全部NLP任务的时候,咱们首先须要解决很是重要的一个问题(多是最重要的):用什么方式将词组输入到模型中去。简单的NLP问题可能并不须要将词组做为独立个体对待(atomic symbols),但如今的问题绝大多数须要这样一个预处理,来体现词组之间关联/类似性和区别。因此咱们引入词向量的概念,若是把词编码成词向量,咱们很容易从向量的角度去衡量不一样的词之间的关联与差别(经常使用的距离测度法,包括Jaccard, Cosine, Euclidean等等,注:距离测度法,即用一个可观测度量的量来描述一个不能直接观测度量的量)。
咱们拿英文举例。
英语中大约有1300万个词组(token,自定义字符串,译做词组),不过他们所有是独立的吗?并非哦,好比有一些词组,“Feline猫科动物”和“Cat猫”,“Hotel宾馆“和”Motel汽车旅馆”,其实有必定的关联或者类似性在。所以,咱们但愿用词向量编码词组,使它表明在词组的N维空间中的一个点(而点与点之间有距离的远近等关系,能够体现深层一点的信息)。每个词向量的维度均可能会表征一些意义(物理含义),这些意义咱们用“声明speech”来定义。例如,语义维度能够用来代表时态(过去与如今与将来),计数(单数与复数),和性别(男性与女性)。
提及来,词向量的编码方式其实挺有讲究的。我们从最简单的看起,最简单的编码方式叫作one-hot vector:假设咱们的词库总共有n个词,那咱们开一个1*n的高维向量,而每一个词都会在某个索引index下取到1,其他位置所有都取值为0.词向量在这种类型的编码中以下图所示:
究其根本你会发现,是你开了一个极高维度的空间,而后每一个词语都会占据一个维度,所以没有办法在空间中关联起来。所以咱们可能能够把词向量的维度下降一些,在这样一个子空间中,可能本来没有关联的词就关联起来了。
这是一种构造词嵌入(即词向量)的方法,咱们首先会遍历全部的文本数据集,而后统计词出现的次数,接着用一个矩阵X来表示全部的次数状况,紧接着对X进行奇异值分解获得一个USVT的分解。而后用U的行(rows)做为全部词表中词的词向量。对于矩阵X,咱们有几种选择,我们一块儿来比较一下。
最初的想法是,咱们猜想相互关联的词组同时出如今相同的文件中的几率很高。例如,“银行”、“债券”、“股票”、“钱”等均可能出如今一块儿。可是,“银行”、“章鱼”、“香蕉”和“曲棍球”可能不会一直一块儿出现。基于这个想法,咱们创建一个词组文档矩阵X,具体是这么作的:遍历海量的文件,每次词组i出如今文件j中时,将Xij的值加1。不过你们可想而知,这会是个很大的矩阵R|V|×M,并且矩阵大小还和文档个数M有关系。因此我们最好想办法处理和优化一下。
咱们仍是用同样的逻辑,不过换一种统计方式,把矩阵X记录的词频变成一个相关性矩阵。咱们先规定一个固定大小的窗口,而后统计每一个词出如今窗口中次数,这个计数是针对整个语料集作的。可能说得有点含糊,我们一块儿来看个例子,假定咱们有以下的3个句子,同时咱们的窗口大小设定为1(把原始的句子分拆成一个一个的词):
1. I enjoy flying.
2. I like NLP.
3. I like deep learning.
由此产生的计数矩阵以下:
而后咱们对X作奇异值分解,观察观察奇异值(矩阵的对角元素),并根据咱们期待保留的百分比来进行阶段(只保留前k个维度):
而后咱们把子矩阵U1:|V|,1:k视做咱们的词嵌入矩阵。也就是说,对于词表中的每个词,咱们都用一个k维的向量来表达了。
对X采用奇异值分解
经过选择前K个奇异向量来进行降维:
这两种方法都能产生词向量,它们可以充分地编码语义和句法的信息,但同时也带来了其余的问题:
固然,有一些办法能够缓解一下上述提到的问题:
不过缓解终归只是缓解,我们须要更合理地解决这些问题,这也就是咱们立刻要提到的基于迭代的方法。
如今咱们退后一步,来尝试一种新的方法。在这里咱们并不计算和存储全局信息,由于这会包含太多大型数据集和数十亿句子。咱们尝试建立一个模型,它可以一步步迭代地进行学习,并最终得出每一个单词基于其上下文的条件几率。
词语的上下文:
一个词语的上下文是它周围C个词之内的词。若是C=2,句子"The quick brown fox jumped over the lazy dog"中单词"fox"的上下文为 {"quick", "brown", "jumped", "over"}.
咱们想创建一个几率模型,它包含已知和未知参数。每增长一个训练样本,它就能从模型的输入、输出和指望输出(标签),多学到一点点未知参数的信息。
在每次迭代过程当中,这个模型都可以评估其偏差,并按照必定的更新规则,惩罚那些致使偏差的参数。这种想法能够追溯到1986年(Learning representations by back-propagating errors. David E. Rumelhart, Geoffrey E. Hinton, and Ronald J.Williams (1988)),咱们称之为偏差“反向传播”法。
首先,咱们须要创建一个能给“分词序列”分配几率的模型。咱们从一个例子开始:
"The cat jumped over the puddle."(猫 跳 过 水坑)
一个好的语言模型会给这句话以很高的几率,由于这是一个在语法和语义上彻底有效的句子。一样地,这句”stock boil fish is toy”(股票 煮 鱼 是 玩具)就应该有一个很是低的几率 ,由于它是没有任何意义的。在数学上,咱们能够令任意给定的n个有序的分词序列的几率为:
有种模型是以{“The”, “cat”, ’over”, “the’, “puddle”}为上下文,可以预测或产生它们中心的词语”jumped”,叫作连续词袋模型。
上面是最粗粒度的描述,我们来深刻一点点,看点细节。
首先,咱们要创建模型的一些已知参数。它们就是将句子表示为一些one-hot向量,做为模型的输入,我们记为x(c)吧。模型的输出记为y(c)吧。由于连续词袋模型只有一个输出,因此其实咱们只需记录它为y。在咱们上面举的例子中,y就是咱们已经知道的(有标签的)中心词(如本例中的”jumped”)。
好了,已知参数有了,如今咱们一块儿来定义模型中的未知参数。咱们创建两矩阵,V∈Rn∗|V|和U∈R|V|∗n。其中的n是能够任意指定的,它用来定义咱们“嵌入空间”(embedding space)的维度。V是输入词矩阵。当词语wi(译注:wi是只有第i维是1其余维是0的one-hot向量)做为模型的一个输入的时候,V的第i列就是它的n维“嵌入向量”(embedded vector)。咱们将V的这一列表示为vi。相似的,U是输出矩阵。当wj做为模型输出的时候,U的第j行就是它的n维“嵌入向量”。咱们将U的这一行表示为uj。要注意咱们实际上对于每一个词语wi学习了两个向量。(做为输入词的向量vi,和做为输出词的向量uj)。
连续词袋模型(CBOM)中的各个记号:
那这个模型是如何运做的呢?咱们把整个过程拆分红如下几步:
用一幅图来表示就是下面这个样子:
经过上面说的种种步骤,咱们知道有了矩阵U、V整个过程是如何运做的,那咱们怎样找到U和V呢?——咱们须要有一个目标函数。一般来讲,当咱们试图从已知几率学习一个新的几率时,最多见的是从信息论的角度寻找方法来评估两个几率分布的差距。其中广受好评又普遍应用的一个评估差别/损失的函数是交叉熵:
结合咱们当下的例子,y只是一个one-hot向量,因而上面的损失函数就能够简化为:
咱们用c表示y这个one-hot向量取值为1的那个维度的下标。因此在咱们预测为准确值的状况下y^c=1。因而损失为 −1 log(1) = 0。因此对于一个理想的预测值,由于预测获得的几率分布和真实几率分布彻底同样,所以损失为0。如今让咱们看一个相反的状况,也就是咱们的预测结果很是不理想,此时y^c=0.01。计算获得的损失为−1 log(0.01) ≈ 4.605,损失很是大,本来这才是标准结果,但是你给了一个很是低的几率,所以会拿到一个很是大的loss 。可见交叉熵为咱们提供了一个很好的衡量两个几率分布的差别的方法。因而咱们最终的优化函数为:
很上面提到的模型对应的另外一种思路,是以中心的词语”jumped”为输入,可以预测或产生它周围的词语”The”, “cat”, ’over”, “the”, “puddle”等。这里咱们叫”jumped”为上下文。咱们把它叫作Skip-Gram 模型。
这个模型的创建与连续词袋模型(CBOM)很是类似,但本质上是交换了输入和输出的位置。咱们令输入的one-hot向量(中心词)为x(由于它只有一个),输出向量为y(j)。U和V的定义与连续词袋模型同样。
Skip-Gram 模型中的各个记号:
对应到上面部分,咱们能够把Skip-Gram 模型的运做方式拆分红如下几步:
用一幅图来表示这个过程以下:
咱们再次观察一下目标函数,注意到对整个单词表|V|求和的计算量是很是巨大的,任何一个对目标函数的更新和求值操做都会有O(|V|)的时间复杂度。咱们须要一个思路去简化一下,咱们想办法去求它的近似。
对于每一步训练,咱们不去循环整个单词表,而只是抽象一些负面例子就够了!咱们能够从一个噪声分布(Pn(w))中抽样,其几率分布与单词表中的频率相匹配。为了将描述问题的公式与负面抽样相结合,咱们只须要更新咱们的:
Mikolov ET AL.在他的《Distributed Representations of Words and Phrases and their Compositionality》中提出了负面抽样。虽然负面抽样是基于Skip-Gram 模型,它其实是对一个不一样的目标函数进行最优化。考虑一个“词-上下文”对(w,c),令P(D = 1|w, c)为(w, c)来自于语料库的几率。相应的,P(D = 0|w, c) 则是不来自于语料库的几率。咱们首先对P(D = 1|w, c)用sigmoid函数建模:
注意这里的D˜表示“错误的”或者“负面的”语料库,像句子”stock boil fish is toy”就是从这样的语料库来的。不天然的句子应该有比较低的发生几率,咱们能够从词库中随机采样来产生这样的“负面的”语料库。咱们的新目标函数就变成了:
在这里{u˜k|k=1,⋯,K}是从(Pn(w))中抽样取到的。须要多说一句的是,虽然关于怎么样最好地近似有许多讨论和研究,可是工做效果最好的彷佛是指数为3/4的一元语言模型。至于为何是3/4,下面有几个例子来帮助你们感性地理解一下:
你看,通过3/4这样一个指数处理,”Bombastic”(少见)被采样的几率是以前的3倍,而“is”这个词(多见)被采样的几率只是稍微增加了一点点。