版权声明:本文智能单元首发,本人原创翻译,禁止未授权转载。
译者注:在CS231n课程笔记止步于CNN,没有循环神经网络(RNN和LSTM),实为憾事。经知友推荐,将 The Unreasonable Effectiveness of Recurrent Neural Networks一文翻译完毕,作为补充。感谢@ 猴子, 和 的校对。
目录
- 循环神经网络
- 字母级别的语言模型
- RNN的乐趣
- Paul Graham生成器
- 莎士比亚
- 维基百科
- 几何代数
- Linux源码
- 生成婴儿姓名
- 理解训练过程 译者注:下篇起始处
- 训练时输出文本的进化
- RNN中的预测与神经元激活可视化
- 源代码
- 拓展阅读
- 结论
- 译者反馈
理解训练过程
我们已经看见训练结束后的结果令人印象深刻,但是它到底是如何运作的呢?现在跑两个小实验来一探究竟。
训练时输出文本的进化
首先,观察模型在训练时输出文本的不断进化是很有意思的。例如,我使用托尔斯泰的《战争与和平》来训练LSTM,并在训练过程中每迭代100次就输出一段文本。在第100次迭代时,模型输出的文本是随机排列的:
tyntd-iafhatawiaoihrdemot lytdws e ,tfti, astai f ogoh eoase rrranbyne 'nhthnee e
plia tklrgd t o idoe ns,smtt h ne etie h,hregtrs nigtike,aoaenns lng
但是至少可以看到它学会了单词是被空格所分割的,只是有时候它使用了两个连续空格。它还没学到逗号后面总是有个空格。在迭代到第300次的时候,可以看到模型学会使用引号和句号。
"Tmont thithey" fomesscerliund
Keushey. Thom here
sheulke, anmerenith ol sivh I lalterthend Bleipile shuwy fil on aseterlome
coaniogennc Phe lism thond hon at. MeiDimorotion in ther thize."
单词被空格所分割,模型开始知道在句子末尾使用句号。在第500次迭代时:
we counter. He stutn co des. His stanted out one ofler that concossions and was
to gearang reay Jotrets and with fre colt otf paitt thin wall. Which das stimn
模型开始学会使用最短和最常用的单词,比如“we”、“He”、“His”、“Which”、“and”等。从第700次迭代开始,可以看见更多和英语单词形似的文本:
Aftair fall unsuch that the hall for Prince Velzonski's that me of
her hearly, and behs to so arwage fiving were to it beloge, pavu say falling misfort
how, and Gogition is so overelical and ofter.
在第1200次迭代,我们可以看见使用引号、问好和感叹号,更长的单词也出现了。
"Kite vouch!" he repeated by her
door. "But I would be done and quarts, feeling, then, son is people...."
在迭代到2000次的时候,模型开始正确的拼写单词,引用句子和人名。
"Why do what that day," replied Natasha, and wishing to himself the fact the
princess, Princess Mary was easier, fed in had oftened him.
Pierre aking his soul came to the packs and drove up his father-in-law women.
从上述结果中可见,模型首先发现的是一般的单词加空格结构,然后开始学习单词;从短单词开始,然后学习更长的单词。由多个单词组成的话题和主题词要到训练后期才会出现。
RNN中的预测与神经元激活可视化
另一个有趣的实验内容就是将模型对于字符的预测可视化。下面的图示是我们对用维基百科内容训练的RNN模型输入验证集数据(蓝色和绿色的行)。在每个字母下面我们列举了模型预测的概率最高的5个字母,并用深浅不同的红色着色。深红代表模型认为概率很高,白色代表模型认为概率较低。注意有时候模型对于预测的字母是非常有信心的。比如在http://www. 序列中就是。
输入字母序列也被着以蓝色或者绿色,这代表的是RNN隐层表达中的某个随机挑选的神经元是否被激活。绿色代表非常兴奋,蓝色代表不怎么兴奋。LSTM中细节也与此类似,隐藏状态向量中的值是[-1, 1],这就是经过各种操作并使用tanh计算后的LSTM细胞状态。直观地说,这就是当RNN阅读输入序列时,它的“大脑”中的某些神经元的激活率。不同的神经元关注的是不同的模式。在下面我们会看到4种不同的神经元,我认为比较有趣和能够直观理解(当然也有很多不能直观理解)。
————————————————————————————————————————
本图中高亮的神经元看起来对于URL的开始与结束非常敏感。LSTM看起来是用这个神经元来记忆自己是不是在一个URL中。——————————————————————————————————————————
高亮的神经元看起来对于markdown符号[[]]的开始与结束非常敏感。有趣的是,一个[符号不足以激活神经元,必须等到两个[[同时出现。而判断有几个[的任务看起来是由另一个神经元完成的。——————————————————————————————————————————
这是一个在[[]]中线性变化的神经元。换句话说,在[[]]中,它的激活是为RNN提供了一个以时间为准的坐标系。RNN可以使用该信息来根据字符在[[]]中出现的早晚来决定其出现的频率(也许?)。——————————————————————————————————————————
这是一个进行局部动作的神经元:它大部分时候都很安静,直到出现www序列中的第一个w后,就突然关闭了。RNN可能是使用这个神经元来计算www序列有多长,这样它就知道是该输出有一个w呢,还是开始输出URL了。——————————————————————————————————————————
当然,由于RNN的隐藏状态是一个巨大且分散的高维度表达,所以上面这些结论多少有一点手动调整。上面的这些可视化图片是用定制的HTML/CSS/Javascript实现的,如果你想实现类似的,可以查看这里。
我们可以进一步简化可视化效果:不显示预测字符仅仅显示文本,文本的着色代表神经元的激活情况。可以看到大部分的细胞做的事情不是那么直观能理解,但是其中5%看起来是学到了一些有趣并且能理解的算法:
—————————————————————————————————————————
—————————————————————————————————————————在预测下个字符的过程中优雅的一点是:我们不用进行任何的硬编码。比如,不用去实现判断我们到底是不是在一个引号之中。我们只是使用原始数据训练LSTM,然后它自己决定这是个有用的东西于是开始跟踪。换句话说,其中一个单元自己在训练中变成了引号探测单元,只因为这样有助于完成最终任务。这也是深度学习模型(更一般化地说是端到端训练)强大能力的一个简洁有力的证据。
源代码
我想这篇博文能够让你认为训练一个字符级别的语言模型是一件有趣的事儿。你可以使用我在Github上的char rnn代码训练一个自己的模型。它使用一个大文本文件训练一个字符级别的模型,可以输出文本。如果你有GPU,那么会在比CPU上训练快10倍。如果你训练结束得到了有意思的结果,请联系我。如果你看Torch/Lua代码看的头疼,别忘了它们只不过是这个100行项目的高端版。
题外话。代码是用Torch7写的,它最近变成我最爱的深度学习框架了。我开始学习Torch/LUA有几个月了,这并不简单(花了很多时间学习Github上的原始Torch代码,向项目创建者提问来解决问题),但是一旦你搞懂了,它就会给你带来很大的弹性和加速。之前我使用的是Caffe和Theano,虽然Torch虽然还不完美,但是我相信它的抽象和哲学层次比前两个高。在我看来,一个高效的框架应有以下特性:
- 有丰富函数(例如切片,数组/矩阵操作等)的,对底层CPU/GPU透明的张量库。
- 一整个基于脚本语言(比如Python)的分离的代码库,能够对张量进行操作,实现所有深度学习内容(前向、反向传播,计算图等)。
- 分享预训练模型非常容易(Caffe做得很好,其他的不行)。
- 最关键的:没有编译过程!或者至少不要像Theano现在这样!深度学习的趋势是更大更复杂的网络,这些网络都有随着时间展开的复杂计算流程。编译时间不能太长,不然开发过程将充满痛苦。其次,编译导致开发者放弃解释能力,不能高效地进行调试。如果在流程开发完成后有个选项能进行编译,那也可以。
拓展阅读
在结束本篇博文前,我想把RNN放到更广的背景中,提供一些当前的研究方向。RNN现在在深度学习领域引起了不小的兴奋。和卷积神经网络一样,它出现已经有十多年了,但是直到最近它的潜力才被逐渐发掘出来,这是因为我们的计算能力日益强大。下面是当前的一些进展(肯定不完整,而且很多工作可以追溯的1990年):
在NLP/语音领域,RNN将语音转化为文字,进行机器翻译,生成手写文本,当然也是强大的语言模型 (Sutskever等) (Graves) (Mikolov等)。字符级别和单词级别的模型都有,目前看来是单词级别的模型更领先,但是这只是暂时的。
计算机视觉。RNN迅速地在计算机视觉领域中被广泛运用。比如,使用RNN用于视频分类,图像标注(其中有我自己的工作和其他一些),视频标注和最近的视觉问答。在计算机视觉领域,我个人最喜欢的RNN论文是《Recurrent Models of Visual Attention》,之所以推荐它,是因为它高层上的指导方向和底层的建模方法(对图像短时间观察后的序列化处理),和建模难度低(REINFORCE算法规则是增强学习里面策略梯度方法中的一个特例,使得能够用非微分的计算来训练模型(在该文中是对图像四周进行快速查看))。我相信这种用CNN做原始数据感知,RNN在顶层做快速观察策略的混合模型将会在感知领域变得越来越流行,尤其是在那些不单单是对物体简单分类的复杂任务中将更加广泛运用。
归纳推理,记忆和注意力(Inductive Reasoning, Memories and Attention)。另一个令人激动的研究方向是要解决普通循环网络自身的局限。RNN的一个问题是它不具有归纳性:它能够很好地记忆序列,但是从其表现上来看,它不能很好地在正确的方向上对其进行归纳(一会儿会举例让这个更加具体一些)。另一个问题是RNN在运算的每一步都将表达数据的尺寸和计算量联系起来,而这并非必要。比如,假设将隐藏状态向量尺寸扩大为2倍,那么由于矩阵乘法操作,在每一步的浮点运算量就要变成4倍。理想状态下,我们希望保持大量的表达和记忆(比如存储全部维基百科或者很多中间变量),但同时每一步的运算量不变。
在该方向上第一个具有说服力的例子来自于DeepMind的神经图灵机(Neural Turing Machines)论文。该论文展示了一条路径:模型可以在巨大的外部存储数组和较小的存储寄存器集(将其看做工作的存储器)之间进行读写操作,而运算是在存储寄存器集中进行。更关键的一点是,神经图灵机论文提出了一个非常有意思的存储解决机制,该机制是通过一个(soft和全部可微分的)注意力模型来实现的。译者注:这里的soft取自softmax。基于概率的“软”注意力机制(soft attention)是一个强有力的建模特性,已经在面向机器翻译的《 Neural Machine Translation by Jointly Learning to Align and Translate》一文和面向问答的《Memory Networks》中得以应用。实际上,我想说的是:
注意力概念是近期神经网络领域中最有意思的创新。
现在我不想更多地介绍细节,但是软注意力机制存储器寻址是非常方便的,因为它让模型是完全可微的。不好的一点就是牺牲了效率,因为每一个可以关注的地方都被关注了(虽然是“软”式的)。想象一个C指针并不指向一个特定的地址,而是对内存中所有的地址定义一个分布,然后间接引用指针,返回一个与指向内容的权重和(这将非常耗费计算资源)。这让很多研究者都从软注意力模式转向硬注意力模式,而硬注意力模式是指对某一个区域内的内容固定关注(比如,对某些单元进行读写操作而不是所有单元进行读写操作)。这个模型从设计哲学上来说肯定更有吸引力,可扩展且高效,但不幸的是模型就不是可微分的了。这就导致了对于增强学习领域技术的引入(比如REINFORCE算法),因为增强学习领域中的研究者们非常熟悉不可微交互的概念。这项工作现在还在进展中,但是硬注意力模型已经被发展出来了,在《 Inferring Algorithmic Patterns with Stack-Augmented Recurrent Nets》,《 Reinforcement Learning Neural Turing Machines》,《Show Attend and Tell》三篇文章中均有介绍。
研究者。如果你想在RNN方面继续研究,我推荐Alex Graves,Ilya Sutskever和Tomas Mikolov三位研究者。想要知道更多增强学习和策略梯度方法(REINFORCE算法是其中一个特例),可以学习David Silver的课程,或Pieter Abbeel的课程。
代码。如果你想要继续训练RNN,我听说Theano上的keras或passage还不错。我使用Torch写了一个项目,也用numpy实现了一个可以前向和后向传播的LSTM。你还可以在Github上看看我的NeuralTalk项目,是用RNN/LSTM来进行图像标注。或者看看Jeff Donahue用Caffe实现的项目。
结论
我们已经学习了RNN,知道了它如何工作,以及为什么它如此重要。我们还利用不同的数据集将RNN训练成字母级别的语言模型,观察了它是如何进行这个过程的。可以预见,在未来将会出现对RNN的巨大创新,我个人认为它们将成为智能系统的关键组成部分。
最后,为了给文章增添一点格调,我使用本篇博文对RNN进行了训练。然而由于博文的长度很短,不足以很好地训练RNN。但是返回的一段文本如下(使用低的温度设置来返回更典型的样本):
I've the RNN with and works, but the computed with program of the
RNN with and the computed of the RNN with with and the code
是的,这篇博文就是讲RNN和它如何工作的,所以显然模型是有用的:)下次见!
译者反馈
- 翻译不到位的地方,欢迎知友们评论批评指正;
- 关于Torch和TensorFlow,AK本人现在在OpenAI工作主要是在用TF了,但是他对于Torch还是有很强的倾向性。这在他最新的博文中可以看到;
- 在计算机视觉方面,个人对于图像标注比较感兴趣,正在入坑。欢迎有同样兴趣的知友投稿讨论;
- 想要加入翻译小组的同学,请连续3次在评论中对我们最新的翻译做出认真的批评和指正,而后我们会小组内投票决定是否吸纳新成员:)这个小小的门槛是为了方便我们找到真正喜爱机器学习和翻译的同学。