递归神经网络不可思议的有效性(上)

原文作者:Andrej Karpathy

递归神经网络(RNNs)有一些不可思议的地方。我仍然记得我训练的第一个用于 图片字幕的递归网络。从花几十分钟训练我的第一个婴儿模型(相当随意挑选的超参数)开始,到训练出能够针对图像给出有意义描述的模型。有些时候,模型对于输出结果质量的简单程度的比例,会与你的期望相差甚远,而这还仅仅是其中一点。有如此令人震惊结果,许多人认为是因为RNNs非常难训练(事实上,通过多次试验,我得出了相反的结论)。一年前:我一直在训练RNNs,我多次见证了它们的强大的功能和鲁棒性,而且它们的输出结果同样让我感到有趣。这篇文章将会给你展现它不可思议的地方。

我们将训练一个RNNs让它一个字符一个字符地生成文本,然后我们思考“这怎么可能?”

顺便说句,在讲述这篇文章的同时,我同样会将代码上传到 Github 上,这样你就可以基于多层LSTMs来训练字符级语言模型。你向它输入大量的文本,它会学习并产生类似的文本。你也可以用它来重新运行我下面的代码。但是我们正在不断超越自己;那么RNNs究竟是什么呢?

递归神经网络

序列。你可能会问:是什么让递归神经网络如此特殊?Vanilla神经网络(卷积网络也一样)最大的局限之处就是它们API的局限性:它们将固定大小的向量作为输入(比如一张图片),然后输出一个固定大小的向量(比如不同分类的概率)。还不止这些:这些模型按照固定的计算步骤来(比如模型中层的数量)实现这样的输入输出。递归网络更令人兴奋的主要原因是,它允许我们对向量序列进行操作:输入序列、输出序列、或大部分的输入输出序列。通过几个例子可以具体理解这点:

每一个矩形是一个向量,箭头则表示函数(比如矩阵相乘)。输入向量用红色标出,输出向量用蓝色标出,绿色的矩形是RNN的状态(下面会详细介绍)。从做到右:(1)没有使用RNN的Vanilla模型,从固定大小的输入得到固定大小输出(比如图像分类)。(2)序列输出(比如图片字幕,输入一张图片输出一段文字序列)。(3)序列输入(比如情感分析,输入一段文字然后将它分类成积极或者消极情感)。(4)序列输入和序列输出(比如机器翻译:一个RNN读取一条英文语句然后将它以法语形式输出)。(5)同步序列输入输出(比如视频分类,对视频中每一帧打标签)。我们注意到在每一个案例中,都没有对序列长度进行预先特定约束,因为递归变换(绿色部分)是固定的,而且我们可以多次使用。

正如你预想的那样,与使用固定计算步骤的注定要失败的固定网络相比,使用序列进行操作要更加强大,因此,这激起了我们建立更智能系统更大的兴趣。而且,我们可以从一小方面看出,RNNs将输入向量与状态向量用一个固定(但可以学习)函数绑定起来,从而用来产生一个新的状态向量。在编程层面,在运行一个程序时,可以用特定的输入和一些内部变量对其进行解释。从这个角度来看,RNNs本质上可以描述程序。事实上,众所周知, RNNs是图灵完备的,即它们可以模拟任意程序(使用恰当的权值向量)。但是,类似于通用逼近定理神经网络,你还不应该深入阅读。就当我没说过这些吧。

如果训练Vanilla神经网络是优化功能,那么训练递归神经网络则是优化程序。

序列缺失情况下的序列处理。你可能会想,有序列作为输入或输出可能是相对少见的,但关键是,即使你的输入/输出是固定向量,仍然有可能使用这种强大的以序列的方式来处理它们。比如,下图显示了 DeepMind 中两篇非常棒的论文的结果。在左边,一个算法学习了一种递归网络策略,可以将它的注意力集中在图像周围;特别的,它学会了从左到右阅读门牌号码( Ba等人 )。在右边,一个递归网络通过学习在画布上序列化地添加颜色然后生成一张数字图像(Gregor等人 ):

左边:RNN学习阅读门牌号。右边:RNN学习学习绘制门牌号。

即使你的数据不是序列形式的,你仍然可以制定并训练出强大的模型来学习处理它。你可以学习有状态的程序来处理固定大小的数据。

