RNN是只能用于自然语言处理的一种神经网络框架(一篇文章看懂RNN循环神经网络)
RNN是只能用于自然语言处理的一种神经网络框架(一篇文章看懂RNN循环神经网络)和通常的vanilla networks以及卷积神经网络不同(CNN),RNN模型不会要求约束输入和输出的长度,允许输入或输出一个向量序列。它的工作原理参见下图:1. 序列以下就是老K根据Andrej Karpathy的文章整理和翻译的内容摘要,大家看下来吧。看不完可以先收藏, 一定会对你有帮助。另:由于平台规定不允许放置外链,所以文中涉及的很多资源和链接,请各位小伙伴在后台私信 / RNN / 查看。
【NLP论文精选】一篇文章看懂rnn循环神经网络模型,令人震惊的实验结果
我是@老K玩代码,专注分享实战项目和最新行业资讯,已累计分享超1000实战项目!
前言
学习自然语言处理,就绕不开RNN模型,RNN在自然语言处理中的表现非常出色。而关于介绍RNN的文章中,就不得不提Andrej Karpathy大佬的经典文章——《The Unreasonable Effectiveness of Recurrent Neural Networks》。
不过,大神的文章比较长,而且全篇英文,加上很多专业术语,对于很多初学NLP的小伙伴很不友好。所以,老K为大家整理翻译了文章的主旨大意,方便各位小伙伴更好地学习
以下就是老K根据Andrej Karpathy的文章整理和翻译的内容摘要,大家看下来吧。
看不完可以先收藏, 一定会对你有帮助。
另:由于平台规定不允许放置外链,所以文中涉及的很多资源和链接,请各位小伙伴在后台私信 / RNN / 查看。
循环神经网络(RNN)
1. 序列
和通常的vanilla networks以及卷积神经网络不同(CNN),RNN模型不会要求约束输入和输出的长度,允许输入或输出一个向量序列。它的工作原理参见下图:
- one-to-one:vanilla networks的模式,不包含RNN模型,应用场景有:图片分类等
- one-to-many:输出为序列,应用场景有:看图说话等
- many-to-one:输入为序列,应用场景有:语句情感分析等
- many-to-many:输入和输出均为序列,应用场景有:机器翻译等
- many-to-many:输入和输出为同步序列,应用场景有:视频分类中的逐帧标记等
2. 非序列的处理场景
RNN在非序列场景的应用现在虽然稀少,但正在发展。比如:下图是来自DeepMind的两篇论文中提到的试验
该图展示的是阅读门牌号时的注意力轨迹,得到的结果是从左到右;
该图展示的是通过RNN在画布上生成数字图片。
3. RNN计算
在看似简单的RNN的API下,其实藏着非常有趣和精巧的设置。模型中,输出向量不仅受到你即时输入的向量影响,还受到历史输入的影响。
以下是一个RNN的演示代码,可以直观地进行说明:
rnn = RNN()
y = rnn.step(x) # x是输入向量,y是rnn的输出向量
声明的RNN类如下:
class RNN:
# …
def step(self x):
# 更新隐藏层
self.h = np.tanh(np.dot(self.W_hh self.h) np.dot(self.W_xh x))
# 计算输出层
y = np.dot(self.W_hy self.h)
return y
这里的:
- step是RNN模型中,每一次更新输出都会用到的方法;
- h是一个内部的隐藏向量,初始值是零矩阵,会通过每一次调用step传递到下一次运算中;
- W_hh、W_xh、W_hy是RNN模型的参数,是三个矩阵;
- np.tanh是非线性的激活函数,取值范围是[-1 1];
- np.dot是矩阵乘法;
用传统的数学公式展示的话,上面的式子可以写成:
$(h_t = \tanh(W_{hh} h_{t-1} W_{xh} x_t))$
4. 深入研究
和大多数神经网络模型一样,只要方法合适和正确,RNN模型可以通过堆叠得到更好的结果,比如:
y1 = rnn1.step(x)
y = rnn2.step(y1)
将x传入一个RNN神经网络(rnn1),将它的输出作为输入,传入另一个RNN神经网络(rnn2),得到最终的输出结果。有时会得到有趣的结果。
有趣的尝试
通常情况下,将基本的RNN网络替换成LSTM网络,在大多数场景下会得到更好、更有趣的结果。
LSTM全称是Long-Short-Term Memory,即长短记忆网络模型,是特殊的RNN模型。
之后的试验中,在没有强调的情况下,笔者都是会用LSTM表示。
字符级语言模型
我们先用RNN编写一个有趣的应用程序:我们给RNN模型一系列文本,并且要求它返回后一个字符可能的结果分布。也就是说,我们可以通过它生成下一个字符。
先从简单的模型开始:
我们只提供4个字符h e l o,让模型从中生成"hello"这个单词,这需要模型能给出:
- 条件h时,e的可能性;
- 条件是he时,l的可能性;
- 条件是hel时,l的可能性;
- 条件是hell时,o的可能性
具体的方案和步骤是:
- 将每个字符,编码成一个one-hot向量(即1-of-k vector),参见图中input-layer的内容
- 把one-hot向量传入RNN模型进行step函数运算
- 得到一个四维向量序列,这里的每个向量表示一个字符,向量中每个值反应相应字符的可信度(confidence)
见图:
以上图为例,当给出输入字符为h时,one-hot向量为[1 0 0 0],而输出的值分别表示:
- 下一个字符为h的可信度是1.0;
- 下一个字符为e的可信度是2.2;
- 下一个字符为l的可信度是-3.0;
- 下一个字符为o的可信度是4.1;
可以看到,正确答案e对应的值(绿色)为2.2,不是4个结果中最大的值。
这时候,我们可以通过反向传播算法(backpropation algorithm)对每个权重进行轻微调整,以增加正确目标(绿值)的可信度,降低错误目标(红值)的可行度,直到模型收敛,预测结果始终和正确值一致。
以上是原理,接下来说一些技巧:
- 损失函数:通常首选softmax,但也可以考虑使用交叉熵损失(cross-entropy loss)
- 优化函数:RNN一般使用mini-batch SGD,但RMSProp和Adam也是很好的优化器
值得注意的是,当第一次输入l时,结果应该是l,而第二次输入l时,输出则是o。从这个意义上可以看出,RNN模型确实不是仅仅依赖于当前输入给出结果,而会充分考虑历史输入的影响。
RNN的有趣项目
以下项目,原始代码都被放到了Github上,不过由于平台规定,频繁使用外链可能会被处罚,所以小伙伴可以自行搜索,或私信 / RNN / 关键词给我。
1. Paul Graham生成器我们不要在意PaulGraham是谁,总之是个会撰写一些内容的作家,我们的模型语料会基于这个作家的文字来训练。
Paul Graham生成器是一个基于小语料和通顺检测思路做的一个项目:
- 语料:大约1MB(合1 000 000字符)
- 模型:2个LSTM层(512隐藏节点,合3 500 000参数),0.5的dropout,100条数据/bacth
- 用时:0.46秒/batch
以下是生成的样例:
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.
这里,Andrej Karpathy提到一个概念,叫Temperature(温度参数)。通过调整温度参数,可以使文本变得灵活或保守,数值越低越保守。当值为0时,语料就不会有任何创造性,可能会得到这样的结果:
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
一段重复文本
2. 莎士比亚让RNN学会拼写单词似乎不再是难事,那有没有可能让模型了解数据语料中的结构和格式?我们用莎士比亚的文本做试验:
- 语料:4.4MB的语料文件;
- 模型:3个RNN层(每层512个隐藏节点)
- 用时:数小时
看一下训练出来的结果:
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了,我们来挑战一下标记语言。这里用到了wikipedia的语料来训练:
- 语料: 100MB的wikipedia原始文本(训练集96MB,测试集4MB)
- 模型: LSTM模型
- 用时: 整晚
下面是结果,很有意思:
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,但这个url实际并不存在。另外,可以看到它对括号([[]])的使用是正确的。
{ { 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)]
上面这段可以看到,模型已经掌握了标记语言的基本结构.
<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>
有时候甚至能输出正确的XML语句,包括缩进格式。
4. 代数几何(Latex)似乎已经没什么能难得了RNN的了,但作者还想挑战升级一下难度,让模型学会编写数学公式或者几何分析(即Latex语法)。
- 语料:16MB的Latex源文件
- 模型:多层LSTM模型
作者得到了惊人的结果,以下是他通过模型生成的结果
虽然公式不正确,但模型确实掌握了Latex的语法逻辑,生成了很多似是而非的公式、推论和图解。
而以下是模型输出的代码:
\begin{proof}
We may assume that $\mathcal{I}$ is an abelian sheaf on $\mathcal{C}$.
\item Given a morphism $\Delta : \mathcal{F} \to \mathcal{I}$
is an injective and let $\mathfrak q$ be an abelian sheaf on $X$.
Let $\mathcal{F}$ be a fibered complex. Let $\mathcal{F}$ be a category.
\begin{enumerate}
\item \hyperref[setain-construction-phantom]{Lemma}
\label{lemma-characterize-quasi-finite}
Let $\mathcal{F}$ be an abelian quasi-coherent sheaf on $\mathcal{C}$.
Let $\mathcal{F}$ be a coherent $\mathcal{O}_X$-module. Then
$\mathcal{F}$ is an abelian catenary over $\mathcal{C}$.
\item The following are equivalent
\begin{enumerate}
\item $\mathcal{F}$ is an $\mathcal{O}_X$-module.
\end{lemma}
5. Linux源代码
变态的Andrej Karpathy给RNN模型带来了一个终极大挑战!他从github上把linux源代码下载下来,喂给模型让它学习:
- 语料:474MB的C语言语料;
- 模型:3层LSTM模型,10 000 000个参数;
- 用时:几天
/*
* Increment the size file of the new incorrect UI_FILTER group information
* of the size generatively.
*/
static int indicate_policy(void)
{
int error;
if (fd == MARN_EPT) {
/*
* The kernel blank will coeld it to userspace.
*/
if (ss->segment < mem_total)
unblock_graph_and_set_blocked();
else
ret = 1;
goto bail;
}
segaddr = in_SB(in.addr);
selector = seg / 16;
setup_works = true;
for (i = 0; i < blocks; i ) {
seq = buf[i ];
bpf = bd->bd.next i * search;
if (fd) {
current = blocked;
}
}
rw->name = "Getjbbregs";
bprm_self_clearl(&iv->version);
regs->new = blocks[(BPF_STATS << info->historidac)] | PFMR_CLOBATHINC_SECONDS << 12;
return segtable;
}
这段文本看起来确实像一段C语言代码,有合适的字符串、适当的注释,各类括号的使用也是正确的。
当然,也存在一些错误,如声明了变量却未使用(例:int error),return(返回)了一个不存在的变量(segtable)等。
原文中还展示了更多模型生成的代码,这里就不展示了。
6. 婴儿起名器这个试验完全是因为好玩,用RNN生成新名字。 - 语料:8000个婴儿名字
Rudi Levette Berice Lussa Hany Mareanne Chrestina Carissy Marylen Hammine Janye Marlise Jacacrie Hendred Romand Charienna Nenotto Ette Dorane Wallen Marly Darine Salina Elvyn Ersia Maralena Minoria Ellia Charmin Antley Nerille Chelon Walmor Evena Jeryly Stachon Charisa Allisa Anatha Cathanie Geetra Alexie Jerin Cassen Herbett Cossie Velen Daurenge Robester Shermond Terisa Licia Roselen Ferine Jayn Lusine Charyanne Sales Sanny Resa Wallon Martine Merus Jelen Candica Wallin Tel Rachene Tarine Ozila Ketia Shanne Arnande Karella Roselina Alessia Chasty Deland Berther Geamar Jackein Mellisand Sagdy Nenc Lessie Rasemy Guen Gavi Milea Anneda Margoris Janin Rodelin Zeanna Elyne Janah Ferzina Susta Pey Castina
这里可以生成各种各样的名字,这对于写小说或者起名字,是一个很好的灵感来源。
理解原理1. 训练是如何带来改变的?
以下是通过LSTM模型通过对列夫.托尔斯泰的《战争与和平》为语料,训练出的语言模型生成的结果。以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
以上是迭代100次后产生的结果:虽然看不出任何单词和语法,但模型显然学会了“单词和单词之间,主要是通过空格进行分割”这一特征。
"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."
以上是迭代300次后产生的结果:模型基本学会了如何正确使用引号和句号等常见的标点符号。
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
以上是迭代500次后产生的结果:模型可以拼出一些比较短的单词,如:we、he、one、out等,也能准确地使用逗号。
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.
以上是迭代700次后产生的结果:模型学会了越来越多的英文代词。
"Kite vouch!" he repeated by her door. "But I would be done and quarts feeling then son is people...."
以上是迭代1200次后产生的结果:模型已经学会“引用”的语法结构,并掌握问号/省略号的使用。
"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.
以上是迭代2000次后产生的结果:模型能掌握大部分单词的拼写,掌握引用和起名的逻辑。
2. 通过可视化展示神经元的工作原理将结果进行可视化展示,是一种有趣的研究方法。这里,我们采用Wikipadia的RNN模型生成的文本和验证集进行比较。
第一行是验证集里的文本序列,以这些序列为输入,预测的下一个字符,根据模型给出的可能性,依次将可信度(confidence)排前5的字符列在2-6行。根据可信度(confidence)值的大小,将单元格的颜色标红(1为深红,0为白色)。
为了研究神经元在模型中的作用,我们给第一行的字符标记上从蓝到绿的颜色。随机从RNN模型的隐藏层中抽取一个神经元,该神经元的值是一个[-1 1]的值,我们称之为'firing'(热度),反应这个神经元当前活跃程度。用绿色表示非常活跃,蓝色表示非常不活跃。
基于上述方法,我们看看具体的可视化结果:
这是一个用来判断是否是url的神经元
这是用来判断此处为右括号是否合适的神经元
这是用来判断内容是否在括号内的神经元
这是用来判断网址中连续w次数的神经元
以上效果展示,是通过HTML/CSS/Javascript实现的,大家完全可以通过自己的双手编写出相似的工具。
通过这种方式,我们可以提取每个神经元在模型中起到的功能。不过并不是所有神经元的功能都可以被我们所理解,虽然大部分不易被我们解释,但仍有很多有趣的发现:
对文本行长度敏感的神经元
对引用文本敏感的神经元
对if声明敏感的神经元
对注释或引用敏感的神经元
对缩进敏感的神经元
对右括号和换行敏感的神经元
源代码
作者已经把上述涉及的所有模型代码,上传到了Github了,需要的话可以自行查找,或给老K私信 / RNN /。
作者在开发RNN模型时,偏好于PyTorch这个深度学习框架。虽然学习框架会花费大量的时间,但当你掌握它之后,会觉得非常得心应手,有很多地方比较早的Caffe和Theano框架要好。
作者认为优秀的、有效率的框架应该包含以下特点:
- 能使用GPU进行张量运算(如切分、数组/矩阵运算等);
- 框架是基于独立的脚本语言开发的,并且包含主要的深度学习函数(如前馈、后馈等);
- 必须能方便的分享预训练模型;
- 无需编译。
拓展阅读
NLP、自然语言处理,是RNN主要应用领域,有很多可以学习的方向,如:语言转文本、机器翻译、生成手写字体等。目前在这些领域,单词级语言模型的表现要优于字符级语言模型。
计算机视觉:RNN在计算机视觉的领域也逐渐发挥作用,如:帧幅级视频分类器、图片字母、视频字幕以及看图说话等应用场景。
归纳推理、记忆或注意力模型:RNN本身不具有归纳性的特征,它是一个序列记忆模型。在运算过程中,参数的叠加会给计算量带来指数级的提升。现在,在RNN研究领域里,一个叫做Attention(注意力模型)的概念正在被越来越多地提及,这也会在将来成为主要的研究方向之一,老K也会在后续的文章或视频里,分享关于Attention的学习心得,敬请期待。
研究者中,如果想精进RNN相关知识,推荐了解和学习的名单有:Alex Graves、Ilya Sutskever、Tomas Mikolov等。如果对强化学习的部分想进一步学习,可以关注David Silver或Pieter Abbeel的课程。
结论
经过上述的内容,我们已经基本了解和掌握了RNN模型理论中主要的知识点,有任何需要进一步了解的,欢迎私信/ RNN /和我讨论。
关注老K玩代码,私信关键词 / RNN / 获取更多自然语言处理材料