基于诸如 TensorFlow 等几种流行工具包的编程模型使用的是静态声明方法,这些工具包将网络架构的声明和执行进行了分离。
静态声明优点众多。在定义了计算图后,我们可以通过多种方式对其进行优化,以便尽可能快地完成后续的重复执行计算。而且,以在 TensorFlow 中的应用为例,静态声明也简化了跨多个设备的计算分布。但即便如此,静态声明在以下几种情况下依旧有不便之处。
可变大小的输入
可变结构的输入
非默认的推理算法
可变结构的输出
当然,如果计算图可以表示在声明时间内大小未指定的对象,那么静态声明也可以处理可变大小输入。流程控制操作(如条件执行和迭代)能够被添加到计算图所支持的操作清单中。比如说,要运行可变序列长度的 RNN,Theano 提供扫描操作,TensorFlow 提供动态 RNN 操作。
虽然从理论上来看,可以用静态声明来处理可变结构,但在实际应用中依然存在一些难点:
难以表达复杂的流程控制逻辑
计算图实现的复杂性
调试困难
这些难点直接关乎一些严重的软件工程风险。作为一种替代方案,DyNet 提出了一个新的编程模型:计算图的动态声明。PDF 链接如下:
https://arxiv.org/pdf/1701.03980.pdf
DyNet 旨在最小化图构造的计算成本,从而实现高效的动态计算。通过这种方式,DyNet 不仅移除了快速原型设计的障碍(rapid prototyping),也实现了在静态计算范例中不易实现的更复杂的神经网络应用。
用 C++ 编写的 DyNet 后端,经过优化可消除计算图构造的开销,并支持在 CPU 或 GPU 上的高效执行。由于处理可变大小输入的流程控制和工具仍留在宿主语言中(而不是静态声明所要求的计算图中),计算图需支持更少的操作类型,并且这些操作类型倾向于更具体的指定(例如,张量的大小应该是已知的,而不是执行时推断的)。
DyNet 程序遵循以下模板:
创建模型(Model)
向模型里增加必要的参数(Parameters)和查找表参数(LookupParameters)。创建一个训练器(Trainer)对象,并使之与模型(Model)相关联。
对每个样本(example):
(a) 创建一个新的计算图(ComputationGraph),并且建立一个表达式(Expression)来填充该计算图,该表达式用来表示针对这个样本想要进行的计算。
(b) 通过调用最终表达式(Expression)的 value() 或者 npvalue() 函数,计算整个图前向计算的结果。
(c) 如果训练的话,计算损失函数的表达式(Expression),并使用它的 backward() 函数来进行反向传播。
(d) 使用训练器对模型(Model)的参数进行更新。
与像 TensorFlow 这样的静态声明库对比可以发现,DyNet 中创建一个图的步骤落在每一个循环里。这有利于用户为每个实例(instance)灵活地创建新的图结构,并使用他们掌握的编程语言中的流控句法(flow control syntax,比如迭代(iteration))来做这些。
示例程序如下:
这个程序显示了为一个简单分类器进行最大似然训练的过程,这个分类器为每个需要它预测的类计算一个向量分数,然后返回这个得分最高的类 ID 以及这个最高分。我们可以注意到,在第 14 行做了符号图的动态定义,在第 15 行,前向传递执行,在第 16 行,反向传递自动差异执行。在第 19 行,训练结束后,推理完成。考虑到推理中的动态输入 / 图,图将会针对每一个服务输入做重构。
目前,DyNet 是集中式的。而且,为了提高计算效率它还支持自动微型批处理(automatic mini-batching),为想要在模型中实现微型批处理的用户减轻负担。对于不支持微型批处理的更复杂的模型,DyNet 支持数据并行(data-parallel)多线程处理(multi-processing),这样的话,异步参数的更新可以在多个线程中执行,这也使在训练时间内并行化任何模型(在单个机器中)变得简单些。
Petuum Inc. 正在致力于通过使用 Poseidon 机器学习通信框架将这种并行性从单机处理扩展到多机数据并行处理。
查看英文原文:
http://muratbuffalo.blogspot.jp/2017/11/paper-summary-dynet-dynamic-neural.htm
点击下方图片即可阅读
学习人工智能需要哪些必备的数学基础?