RNN计算。那么这些是如何工作的呢?主要是,RNNs有一个非常简洁的API:它们将向量x作为输入,然后输出结果向量y.然而,关键的是这个输出向量的内容不仅受到前一次输入数据的影响,而且还会受整个历史输入数据的影响。这个API编写成了一个类,它由一个step方法构成:

rnn = RNN()
y = rnn.step(x) # x is an input vector, y is the RNN's output vector

RNN类有一些内部的状态,会在每一次调用 step方法的时候进行更新。最简单的情况是,这个状态由单个隐藏向量h构成。下面是Vanilla RNN中对step方法的一种实现:

class RNN:
  # ...
  def step(self, x):
    # update the hidden state
    self.h = np.tanh(np.dot(self.W_hh, self.h) + np.dot(self.W_xh, x))
    # compute the output vector
    y = np.dot(self.W_hy, self.h)
    return y

上面的代码指明了vanilla RNN的前馈操作。这个RNN的参数是以下三个矩阵:w_hh,w_xh,w_hy。隐藏状态self.h由两个零向量初始化。np.tanh函数实现了非线性的方法,将活化结果压缩到范围[-1,1]之内。简单介绍工作原理:tanh中有两种形式:一种是基于前面的隐藏状态,另一种是基于当前的输入。numpy中的np.dot是矩阵乘法。这两种中间体相加,然后由tanh函数将它压缩成一个新的状态向量。如果你适合看数学公式的话,我们同样可以将隐藏状态写成 ht+1 =tanh(Whh ht+ Wxhx t), tanh函数是元素智能的。

我们用随机数来初始化RNN矩阵,通过大量的训练找到一个令人满意的矩阵,并且用一些损失函数来度量,你可以在输入序列x上得到你希望的输出y。

更深层次说明。RNNs是一种神经网络,而且如果你开始学习深度学习并开始像堆煎饼一样积累模型,它们将会工作得更好(如果做得正确的话)。例如,我们可以通过以下方式建立一个2层的递归网络:

y1 = rnn1.step(x)
y = rnn2.step(y1)

换句话说,我们有两个独立的RNNs:一个RNN接收输入向量,另一个将前一个RNN的输出作为输入。这两个RNN没有本质区别——这不外乎就是向量的输入输出而已,而且在反向传播过程中每个模块都伴随着梯度操作。

来点更奇特的。我会简要说明,实际上我们大多数人使用一种与上面我所提及稍微不同的网络,它叫做长短期记忆(LSTM)网络。LSTM是一种特殊类型的递归网络,在实践中工作效果更佳,这归功于其强大的更新方程和一些吸引人的动态反向传播功能。我不会详细介绍,除了用于更新计算(self.h=···)的数学形式有点更复杂外,与其他RNNs没有多大区别。从现在开始,我将会交替使用术语“RNN/LSTM”,但是这篇文章中所有的实验都是用LSTM完成的。

字符级语言模型

好,我们现在已经初步了解了什么是RNNs,为什么它们如此令人兴奋,还有它们是如何工作的。我们现在就用它来实现一个有趣的应用:我们将要训练字符级的语言RNN模型。具体来说就是,我们将会向RNN输入大量的文本数据,然后在一个序列中给定一个前面的字符,用它来建立计算这个序列下一个字符概率的模型。这将会让我们在同一时间产生新文本字符。

作为一个案例,假设我们只有四种字母的词汇“helo”,然后我们想要用训练序列“hello”训练一个RNN。这个训练序列实际上是来自于4个独立的训练案例:1.字母e应该在字母h出现的情况下才可能出现,2.字母l应该出现在he出现的情况下,3.字母l同样可以出现在hel出现的情况下,最后4.字母o应该出现在hell出现的情况下。

具体来说,我们将用1-of-k编码(所有都是0,除了词汇中字符的索引)将每个字符编码成一个向量,然后用step函数每次向RNN中输入一个字符。然后我们会看到一个4维序列的输出向量(每个字符代表一个维度),我们将此作为RNN分配给序列下一个字符的置信度。下面是一张案例图:

一个有四维输入输出层和一个有着3个单元(神经元)的隐藏层的实例。这张图显示了当将“helo”作为RNN的输入时前馈操作的活化结果。输出层包含了RNN对下一个出现字符(这里词汇是“h,e,l,o”)的置信度。我们希望使得绿色的数字尽可能高而红色数字尽可能低。

