本篇文章3683字,读完约9分钟
雷锋。这篇文章最初发表在英伟达的博客上,由雷锋编辑。
从siri到谷歌翻译,深层神经网络在促进机器对自然语言的理解方面取得了长足的进步。
到目前为止,大多数模型把语言看作是一个扁平的单词序列,并使用递归神经网络来处理它。然而,语言学家认为这不是看待语言的最佳方式,它应该被理解为短语的层次树。由于这种结构的支持,递归神经网络得到了大量深入的学习研究。在行业中,这些模型以难以实施和运行效率低下而闻名。
然而,对于今年的facebook开源新深度学习框架pytorch,业内人士认为它的主要贡献在于构建了结构递归神经网络和其他复杂的自然语言处理模型,使其变得更加容易。
结构递归神经网络是显示pytorch灵活性的一个很好的例子。同时,pytorch是一个功能完备的框架,用于各种深度学习任务,尽管它特别适用于计算机视觉问题。它是由fair,facebook人工智能研究所的研究人员发明的。pytorch将torch7中高效灵活的gpu加速后端算法库与直观的python前端相结合,能够快速创建原型、高度可读的代码以及对各种深度学习模型的支持。
旋转这篇文章将引导你在pytorch上实现一个带有递归追踪器和treelstm节点的结构化递归神经网络,即旋转。对于相当多的主流深度学习框架来说,这是一个困难的自然语言处理模型。我在这里描述的实现部分已经完成了批处理,所以它可以利用gpu加速性能,这比没有批处理的版本快得多。
spinn模型的全称是“堆栈增强解析器解释器神经网络”。作为自然语言推理任务的解决方案,spinn模型是与bowman等人(2016)一起发表的,该模型使用了当时的斯坦福snli数据集。
这里的任务是将成对的句子分成三类:如果第一句是对用户看不到的图像的准确注释,第二句也是对图像的注释,那么第二句是(a)绝对准确(b)可能准确还是(c)绝对不准确?例如,假设第一句话是“两只狗正在穿过一片田野。”那么,使这组句子“绝对正确”的句子可以是“户外有动物”;使它们“可能准确”的是“一些小狗跑着去抓棍子”(一群小狗跑着去捡棍子);使它们“绝对不准确”的可能是“宠物正坐在沙发上”。
导致spinn诞生的研究,为了实现其目标,应该在决定句子之间的关系之前,将每个句子编码成一个固定长度的向量表达式(还有其他方法,如注意模型)。
数据集包含机器生成的句法分析树,它将每个句子中的单词组合成短语和从句,每个短语和从句都有独立的含义,并由两个单词或子短语组成。许多语言学家认为,人类理解语言的方式是通过层次化的方式组合意义,就像这种树形结构一样。因此,可能有必要创建一个以相同方式运行的神经网络。以下示例是数据集中的一个句子,其语法树用括号表示:
( (教堂) (有(天花板上的)裂缝)。) )
用支持语法树结构的神经网络对该句子进行编码,方法之一是创建一个神经网络层约简,将短语(通过像手套一样的单词嵌入来表示)或短语组合起来,然后循环应用该层,将前一次约简操作的结果作为句子的编码:
x =减少(“上限”)
y =减少(英寸,x)
...等等。
但是如果我想让神经网络以一种更“人性化”的方式运作呢?可以从左到右阅读,保持上下文,并使用语法树来组合短语?或者,如果我想训练一个神经网络,根据我看到这个句子时读到的单词创建自己的语法树?这是同一个语法树,但书写方式略有不同:
教堂的天花板有裂缝。) )
第三种方法仍然是一样的:
歌词:教堂的天花板有裂缝。
解析:s s r s s s s s r r r r s r r
我所做的就是去掉括号,用“S”标记单词“shift”,用“R”替换右边的括号“reduce”。现在,信息可以作为一系列指令从左到右读取,以操作类似于堆栈的堆栈和缓冲区,其结果与上述循环模式相同:
将文本导入缓冲区。
从第一个单词“the”弹出缓冲区,并把推栈,当“the”应该在“church”前面。
pop应用程序的前两个堆栈值减少并将结果推送到堆栈上。
“有”来自缓冲流行,“裂缝”,“在”,“在”和“天花板”。
重复四次:弹出的前两个堆栈值,应用减少和推送的结果。
","然后将它推入堆栈。
重复两次:pop的前两个堆栈值,应用减少和推送结果。
pop的剩余堆栈值作为句子代码返回。
我还想维护上下文,处理其他信息——句子中已被系统读取的部分,并对句子的后半部分执行缩减操作。因此,我将用三个参数的函数替换两个参数的缩减函数,这将被导入到左子树、右子树短语和当前上下文状态中。这种状态是由第二个神经网络层产生的——一个叫做跟踪器的循环单元。给定现有的句子上下文状态,tracker在堆栈操作的每一步生成一个新状态(在读取每个单词和右括号之后),即缓冲区顶部的条目b和堆栈顶部的两个条目s1和s2:
上下文[t+1] =跟踪器(上下文[t],b,s1,s2)
想象一下用你最喜欢的编程语言写这些东西:对于每个需要处理的句子,它将从缓冲区加载下一个单词,运行跟踪器,检查是将它推入堆栈还是减少它,并在操作后重复它,直到整个句子被处理。当应用于一个句子时,这个过程由一个大而复杂的深层神经网络运行,网络上的两个可训练层根据堆栈操作指定的方式反复执行。
但是如果你熟悉传统的深度学习框架,比如张量流和模拟退火,你就会知道执行这样的动态过程有多难。值得花些时间来思考为什么他们不能处理这种任务,以及pytorch是否能提供一些不同的东西。
图论
本质上,深层神经网络只是一个具有大量参数的复杂函数。深度学习的目标是通过计算偏导数和测量损耗来优化这些参数。如果函数用计算图的结构表示,反操作可以消除不必要的计算梯度的工作。所有现代深度学习框架都基于这种反向传播的概念。因此,每个框架都需要找到一种方法来表示计算图。
大多数主流深度学习框架,如tensorflow、an ano、keras和torch7的nngraph算法库,都预先创建了静态对象。这个图是由看起来像数学表达式的代码定义的,但是它的变量实际上是没有被赋值的占位符。一个由占位符标量组成的图被编译成一个函数,然后在训练数据批次上重复运行以生成输出和梯度。
这个静态计算图表在美国有线电视新闻网上运行良好,后者的结构通常是固定的。然而,对于许多应用程序,开发人员需要用数据修改神经网络图的机制。在自然语言处理中,研究人员通常希望扩展时间递归神经网络,并且最好输入尽可能多的时间步长。上面提到的spinn模型的堆栈操作很大程度上依赖于控制流,例如“for”和“if”语句,来定义特定句子的计算图的结构。在一个更复杂的示例中,您可能希望构建一个模型,其结构取决于子网的输出。
一些想法可以被塞进静态图形系统,但不是全部,而且几乎总是以更差的透明度和难以理解的代码为代价。该框架需要向计算图中添加表示基本编程指令(循环和条件)的特殊节点,用户需要学习和使用这些节点,而不是编程语言中的“for”和“if”语句。这是因为任何程序员使用的控制流语句只能使用一次,并且在创建图形时计算通道是硬编码的。
例如,一个特殊的控制流节点tf.while_loop需要对字中的向量(从初始状态h0开始)运行一个时间递归神经网络(rnn_unit)。当张量流运行时,它需要一个额外的特殊节点来获得字长,因为它只是代码运行时的一个占位符。
#张量流
#(该代码在模型初始化期间运行一次)
#“单词”不是一个真正的列表(它是一个占位符变量)
#我不能用" len "
cond =λI,h:I cell =λI,h:rnn _ unit(word[I],h)
i = 0
_,h = tf.while_loop(cond,cell,(I,h0))
一种根本不同的方法是动态计算图,它在几十年前就已经在学术界进行了研究,也被称为“运行时定义”。Kayak,由哈佛大学开发,chainer和dynet,一个面向研究的框架,都是基于动态计算图。在这个框架中,计算图是在运行时创建或重新创建的。前馈信道操作的代码也为反向传播创建了所需的数据结构。这种方法生成更直观的代码,因为控制流是使用标准的“for”和“if”编写的。修复漏洞也更容易,因为运行时断点和堆栈跟踪允许您直接找到编写的代码,而不是在引擎中执行编译后的函数。通过简单的python“for”循环,可以在动态框架中实现相同变长的时间递归神经网络。
# pytorch(也在chainer工作)
#(该代码在模型的每次向前传递时运行)
#“单词”是一个python列表,其中包含实际值
h = h0
逐字逐句:
h = rnn_unit(字,h)
Pytorch是第一个“按运行定义”的深度学习框架,在性能和灵活性方面与静态图形框架相当。这使得它适用于开发几乎所有的模型,从标准的卷积网络到最离谱的强化学习思想。在下一节中,我们将一起看看spinn的代码实现。
接下来,请关注雷锋的后续文章。
雷锋文章版权所有。严禁擅自转载。详情请参考转载说明。
来源:搜狐微门户
标题:从原理到实战 英伟达教你用PyTorch搭建RNN
地址:http://www.shwmhw.com/shxw/63443.html