Torch 是进行深度机器学习研究的主要框架之一,不过研究人员必须重复实验逻辑,Facebook 推出的 Torchnet 由于鼓励模块化编程和代码重用,未来可以推动机器视觉、自然语言处理和语音处理等多个机器学习领域的发展,并且,整个研究社区都能通过插件参与贡献。
摘要
Torch 7 是一个支持 CPU 和 GPU 计算的科学计算平台,在简单的脚本语言中带有轻量的包装,可以快速执行常见的代数运算。它已成为(深度)机器学习研究的主要框架之一。不过,Torch 不提供机器学习实验的抽象和样板代码。因此,研究人员一次次重复完成那些并非彼此协作的实验逻辑。我们在此介绍 Torchnet:一个为机器学习提供抽象和样板代码的开源框架。它鼓励模块化编程和代码重用,这减少了漏洞出现的几率,并且让不同步的数据载入和高效的多GPU计算,使用起来简单明了。Torchnet 是用 Lua 语言编写的,因此用 Torch 装置在任何架构上都很容易安装。我们认为未来 Torch 会成为一个平台,外界社区可以通过插件参与贡献。
1. 简介
Torch 7 是一个针对科学计算框架的灵活计算库,包含 CPU (通过 OpenMP / SSE)和 GPU (通过 CUDA)上、针对主要代数运算的低等级高效执行,以及使用 Lua 脚本语言的非常轻量的包装(Collobert等人,2011)。Torch 有非常活跃的开发者社区,已经开发了许多程序包,包括优化、流行学习、度量学习和神经网络等等。Torch 神经网络程序包目前是一个非常流行的深度学习框架,因为它融合了灵活性和计算高效性。
Torch 神经网络程序包使得建立模型、评估模型输出、以及基于其参数或输入来计算模型输出的导数变得很容易。但是,要实施一个完整的学习实验仍然需要大量开发工作,而 torch / nn 无法为之提供支持:研究人员们需要开发一个高效的数据加载器,将可用的数据区分为训练组和测试组,用所选的优化器连接模型(梯度)进行评估,进行性能测量来监控训练、评估最终模型的质量,并且设立日志。此类样板代码的开发经常包含大量代码重复,并且容易出错,这可能会导致不正确的研究结果。尤其是缺少预定义的抽象和参考执行,让研究人员很难写出容易为他人所采用和重用的代码。
这篇论文中我们呈现 Torch:一个新的开源框架,推动(深度)机器学习实验快速前进。Torchnet 提供了一系列关键抽象、样板代码和参考执行,目标是让代码可以重用,并且实现高效。Torchnet 特别鼓励一种模块化设计,明确区分数据库、数据载入过程、模型、优化和性能测量。不同的组成部分在一个 Engine 中互相联接,它执行模型训练和评估。模块化设计使其很容易重用代码、并开发一系列实验:例如,在不同的数据库上运行同样的实验,相当于插入一个不同的数据载入器;改变评估标准,相当于插入一个不同的性能表。Torch 也不牺牲效率:它提供不同步数据载入的创新支持,并在多GPU上支持训练。
我们预见,Torchnet 未来会成为一个平台,研究社区可以通过机器学习实验或工具的插件来参与贡献。这会让验证实验设置的细节(和正确度)、复制结果和重用代码都变得更加容易。
表1:Torchnet 中所有实现的 Dataset 概况。
2. 抽象
Torchnet 从有所相似、但是问世更早的 Lush 框架中获得启发,执行五种主要类型的抽象:(1) Dataset,(2) DatasetIterator,(3) Engine,(4) Meter 和(5) Log。下面,我们分别呈现这五种主要的抽象:
2.1 Dataset
Dataset 抽象只提供两种函数:(1) size( ) 函数,返回数据库中样本的数量,以及(2) get ( idx ) 函数,返回数据库中第 idx 个样本。创建复杂的数据载入器可以通过将一个数据库插入另一个数据库,后者执行各种操作,例如数据联接、数据库分割、批量数据、数据重新取样、数据过滤和样本转换,这与 Torchnet 对模块化编程的重视一致。表1展现了通过使用 Torchnet 在数据库上可以运行的所有操作。模块化方法的主要优势是,它在少数几行代码中帮助打造复杂的数据载入器:当你想在一个新数据库上训练模型时,只要执行一个返回数据库中样本数量的函数、以及一个返回某个具体样本的函数就行。接下来,表1中的数据库可以基于某个特定的分布用于各项操作,包括重新平衡类别、打造小批量进行训练、将数据分割为训练数据和测试数据等等。而且,实施模型训练或评估的引擎,对于其用来训练的数据库基本上是不可知的:例如,当使用 Imagenet(Deng等人,2009)、MS COCO(Lin等人,2014b) 数据库等数据载入器的时候,在 MS COO 数据库上重新训练(或测试)一个 Imagenet 卷积神经网络(He等人,2016),相当于只要将 MS COCO 数据库的核心数载入器插入现有代码中就行了。
2.2 数据库迭代器
当运行训练或测试时,必须在数据库中所有样本上进行迭代,并进行参数更新或者性能测量积累(分别是 Engine 和 Meter 函数的功能)等操作。类似这样的数据库迭代器最简单的形式是一个简单的 for 循环,从1运行至数据库大小,调用 get()函数,用循环值作为输入;DatasetIterator 执行的就是这个迭代器,带有一个可选的依赖数据的过滤器(可以通过 filter ( ) 闭包来实现)。在实际情况中效率非常重要,宁可多线不同步地执行数据载入。ParallelDatasetIterator 提供这项功能:其中线的数量是预定义的,都从其中的数据库中载入数据,当迭代器中的样本遇到请求,会返回首个可用的样本。如果有足够多线,数据迭代器永远都会有可供即刻返回的可用样本,这样我们可以将整个针对训练或测试的数据载入和预处理都隐藏起来。当数据在进入模型前执行复杂转换时,这变得尤为重要,例如,在训练计算机视觉模型时经常应用在图像上的仿射变换和色彩变换(Howard,2013)。
2.3 Engine
当利用不同的模型和数据库进行实验时,经常是基于相同的训练过程。Engine 抽象提供模型训练和测试必需的样本逻辑。特别重要的是,它完成模型(默认为 nn.Module)、DatasetIterator 和损失函数(默认为 nn.Criterion)之间的交互。举个例子,一个 Engine 执行两个说明这类互动的函数:(1)一个 train( ) 函数从数据中取样、在模型中传输该数据、计算损失值、在模型中传输损失梯度并执行参数更新;(2)一个 test( ) 函数从数据中取样、在模型中传输数据并测量最终预测的质量。
Engine 提供了一系列钩子,让用户不用编辑 Engine 的核心逻辑,就能插入针对某个具体实验的代码,例如性能 Meter。这鼓励了代码重用,并可能预防漏洞,同时仍然为编写训练和测试代码提供了完全灵活性。钩子有一个特别好的特点,就是它们被打造为闭包,这样,要在训练模型使用的代码和测试模型使用的代码之间分享逻辑(例如复制数据样本到 GPU)就很方便。
目前的 Torchnet 代码包含两个 Engine 操作:(1)一个 SGDEngine,通过 SGD 执行模型的训练;(2)一个 OptimEngine,通过 torch / optim 程序包中的任何优化器——包括 AdaGrad(Duchi等人,2011)、Adam(Kingma & Ba,2015)、共轭梯度法以及 L-BFGS——执行模型的训练。
2.4. Meter
通常在学习模型的训练和测试中,我们希望测量一些特性,例如执行训练阶段所需要的时间、在所有样本上平均的损失函数值、二元分类器的 ROC 曲线下的面积、多类分类器的分类错误、检索模型的精度和召回、或者排名算法的归一化衰减累积增量。Torchnet 提供了各种 Meter,能防止研究人员一遍遍重新执行此类性能测量(此过程中还可能引入漏洞)。表2 是所有目前 Torchnet 中实现的所有 Meter 的概况。。大部分性能表(除了 TimeMeter 和AverageValueMeter 之外)执行两个主要函数:(1)add(output,target)函数,将模型输出和一或多个样本相应目标的值加入性能表;(2)value()函数,返回目前性能表的值。
2.5 日志
Torchnet 为记录实验提供两种 Log:一种简单的 Log,还有一种 RemoteLog。两者都可以以原始文本(输入到一个文档或者 stdout)和 JSON 的形式输出日志信息。
上一篇:深度好文:人工智能和云技术能碰撞出什么火花
下一篇:当人工智能遇上无人驾驶
推荐阅读最新更新时间:2024-05-03 00:30