比如,我们可以看出,在第一次执行step函数的时候,RNN读取到字符“h”然后将它之后可能出现字符“h”的置信度设置为1.0,可能出现字符“e”的置信度设置为2.2,可能出现字符“l”的置信度设置为-3.0,可能出现字符“o”的置信度设置为4.1。因为在我们的训练数据中,下一个出现的字符是“e”,我们将要提高这个字符的置信度(绿色数字)并且降低其他字符的置信度(红色数字)。通常的做法是使用一个交叉熵损失函数,这相当于在每个输出向量上使用Softmax分类器,将下一个出现的字符的索引作为一个正确的分类。一旦损失进行了反向传播并且RNN权值得到更新,在输入相同的情况下,下一个正确的字符将会有更高的分数。技术解释:该RNN是由小批量随机梯度下降训练的。我喜欢使用 RMSProp (每个参数的自适应学习率)来稳定更新。

同样可以注意到,字符“l”第一次输入时,得到的结果是“l”,但是第二得到的结果是“o”。因此,这个RNN不能单独依赖于输入数据,必须使用它的递归连接来跟踪内容以达到准确结果。

在测试的时候,我们向RNN输入一个字符,然后得到了下一个可能出现字符的分布。我们从这个分布中抽样,然后又将这些样本输入到RNN中得到下一个字符。重复这个过程,你就在做取样的工作了!现在让我们在不同数据集上训练RNN,看看会有什么发生。

为进一步说明,出于教育目的我还写了一篇文章 minimal character-level RNN language model in Python/numpy 。只有大约100行代码,如果你更擅长阅读代码而不是文字,你可以从中得到简明的、具体的、有用的结论。现在我们将深入到实例结果,使用更高效的Lua/Torch代码库来编程。

开心使用RNNs

下面的5个字符模型案例都是使用我发布在Github上的 代码 进行训练的。每个实例的输入都是单个文本文件,然后我们训练RNN预测序列中下一个可能出现的字符。

Paul Graham生成器

首先让我们尝试用一个小英语数据集作一个全面检查。我个人最喜欢的数据集是 Paul Graham散文串联集。其基本思路是,散文中有很多智慧,不幸的是Paul Graham是一个相对缓慢的生成器。如果我们能够按需生成智慧样本,那不是很强大?RNNs在这里就起到了作用。

连接过去5年所有的论文,我们得到了大约1MB的文本文件,或者说是大约100万个字符(这是一个非常小的数据集)。技术方面:我们用512个隐藏节点(大约350万个参数)来训练一个2层的LSTM,然后在每层之后设定参数为0.5的dropout层。我们将每批训练100个实例,然后每超过100个字符则停止反向传播。通过这些设置,每一批在TITAN Z GPU上处理完成大约需要0.46秒(这通过性能代价忽略不计的50个字符的BPTT算法将它分为两半)。事不宜迟,让我们看看RNN中的样本:

"The surprised in investors weren't going to raise money. I'm not the company with the time there are all interesting quickly, don't have to get off the same programmers. There's a super-angel round fundraising, why do you can do. If you have a different physical investment are become in people who reduced in a startup with the way to argument the acquirer could see them just that you're also the founders will part of users' affords that and an alternation to the idea. [2] Don't work at first member to see the way kids will seem in advance of a bad successful startup. And if you have to act the big company too."

好了,很明显上面的样本不会很快随时取代Paul Graham,但请记住, RNN不得不完全从一个小的数据集(包括逗号,顿号和空格的位置)开始学习英语。我同样喜欢让它来学习支持自己的论证(比如上面的[2])。有时,它会提供一些可洞察的东西,比如“ a company is a meeting to think to investors”。如果你想了解更多,点击这个 链接,它有5万个字符样本数据。

温度。我们同样可以在Softmax取样的时候对温度进行操作。将温度从1降至更低的数字(比如0.5)可以让RNN有更高的置信度,但是样本就会更保守。相反地,较高的温度将会得到更多元化的结果,但是失误就更多(比如拼写错误等)。特别地,将温度设置成与0接近的数字就会得到与Paul Graham相似的言论:

"is that they were all the same thing that was a startup is that they were all the same thing that was a startup is that they were all the same thing that was a startup is that they were all the same"

