为什么 PyTorch 这么火?一线开发者这样说


来源:雷锋网

编者按:2017 年初,Facebook 在机器学习和科学计算工具 Torch 的基础上,针对 Python 语言发布了一个全新的机器学习工具包 PyTorch。一经发布,这款开源工具包就受到了业界的广泛关注和讨论,经过几个月的发展,目前 PyTorch 已经成为从业者最重要的研发工具之一。PyTorch 为什么如此受欢迎,研究人员是出于怎样的考虑选择了 PyTorch?针对这些问题,我们今天不妨来看看专业人士怎么说。

以下内容转载自饶锦峰在知乎上的问答,雷锋网已或授权。饶锦峰先后就读于浙江大学和美国马里兰大学的计算机科学学院,曾于微软和谷歌实习,研究方向是深度神经网络和自然语言处理等。

PyTorch比较吸引我的特性有以下几点:

1. 支持Python。之前用Lua写代码不要太痛苦(用 Torch 时),各种功能性函数没有。举个例子,Lua里面最主要的数据结构是table(类似于Python语言里面的dict),table里元素是通过key的形式来访问的。很多情况下我想访问table里面有多少个元素,这要是在python或者java里面就是table.size()一句话就能搞定的,但放在Lua里面,唯一可行的方案就是像下面这样:

function tablelength(T)
 local count = 0
 for _ in pairs(T) do count = count + 1 end
 return countend

2. 支持autograd。不用自己去定义和数学推导back-propagation. 这个还是比较实用的,记得很早的时候,torch里面还没有计算cosine similarity的函数,得自己定义cosine的forward和backward函数,又温习了一遍微积分=_=不过自己写backward也是有好处的,这是一个很好的学习过程,对你理解深度学习的原理有很大的帮助。当你的代码出错了的时候,你能有个比较清晰的思路从哪里开始debug.

3. 更容易debug。无论是Torch还是PyTorch的底层都是一个C语言实现的库函数。在写深度学习的代码的时候最痛苦的一块可能就是debug了。当结果出现问题的时候你不知道你是因为你的hyper-parameter设得不对,还是模型定义的时候出错了,或者是某一层layer计算的时候出错了和整个模型的assumption就不适合这个数据集。要找出原因只能不断的简化模型并且试错,这时候PyTorch能够逐层打印出计算结果就显得非常灵活了(简直是NN debug的救星)。虽然其他一些工具Keras也能支持显示每层layer的output,但是依赖于一些辅助函数,写起来也比较麻烦。

4. 支持动态图的创建。现在的深度学习平台在定义模型的时候主要用两种方式:static computation graph(静态图模型) 和 dynamic computation graph(动态图模型)。 绝大部分平台都采用的是static的定义方式,包括TensorFlow, Theano, Caffe,Keras等。静态图定义的缺陷是在处理数据前必须定义好完整的一套模型,能够处理所有的边际情况。比如在声明模型前必须知道整个数据中句子的最大长度。相反动态图模型(现有的平台比如PyTorch, Chainer, Dynet)能够非常自由的定义模型。举个例子,传统的LSTM往往处理一个句子的时候都是以word为单位,然后利用word2vec来初始化词向量。但是往往有一些很奇怪的词在vocabulary里是找不到的,也就是没法用word2vec初始化词向量。这时候你可能想用characer-level(字符)级别的表示来初始化那个单词,就需要借助动态图模型的定义了。简单来说动态图模型允许你在运行程序的时候动态去修正你的模型结构,来处理各种奇奇怪怪的边角输入,这在学术研究的时候的灵活性就体现出来了。

上图左边为静态图的计算框架,右边为动态图的框架 [1]。静态图需要在处理数据前定义好一套完整的模型;而动态图模型允许用户先定义好一套基本的框架再根据数据来实时修正模型。

5. 和 LuaJIT 相比降低了大概30%-50%的内存使用率,而且 LuaJIT 是有 2G 的内存上限的(这个有时候很麻烦)。另外谢谢评论区的@peng sun补充,LuaJIT的内存上限是指lua内部的数据结构,比如table, string等,不包括用户定义的数据结构,比如torch.Tensor之类等,不然把word embedding load到内存里就炸了。。有时候为了避免内存溢出的情况,会用Lua 5.1编译,而不用LuaJIT。关于Lua 编译器和LuaJIT的区别,可以参看这个帖子:What makes LuaJIT faster than Lua?

补充一点是,目前版本在效率上比Torch慢5%,可能是因为创建动态图的时候多耗时了. 在PyTorch网站上有个帖子讨论和Torch的比较,可以看看:Roadmap for torch and pytorch

其他一些我会考虑的点:

1. 迁移成本。作为Torch用户,我已经很习惯它的一套开发流程了,也能够比较高效的实现定义的模型了。如果要迁移到PyTorch平台,需要学习下里面的一些函数定义和使用,不想换平台的时候太麻烦。

2. 社区支持。作为一个新开发的平台,PyTorch的社区支持还是比较弱的,还没有什么开源的代码和模型。我不知道有多少老Torch用户去转移到PyTorch上面去,但是有一个良好的社区环境是需要长时间的积累的。

在选择一个深度学习平台上,我会主要考虑易用性,学习成本和社区环境。举个例子就Torch而言,社区环境很好,但学习成本和易用性上要打个折扣,我想这是很多新用户可能不会选择Torch的原因,也是PyTorch开发的一部分初衷吧(降低学习成本和提高易用性来吸引更多的新用户)。就PyTorch而言,刚开始开放出来社区支持还不是很强,不过最近一段时间口碑上去得很快,社区的增长也比较迅速。

总体来说我还是很喜欢 PyTorch 的编程模式的,非常好用,推荐 researcher 使用。相反,如果只是想了解一下深度学习,并且快速开发出一套简单实用的深度学习模型,推荐 Keras+TensorFlow 作为入门工具(API简单+文档全+社区强)。