lecture4-神经网络在语言上的应用
Hinton第四课
这一课主要介绍神经网络在语言处理上应用,而主要是在文本上,并附上了2003年Bengio 等人的19页的论文《A Neural Probabilistic Language Model》,觉得不错,打算看看翻译了之后在传上来,虽然不是做这方面的,但是多懂些其他领域的东西也好。
一、学习去预测下一个单词
通过使用BP去学习单词意思的特征表征,这里先介绍一个1980年代的一个例子,当时的计算机硬件和软件都没达到现在的水平,但是这个简单的例子有助于理解如何使用BP将相关的信息映射到特征向量中去:
上图就是一个简单的家庭树关系,等号表示结婚关系,然后往下是他们的子女,这里是通过训练网络来理解这个家庭树中的信息,上图中上半部分是来自于英国的,下半部分就是另一个的家庭树来自意大利,它和上面的家庭树有着很相似结构,当试图在这种数据的两个集合上训练时,NN有能力去进行分析。这些家庭树中的信息都可以表示成命题集合的形式,可以通过关系词来表示这些关系(参考一门课程叫数理逻辑,这种表示法也是当年人工智能火过一段时间的)比如:son,daughter,nephew niece,father,mother,uncle,aunt等等。
所以上述这种任务可以被看成是在使用大量的三元组的形式来表现这些树中的信息,现在这种显而易见的表示方法就是符号规则。例如,X有母亲Y,Y有丈夫Z,zhe就意味着X有父亲Z。
虽然这种规则可以用来表示关系,但是却需要在一个相当大的概率离散空间中进行搜索。一个不同的方法就是通过NN来时图抓取同样的分布信息,NN可以通过一个实值权值的连续空间来试图抓取这些信息,即通过前两个的给定,能否得到第三个信息比如上面的X的父亲是Z:
如上图所示,在这个表格的底部,输入的就是人员和关系,然后这些信息就会往上一直的馈送,就可以学习到的人员2与人员1和他之间的关系(个人:这里的人员2是不是类似于以前的标签)。上图的NN是手动写的,不是自动生成的,所以层数上因不同的设计者而异,而且还能自己决定在哪里放入一个bootle neck来学习有趣的表征。所以上图中的结构底部的块,一个人员一个局部编码,这里有24个人,所以就会有24个神经元,在每个训练情况下,其中的一个神经元就会激活。右边的关系块上,有12个关系,所以在每个训练情况下,其中的一个神经元就会激活,这说明底层的神经元是唯一的,那么在输出层上也是这样有着24个人员神经元,来表示底层的人员和关系。因为这里的神经元都是按照人数给定的,所以差不多人员之间不会有相似的情况出现,所有的两个两个人员之间的都是不相似的。这里介绍的NN不是用符号来解释的。从底往上第二层,就是分布编码层,这里的神经元肯定比底层的少(Hinton说这里就6个神经元),这里就通过神经元的激活来表征下面的信息,并且希望当学习这些命题的时候,是通过激活值来表示的。这NN可以构建这个家庭树的任务,也可以构建这种关系树领域,我们所要作的就是在这112个(这个例子中给的命题)命题上进行训练,并多次的训练(batch training)。在通过观察倒数第二层中左边的观察,
上图就是6个神经元的状态(6个类似五线谱的矩形),是对person one的编码,并且这里有着24个人(先不看上面的人名,上面的人名是说这个16线谱上面一排对应的英国人,所以下面一排对应的是意大利人),12个来自于英国家庭(上面的两个家庭树的上面一个),12个来自于意大利家庭(上面两个家庭树的下面一个),所以每个神经元连接着24个输入(就是一个16线谱上的24个点),每个点就表示连接着一个输入的权值。如果观察上图中这个大的灰色矩形中的右上角,会发现一个有趣的权重结构。上面一层的权值是来自于第一家英国人,都显示是正的(白色代表正的,黑色代表负的),下面一层的权值都是负的,这说明这个单元告诉我们输入的这个人是否是英国人还是意大利人,虽然我们没有明显的获得这种信息,但是这种信息在很多情况下却非常有用,这是因为在家庭树结构(这里的例子)中,如果输入的是个英国人,输出的也是个英国人。所以这里的某些权值其实已经可以预测出有关输出的一些信息了,这里是说他这里就有了一半的概率。如果看着右边往下第二个,可以发现在开头有4个大的真的权值,这些相对应于Christopher和Andrew和相对于意大利人的权重一样,然后还有一些小的权重,然后是两个大的负的权重,这相对应于Collin和他相对的意大利人是权重相同的,然后接着又是四个大的正的权重,相对应于Penelope和Christina,然后接着是两个大的负权重结尾,相对应于Charlotte和他对应的意大利也是相同的,从之前的树结构中发现这个神经元表达的是代数,大的正的权重表现的是最老的一代,大的负的权重表现的是最年轻的一代,接近0的权重表现的是中间的一代。最后,如果观察左边最后一个神经元,会发现一个不同的结构,如果观察这个神经元的上面一层的负权重,会发现有Andrew,James,Charles,Christine,Jennifer,如果再去观察这个家庭树,会发现这几个人都在树的右边,这个神经元表示的是在家庭树结构中的位置关系,这个特征对于这个模型的预测结果来说也是很重要的。
现在看之前的中间那层 所谓的bottleneck 层,我们之前没有去指定什么样的特征,没有指定之前的那些是否是老外,是否是第几代还是在树的什么位置,但是这些都是对这个任务的很好的规律的表现,当然这些都只有在输出结果之前的网络都有着相似的表征结构的时候才是有用的(不同的网络结构有可能抓取的特征就不是这些了)。中间那层是使得输入的人和关系表示的特征如何来预测输出的人。例如:如果输入的人是第三代,关系是需要代数上升(比如谁是他爹这种),那么输出的人就会是第二代的,但是注意到这个规则,必须提取第一层隐藏层的合适的特征和生成给输出层前的隐藏层合适的特征结果过,所以这一层也是需要正确发挥作用的。
另一种方法去看待这个网络怎么工作的:用108个三元组来训练,把剩下的4个挑出来的(held-out)的用来预测,Hinton的结果显示有2个或者3个是正确的,这对于这么点的数据量来说还算不是很糟糕,如果数据量很大的话,那么结果就会好起来的。
上面的是1980年代的一个小实验,现在我们拥有了更好的计算机和数以百万级的数据量,这样的话,就算对于庞大的数据量的查询,比如输入一个人和查询他的父母,那么结果也会是很准确而且轻松的(这就是索引啊)而且输入一个人出生在1902年(举个例子),这个模型也会告知这是错误的,就是换个想法,不是用三元组中前两个来预测第三个,而是将三元组的三个都输入进去,让网络告知这是不是对的(感觉好像真正的大脑),但是这就需要所有的正确的样本和大数量的输出,而且也需要很好的错误数据来让网络知道哪些是错的(这感觉好像是婴儿学习一样)。
二、认知科学中一个简短的介绍
这部分对于学工程的来说估计觉得不太适用,是适用学理论的。在计算机科学中,早在100年前,就有关概念的特征向量表征和不同概念表征之间的关系的争论。
在认知科学中,有两种声音,关于什么是概念的问题:
特征原理:一个概念就是一些语义特征的集合。这可以很好的解释概念之间的相似性而且也方便用特征激活向量来表示概念来进行机器学习
结构原理:概念的意义是介于与其他概念之间的关系上的,所以概念应该最好表示成一张关系图,而不是特征向量,在1970年Marvin Minsky 就将感知机的局限性作为反对特征向量的证据并大力支持关系图的一边。
可是Hinton认为,两个都是错的,一个NN能够用语义特征向量来执行得到一个关系图,在上面的例子中,没有显然的推导需要去解释显而易见的事实结果,因为NN是自动学习特征,而且还能完整的表达关系图的形式,如果研究NN就会发现都是一些概率特征来互相的推导而已,称这些为microfeatures就是因为他们不像那些显式的特征。在大脑中,有成百上千万的交互,并且对这些所有的交互都有结果。这其中并没有特意主观的去干扰,但是有很多基于神经元的交互式的计算,所以可以使用显式的规则去有意识的理解,特别是在分析上,但是在结果执行上,却没有主观的干扰。所以需要知道应用了哪些规则以至于不会做无用功。所以对于许多人来说,当他想在NN中执行一个关系图的时候,只需要假设应该建立一个神经元去对应关系图中的点,并且建立之间的连接,但是这并不奏效。这是因为(1)人们对关系的看法不同,这就需要很多不同的关系,但是NN中一个连接并没有不同的标签,只有数值而已,而且(2)还需要三元关系例如:A在B和C之间。如何在NN中正确的去表示关系现在仍然是个问题。但是Hinton说可以将许多的神经元用来表示一个概念,每个神经元却也可以包含在同一个概念之中(个人猜测:这是不是可以叫做Network In Network 虽然这个是这几年出现的一个论文的名称,不过这个想法也真心好),这也被称之为“distributed representation”分布表征,这样可以得到很多的神经元之间的不同的映射。
三、softmax输出函数
这是一种将NN的输出值进行相加到一个神经元上 并且可以来表示一个谨慎互斥的概率分布(这里的谨慎说的是给出很详细的比例不会一刀切那种,互斥说的是最后的分类只属于一类)。到目前为止对于训练一个NN采用的都是误差平方和的方法,对于线性神经元来说,这是很适合的。但是误差平方和的方法有很多缺点:如果一个合理的输出是1,但是实际上最后的逻辑神经元输出的却是0.0000000001,这对于逻辑单元来说几乎没法做误差梯度,因为这差不多在一个高原上 而下降的范围却总是在水平面上,而且即使最后犯的错误很明显的情况下,还是会导致需要花很长很长的时间去改变一点点的权值,而且如果试图去指派不同的概率来表现互斥的类别标签,虽然输出的最后是1(所有概率的和一定是1),但是得到的A的概率却有可能和B的概率一样大(就是在输出层采用了多个逻辑单元来表示多类,但是却有可能得到两个类别一样的概率的情况)。这时候就会想,是不是cost函数可以换个更好的?既能表达互斥的结果,还能是一个合适的概率型的cost函数。有啊。
softmax是一种最大函数的软连续版本。softmax中的单元接受下层的所有的输入并进行整层的计算输出。图中的Zi是下层中第 i 个单元,也被称之为 “logit” ,输出的 yi,不单单依赖Zi,而是依赖于所有的Z,所以对于softmax的一层来说他的每个单元的计算是通过上图的右边的式子得到的,而且这里的每个 yi 都是介于0 1 之间的,而且他还有着良好的求导式子,虽然说Yi是依赖所有的Z的改变而改变的,但是在softmax层中一个单元对应的一个输入的导数就是上图中右下角显示的。如果想很好的区分这些式子,需要记得之前中分母中的归一化项(就是所有的神经元的和),因为这很容易被遗忘而造成结果错误。
如果我们使用了softmax作为输出层,那么什么cost函数才适合呢?
答案就是关于正确结果的错误log概率,这就是我们想要最大化这个log概率来得到正确的结果。所以上图右上角的式子,是通过将真实目标值和softmax预测的输出log值相乘,这个被称之为交叉熵损失函数(图中是单样本情况,而且这里的Zi 其实等于Wi * xi ,只是这里没写出来,所以在真实计算的时候要注意这点)。它有着很好的特性,因为假设一个神经元的输出是很接近0 的时候而他的真实值却是很接近1 那么,交叉熵损失函数就会很大,而且上图中的0.000001比0.0000000001好的原因是后者得到的惩罚更重,说明他分类比前者的还不靠谱。而且这个交叉熵损失函数的偏导可以很好的解决之前的损失平方函数的导数的问题,所以上图求导结果,也就是权值的改变梯度 yi-ti,可以从-1到+1,但是当两者相差差不多的时候这个值就会接近于0,也就是 这个输出值是接近真实目标值的,那么这个神经元所对应的权值就不会怎么变,其他错误的神经元对应的权值就会不断的改变直到最后收敛。(这里还可以看Ng 的UFLDL 里面有更详细的说明)
四、神经概率语言模型
这部分说的是关于表示单词的特征向量的实际使用。在语音识别系统中,有一种想法是如何让系统自己去很好的预测下一个即将出现的单词。当我们试图去做语音识别的时候,在一个嘈杂的环境下是不能很完美的识别音素(phonemes)的,因为在有噪音的情况下声音的输入本身就不够好。会有好几个不同的单词去很好的匹配声音信号(beach speech,如果加点噪音就没法很好的区分两者)人类不太注意这些细节是因为我们可以通过句子的意思去很好的上下文理解正确的单词,而这一切我们都是无意识的。所以一个语音识别者(人类)能够在理解语义的情况下事先预测下一个将要出现的单词,很幸运的是单词可以在不全部理解的情况下(理解句子的部分语义)很好的进行预测:
在语音识别中一个标准的方法就叫做“trigram”方法,通过得到大量的文本并且计算所有三元单词组(单词1,单词2,单词3)出现的频数,然后通过使用这些频数来计算在给定前两个单词的情况下预测第三个单词是什么,所以如果我们听到单词A和单词B,可以通过之前在大量文本中频数的计算得到序列ABC和ABD的概率,然后说下一个单词会是C因为这个概率更大。直到不久前,这种方法还是 state-of-the-art方法,但是这种方法无法使用更大的上下文,因为会有太多的不确定概率出现,而且如果使用了更大的上下文,那么这种频数差不多就是0(比如一句古文,它在一本课本中只出现一次,但是其中三个相连的单词,三元单词却出现很多次,所以用更大上下文的频数这种方法行不通)而且有些三元单词 组我们未必听过,当频数很低的时候,这时候就需要后退到一个独立的单词,例如 输入前两个单词“dinosaur pizza”,这个之前完全没听过(就是不在训练集中,频数为0),没法预测下一个单词是什么,所以只能预测pizza 下一个单词一般是什么,但是不能说因为不在训练集中,就说后面没有单词出现,那么这也不叫预测了。
但是如果仅仅依靠三元单词组来预测,那势必丢失了很多上下文的信息,如果能够抓取更多的信息,那么就更有助于预测下一个单词
如上图举的例子:假设之前有个句子“the cat got squashed in the garden on friday”,那么他有助于预测下面句子中的单词,因为模式类似,但是三元单词组没法理解cat/dog的相似性,所以为了解决这种局限性,可以通过将单词转化成具有语义和综合之前单词的特征,并用这些去预测下个单词的特征,然后在转化成下一个单词。
上图是Bengio的NN用来预测下一个单词,终于到这课的正主了,上图其实有些像之前说的有关家庭树的网络结构,只是这个网络应用于一个更真实的问题,而且网络结构更大,这个结构的底层是输入的单词的索引值,和之前的家庭树的NN一样,可以想象成很多个神经元在一起,这层网络的激活值和与之相连接的权重会决定隐藏层的激活值,而这些权重就可以用来表示单词的分布表征了,这也就是特征向量,但是这部分只能说是“table look-up”,在通过层层训练的过程中,表示单词的特征会不断的变化,在从底层得到输入单词表示的特征后,通过分布式编码,然后得到能够表示将会出现的下个单词的特征。将使用底层提取到的分布式独立单词的特征跳过一层链接直接到达softmax,这样的结构可以使得网络更好的工作。因为这个结构中单独的输入单词是具有独立信息的,所以也具有输出独立单词的信息。在实际结果上,bengio的网络的预测下一个单词的结果比Trigram的预测结果要稍微差一点,但是如果将两个相对比,还是能够发现NN的网络的改善的地方,因为现在这些使用单词的特征表征的语言模型已经相当大的改善(上图中的模型是03年的,现在过了至少10年了,肯定有很大改进的)所以现在已经比trigram模型好很多了。一个伴随着巨大softmax输出层的问题是,有可能需要处理1000,000个不同的输出,而且单词的复数形式不同于单数形式,动词的时态问题也是不同的,所以才会造成有这么大数量的权重链接。
但是为了避免过拟合,当训练样本不足够的时候,不需要设置太多的隐藏单元,只有如同Google这样的大数据公司才会需要设置这么庞大的softmax的连接,但是当设置最后一层隐藏层的单元较少的时候,就很难使得100,000个结果是正确的了,而且还会使得输出的很多结果是没法决定的,比如最后需要结构设计人员去确定两个不同而且没什么关系的单词,哪个更加的常见,更好的用来作为下一个输出。现在需要解决的问题就是是否有更好的方法来处理这样大数据的输出?
五、神经概率语言模型中大量可能输出的处理方法
如何避免使用100,000个不同的输出单元呢,如果想要输出100,000个不同的单词的概率。Hinton的处理方法是将它们放在一个2D空间中,然后观察他们之间的相似性,这也给出了NN可以学习什么的大致情况,去试图预测下一个单词或者语句中中间的单词。为了避免使用100,000个输出单元的一个方法是每次只输出一个单词:
如上图,输入包含着之前单词的上下文,并插入一个候选单词。然后这个网络的输出是一个得分,关于这个输入的组合的评价,这个候选单词的对应前面输入单词的合适程度,这就意味着需要运行这个网络很多很多次,但是因为大部分的工作可以进行共享,这就可以使用一种串行结构,上下文部分的输入结构相同的,将候选单词作为下个将要输出的单词也放入上下文单词结构中(上图中就是),然后前馈网络得到一个结果关于这种组合的得分,所以在上下文中需要输入到最后隐藏层的之前的单词的部分都是可以相同的,唯一不同的就是候选单词的部分,也就是说上面的网络 其实是将候选单词部分一次一个的进行训练。这也使得每次需要调整的权值就不是很多了。
在串行结构中的学习过程:首先计算每个可能的候选单词的得分并将所有的得分放入一个大的softmax中去得到单词的概率。现在这个单词的概率和他们的目标概率之间的区别就可以用交叉熵损失函数求导表示,通过导数逼近到正确的结果。还可以通过之使用小数量的候选单词,可以通过其他的预测器先预测排除一些完全没必要计算的候选单词,例如先使用trigram计算候选单词,然后将这些单词放入上图的网络进行第二次的预测。
另一种避免使用100,000softmax单元的方法是通过预测一个树结构上的路径来预测下一个单词:
通过将所有的单词都安排进一个树结构,每个单词就是叶子节点,然后使用之前单词的上下文去生成一个预测向量 v ,然后将这个预测向量与每个节点学到的向量进行比较,这里的比较是通过两个向量的乘积得到的,然后应用逻辑函数并给出右子树与左子树的结果,上图中的sigma可以是逻辑函数,通过1 - 右子树的结果来作为左子树的结果。所以当我们学习的时候,是使用之间的相关联系来生成一个预测向量的。
在这个例子中,是使用一个简单的NN,简单的处理每个单词的存储的,学到的表征,并使用这些特征向量去生成预测向量,如上图左边,也就是上上图中的 v 的生成过程。在上图右边中有节点i,j,m这条红色的路径显示是真实的正确的路径,也是我们需要在训练的时候考虑到的。我们希望我们预测的和真实的尽可能的接近,所以我们也希望学习得到的路径尽可能的与红色路径吻合。
因此提出了一个轻量级的分解,当我们试图最大化当前目标单词的概率的时候,可以试图将导致达到目标单词的路径上所有的log概率的累加和最大化(上上图中红色路径涉及的部分),所以在训练的时候,只需要考虑当前路径上的点,这相比较于整个树结构来说,显得数据量不是那么恐怖,所以这就相当于log_2(N)代替了N个节点的考虑量。对于每个节点来说,我们知道当前的分支,(因为我们知道下个单词是什么,树枝上连接着的下一个单词),通过对这些分子的当前概率进行计算并对比,所以可以得到预测向量v和学到节点u的导数,这种只考虑当前路径的方法也使得训练时间大大缩短,但是不幸的是,这仍然很慢。而且在测试的时候,需要知道许多其他的单词的概率以便帮助语音识别的人员来确定,所以不能只是考虑一条路径。
有一些更加简单的方法去学习单词的特征向量:
上图就是有Collobert和Weston提出的结构,他们所作的就是学习单词的特征向量,结果显示他们学到的特征向量对于整个不同的NLP的分支任务都是很好的,具有泛化性。他们不试图预测下个单词,他们只是试图得到单词的好的特征向量,所以他们使用以往的上下文和特征上下文。所以他们一个窗口有着11个单词,5个是以往的,5个是未来的,中间这个窗口,放的是当前的单词,这个当前的单词有可能是真实存在于文本中的,或者是随机得到的。然后训练一个NN来生成一个输出,如果这个输出正确的,那么结果是很大的,如果是随机的,那么结果是很小的。这个NN的工作原理和之前的一样。我们关注其中的单词的特征向量提取的部分,单词编码的部分,和在NN中使用这些特征向量,在NN中有着更多层的概率可以去试图预测这个单词是否在上下文文本中。所以他们实际的工作就是判别中间这个单词是否是这5个单词上下文的合适的单词。他们在维基百科上提取了600百万个样本,并且得到的特征向量对于不同的NLP任务来说都是好特征。可视化学到的单词特征是否有意义的方法是将结果映射到2D空间中,我们所要作的就是以这种方法来显示单词向量并找到相近的单词向量。所以这样就能发现NN认为哪些单词是相似的意思的。可以通过使用一种多尺度方法称之为 “t-sne”来同样的显示相似的聚类。 t-sne 不但能够将相似的单词放在一起,还能将相似的类别放在一起,所以它可以在不同的缩放的尺度下工作。我们看到的这些学到的特征向量抓取了大量的微妙的语义分布信息,数据都只是从维基上抓取而已,没有人告诉这个网络结构任何信息,只是在输入部分说这11个单词是在一个字符串中的,更令人惊讶的是这个网络最后预测得到的上下文单词的信息显示他知道这些单词的意思,而这也是很多人类主要学习外文单词的方法。举个例子:如果对一个人 说 一句他从未听过的语句 “she scrammed him with a frying pan”,从一句话中,就能很好的猜到这个单词 “scrammed”的意思。
上图中就是一个部分数据的显示,从中可以看出都是有关游戏的映射,而且他还能将相似意思的单词放在一起,正是因为采用了相似的特征向量,然后才能将相似的单词一起聚类得到上图,这可以应用在任何NLP任务中。
上图是一个有关places单词的所有映射,在最上面,有us states,在下面有很多城市,红色框起来的是Cambridge,和他重叠的就是十分相似的单词了,如果具体观察每个例子,都能发现他们相近的单词都是有着很相似的信息的。
上图是一个有关副词相似性映射图,红色框中likely,probably和possibly和perhaps都是符合我们人类的认知的。其他的就不用一一说明了吧。反正觉得这个网络很牛逼就对了