看起来我们陷入了startups的死循环了。

Shakespeare

看样子好像我们的模型可以学习拼写英语单词,但是数据更结构化更风格化又会怎样呢?为了检测这一点,我下载了莎士比亚所有的作品并将它们串起来组成一个单一的(4.4MB)文件。现在我们可以训练一个更大的网络了,在这个例子中,我们尝试使用每层上都拥有512个隐藏节点的3层RNN网络。在我们训练网络几小时后,我们得到了如下样本:

PANDARUS:
Alas, I think he shall be come approached and the day
When little srain would be attain'd into being never fed,
And who is but a chain and subjects of his death,
I should not sleep.

Second Senator:
They are away this miseries, produced upon my soul,
Breaking and strongly should be buried, when I perish
The earth and thoughts of many states.

DUKE VINCENTIO:
Well, your wit is in the care of side and that.

Second Lord:
They would be ruled after this chamber, and
my fair nues begun out of the fact, to be conveyed,
Whose noble souls I'll have the heart of the wars.

Clown:
Come, sir, I will make did behold your worship.

VIOLA:
I'll drink it.

切记,RNN只认识字符,所以它将说话者的名字和内容一起生成为样本。有时,我们还可以得到相对延伸的独白段落,比如:

VIOLA:
Why, Salisbury must find his flesh and thought
That which I am not aps, not a man and in fire,
To show the reining of the raven and the wars
To grace my hand reproach within, and not a fair are hand,
That Caesar and my goodly father's world;
When I was heaven of presence and our fleets,
We spare with hours, but cut thy council I am great,
Murdered and by thy master's ready there
My power to give thee but so much as hell:
Some service in the noble bondman here,
Would show him to her wine.

KING LEAR:
O, if you were a feeble sight, the courtesy of your law,
Your sight and several breath, will wear the gods
With his heads, and my hands are wonder'd at the deeds,
So drop upon your lordship's head, and your opinion
Shall be against your honour.

在这些样本中,我几乎认不出这是莎士比亚的作品:)如果你喜欢莎士比亚,你可能会重视这份100,000个字符的样本。当然,你也可以用我提供的代码,在不同温度下生成许多你自己的样本。

Wikipedia

我们看到,LSTM可以学习拼写单词和复制一般的句法结构。让我来加大难度,在结构化markdown语言上训练网络。特别的,让我们使用 Hutter Prize 的100MB的Wikipedia原始数据训练一个LSTM。在Graves等人 之后,我使用前96MB数据来训练,剩下的则花一个晚上用来验证和运行几个模型。现在我们可以取样Wikipedia文章了!下面是几个有趣的节选。首先,一些基本的markdown输出:

Naturalism and decision for the majority of Arab countries' capitalide was grounded
by the Irish language by [[John Clair]], [[An Imperial Japanese Revolt]], associated 
with Guangzham's sovereignty. His generals were the powerful ruler of the Portugal 
in the [[Protestant Immineners]], which could be said to be directly in Cantonese 
Communication, which followed a ceremony and set inspired prison, training. The 
emperor travelled back to [[Antioch, Perth, October 25|21]] to note, the Kingdom 
of Costa Rica, unsuccessful fashioned the [[Thrales]], [[Cynth's Dajoard]], known 
in western [[Scotland]], near Italy to the conquest of India with the conflict. 
Copyright was the succession of independence in the slop of Syrian influence that 
was a famous German movement based on a more popular servicious, non-doctrinal 
and sexual power post. Many governments recognize the military housing of the 
[[Civil Liberalization and Infantry Resolution 265 National Party in Hungary]], 
that is sympathetic to be to the [[Punjab Resolution]]
(PJS)[http://www.humah.yahoo.com/guardian.
cfm/7754800786d17551963s89.htm Official economics Adjoint for the Nazism, Montgomery 
was swear to advance to the resources for those Socialism's rule, 
was starting to signing a major tripad of aid exile.]]

你可能会想,上面的雅虎url并不真实存在,该模型只是将它作为假想事物。同样,可以注意到模型学会正确打开和关闭插入语。模型同样学会了许多结构化markdown语言,比如,有时候它创建了头部信息和列表等:

{ { cite journal | id=Cerling Nonforest Department|format=Newlymeslated|none } }
''www.e-complete''.

'''See also''': [[List of ethical consent processing]]

== See also ==
*[[Iender dome of the ED]]
*[[Anti-autism]]

===[[Religion|Religion]]===
*[[French Writings]]
*[[Maria]]
*[[Revelation]]
*[[Mount Agamul]]

== External links==
* [http://www.biblegateway.nih.gov/entrepre/ Website of the World Festival. The labour of India-county defeats at the Ripper of California Road.]

==External links==
* [http://www.romanology.com/ Constitution of the Netherlands and Hispanic Competition for Bilabial and Commonwealth Industry (Republican Constitution of the Extent of the Netherlands)]

有时模型会生成随机但是有效的XML文件:

<page>
  <title>Antichrist</title>
  <id>865</id>
  <revision>
    <id>15900676</id>
    <timestamp>2002-08-03T18:14:12Z</timestamp>
    <contributor>
      <username>Paris</username>
      <id>23</id>
    </contributor>
    <minor />
    <comment>Automated conversion</comment>
    <text xml:space="preserve">#REDIRECT [[Christianity]]</text>
  </revision>
</page>

这个模型完全拼凑出了timestamp,id等等。同样,注意到它以正确的嵌套顺序适当的闭合了正确的标签。

原文发布于微信公众号 - 人工智能头条(AI_Thinker)

原文发表时间:2015-09-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏量化投资与机器学习

【Python机器学习】系列之特征提取与处理篇(深度详细附源码)

第1章 机器学习基础 将机器学习定义成一种通过学习经验改善工作效果的程序研究与设计过程。其他章节都以这个定义为基础,后面每一章里介绍的机器学习模型都是按照这个...

1.3K7
来自专栏一心无二用,本人只专注于基础图像算法的实现与优化。

阅读Real-Time O(1) Bilateral Filtering 一文的相关感受。

研究双边滤波有很长一段时间了,最近看了一篇Real-Time O(1) Bilateral Filtering的论文,标题很吸引人,就研读了一番,经过几天的攻...

2919
来自专栏Coding迪斯尼

用深度学习实现自然语言处理:word embedding,单词向量化

前几年,腾讯新闻曾发出一片具有爆炸性的文章。并不是文章的内容有什么新奇之处,而是文章的作者与众不同,写文章的不是人,而是网络机器人,或者说是人工智能,是算法通过...

1031
来自专栏人工智能LeadAI

GoogLeNet的心路历程(二)

本文介绍关于GoogLeNet的续作,习惯称为inception v2,如下: [v2] Batch Normalization: Accelerating D...

3646
来自专栏人工智能

在线手写识别的多卷积神经网络方法

本文所描述的研究主要关注在线手写体识别系统中的单词识别技术。该在线手写体识别系统使用多组件神经网络(multiple component neural netw...

1.4K7
来自专栏PPV课数据科学社区

机器学习系列:(三)特征提取与处理

特征提取与处理 上一章案例中的解释变量都是数值,比如匹萨的直接。而很多机器学习问题需要研究的对象可能是分类变量、文字甚至图像。本章,我们介绍提取这些变量特征的方...

5858
来自专栏AI研习社

无监督聚类问题中,如何决定簇的最优数量?

编者按:聚类问题有一大经典难题:没有数据集的真实分类情况,我们怎么才能知道数据簇的最优数目? 本文会谈谈解决该问题的两种流行方法:elbow method(肘子...

3608
来自专栏大数据挖掘DT机器学习

R语言与机器学习(分类算法)决策树算法

决策树定义 首先,我们来谈谈什么是决策树。我们还是以鸢尾花为例子来说明这个问题。 ? 观察上图,我们判决鸢尾花的思考过程可以这么...

5034
来自专栏机器之心

教程 | 5种快速易用的Python Matplotlib数据可视化方法

选自towardsdatascience 作者:George Seif 机器之心编译 参与:刘晓坤、思源 数据可视化是数据科学家工作的重要部分。在项目的早期...

3726
来自专栏机器之心

教程 | 一个基于TensorFlow的简单故事生成案例:带你了解LSTM

选自Medium 机器之心编译 参与:Ellan Han、吴攀 在深度学习中,循环神经网络(RNN)是一系列善于从序列数据中学习的神经网络。由于对长期依赖问题...

4429

扫码关注云+社区

领取腾讯云代金券