DeepLearning经常使用库简要介绍与对比

网上近日流传一张DL相关库在Github上的受关注度对比(数据应该是2016/03/15左右统计的):
html

其中tensorflow,caffe,keras和Theano排名比较靠前。python

今日组会报告上tj师弟从我的使用经验上作了简单介绍与对比,分享给你们。c++

===================华丽的分隔线====================git

师弟的原文出处:http://tianjun.me/essays/102/github

本文将从deep learning 相关工具库的使用者角度来介绍下github上stars数排在前面的几个库(tensorflow, keras, torch, theano, skflow, lasagne, blocks)。因为个人主要研究内容为文本相关的工做,因此各个库的分析带有必定主观因素,以RNN模型为主,CNN相关的内容了解得不是特别深刻(本 文没有比较caffe和mxnet,其实主要缘由仍是本身C++过久没用了……)。算法

阅读本文你会了解:
1. 各个库是如何对神经网络中的结构和计算单元进行抽象的;
2. 如何用每一个库跑RNN相关的模型;
3. 各个库学习和使用的难以程度对比;
4. 在各个库基础之上进一步改进和开发的难易程度.编程

本文不会涉及:
1. 各个库运行时间效率的对比(我没有本身作过相关的对比实验,可是网上有不少数据能够查);
2. CNN相关模型的构建(前面提到了本身最近对这块了解得很少);
3. RNN相关模型的原理和解释(网上不少资料,能够先学习后再进一步阅读).网络

先说说这几个库之间的大体关系dom

对于一个优秀的深度学习系统,或者更广来讲优秀的科学计算系统,最重要的是编程接口的设计。他们都采用将一个领域特定语言 (domain specific language)嵌入到一个主语言中。例如numpy将矩阵运算嵌入到python中。这类嵌入通常分为两种,其中一种嵌入的较浅,其中每一个语句都按原 来的意思执行,且一般采用命令式编程(imperative programming),其中numpy和Torch就是属于这种。而另外一种则用一种深的嵌入方式,提供一整套针对具体应用的迷你语言。这一种一般使用 声明式语言(declarative programing),既用户只须要声明要作什么,而具体执行则由系统完成。这类系统包括Caffe,theano和刚公布的TensorFlow。机器学习

以上是摘自MXNet设计和实现中 的一段话。理解了这段话后,对后面各个库的进一步理解颇有帮助。MXNet的设计者表示融合了这两种编程模式,咱们先抛开mxnet,如上所述torch 是采用命令式编程,而后theano和tensorflow是采用声明式编程,skflow对经常使用的tensorflow的封装,lasagne是对 theano的封装,blocks除了对theano进行封装以外还提供了额外的处理机制,keras则是用一套接口同时封装了theano和 tensorflow,以下图所示。

从theano提及

前面说theano是声明式语言,其基本过程能够描述为如下几步:

1. 定义输入变量(x,y),输出变量(z);
2. 描述变量之间的计算关系(z = x + y);
3. 编译(f = theano.function([x, y], z);
4. 求值(f(1,2)).
那么,若是我想用theano写一个lstm呢?(具体参见这里)

1. 准备输入变量x及x_mask(维度为 batch_size * sentence_length * vector_size),目标变量target(维度为batch_size);
2. 定义初始化lstm结构单元中的参数(i, f, o, c);
3. 定义好一个scan函数,在scan函数中完成每一个结构单元的计算,根据lstm网络的性质,将结构单元的输出导入到下一步的输入。在这里,theano中的scan就是一个增强版的for循环;
4. 计算loss,采用某种算法更新参数;
5. 编译,f = theano.function([x, x_mask, target], loss);
6. 对每一个batch求值.
注意前面加黑的几个关键词,在后咱们将反复看到每一个库的设计者对这几个概念的不一样理解。

接着说tensorflow

tensorflow的设计思想和theano很接近。可是我感受,tensorflow彷佛更强调总体性和结构型。两者的明显区别在于:

1. tensorflow默认有一个Graph的结构,全部添加的结点都是在这个图结构上,可是theano中并无这个概念。个人理解是这个Graph结构对于变量的管理会方便点;
2. tensorflow目前可以在单机上多卡并行处理,其机制是经过指定gpu来分配计算过程的。所以,能够说其并行机制是数据层面的。而theano须要在载入包以前就指定gpu.
其他的不少地方都是类似的,只是换了名字而已,好比: tensorflow中的variable对应theano下的共享变量shared variables, tensorflow中的placeholder对应theano中的tensor变量, 另外tensorflow中为了不变量的来回复制,其所用的tensor的概念和theano中不太同样

而后来看看tensorflow是怎么实现一个LSTM网络的,与theano不一样,tensorflow已经对rnn_cell和lstm_cell作了封装,所以写起来容易了不少。

1. 定义好输入及中间变量;
2. 采用for循环将每一个lstm_cell的输入输出组装起来;
3. 剩下的也就没有新意了,计算loss,更新state.
咱们后面再讨论这种封装方式与其余库的对比。

再说torch

torch的代码写起来有点像写matlab,自己torch是一个科学计算的大集合(我感受只是借了lua这个语言一个外壳,方便和c及c++交互罢了,从这个角度来看,我以为julia这门语言彷佛大有潜力),这里咱们主要是讨论其中的nn和rnn模块。
我本身对lua及torch都不是很熟,可是好在语法不复杂,基本都能看懂,建议你们也能花点时间学习下,这样下次看到哪篇paper里实验部分用 torch写的时候,不至于彻底看不懂。尽管我对torch的了解不深,可是不得不说torch对剩下其它几个库的设计影响很是大!

在torch的nn模块里,首先对整个网络结构作了分类抽象。首先是最顶层的抽象Model,这个里面最基础的就是output和 grad_output,记忆中和caffe的抽象是相似的,将计算结果和偏导结果用一个抽象类来表示了。而后是Sequential, Parallel 及 Concat这三个容器。Sequential用于描述网络中一层层的序列关系,典型的就是MLP,Parallel能够用于分别处理输入的不一样维度,而 Concat则能够用于合并操做。通常来讲,咱们如今的网络结构均可以经过这三种结构拼接获得。

而后再看看torch的rnn模块中如何构建lstm网络的:

和tensorflow同样,首先是继承自AbstractRecurrent的一个抽象,而后是参数配置和初始化,不一样之处在于,其对LSTM中的门结构也作了进一步抽象,最后,用Sequence代替了for循环的功能,从而提供一个完整的网络结构。

小结

经过上面的简单描述,咱们对这三个基本库有了些大体的印象。

1. torch是最庞大的库,若是一开始就选择这个库做为工具的话,还算说得过去,不然学习的代价有点大,由于日常作实验涉及的每每不仅是跑跑模型这么简单,还涉及到数据的预处理与分析,相关图表的绘制,对比实验等等。这样一来要学习的东西就比较多了;
2. theano因为借用了numpy,scipy等python下科学计算的库,相对torch来讲要轻松一些。不过,theano自己并无像其它两个库同样提供cnn,rnn等模型的抽象类,所以每每不会直接使用theano去写模型;
3. tensorflow则更像是为神经网络相关模型而定制的。从顶层设计上就以graph为依托,经过不一样的Session来控制计算流.

从库的使用者角度来讲,tensorflow和torch都还不错。可是,若是涉及网络结构(这里特指RNN相关的网络)修改,那么torch要相 对容易一些,主要是多了一个Gate的抽象,中间参数的处理上不须要太操心,而tensorflow中LSTM和RNN抽象类的耦合比较紧,若是涉及内部 结构的修改会稍稍麻烦点,须要重写的方法比较多。

tensorflow开源时间不久,先抛开不计。因为theano缺乏对神经网络结构的抽象,而torch中nn模块又设计得很合理,因而后面涌现的基于theano的库多多少少都有所参照。

Keras

keras设计的level有点高,其设想的就是底层的计算模块是可拔插的。这个功能固然看起来很炫酷,我想用tensorflow就用 tensorflow,想用theano就用theano做为计算内核,然而代价也是有的,若是你想改其中的结构,复杂程度立立刻去了。我以为这个库的目 标用户仅限于使用现有神经网络单元结构的人。若是你发现某个结构keras里没有?没事,这个项目开发者众多,发起个issue,立刻就有人填坑(好比 highway network, 我在其它几个库里还没发现,这里竟然就有了,虽然并不复杂)。若是你想构造个本身的结构单元?那得了,您仍是看看后面几个库吧。

综上所述,keras最大的亮点就是,简洁而全面。正所谓人多力量大嘛! 因为其底层处于兼容性作了一套本身的封装,想改的话稍显麻烦。

若是你以为看完keras还不知道怎么用?想来点更简单的?有!sklearn用过把,fit, predict两步便可,傻瓜式操做,人人都是机器学习大神。skflow就是相似的,看名字就知道了。不过是基于tensorflow开发的。我反正是没用过这个库……

Lasagne

lasagne对网络结构的抽象和上面的几个库有很大的不一样,在lasagne中基本抽象单元是Layer,对应到整个神经网络中的一层结构。这个 layer能够是cnn也能够是rnn结构,除此以外还有一个MergeLayer,就是多输入多输出的结构。和torch同样,也对Gate门结构作了 抽象。

这样设计有好处也有麻烦的地方:

1. 好处是,写出来的网络结构很简洁,网络结构的初始化和配置都包含在layer初始化参数里;
2. 不方便的地方是,只引入了layer结构抽象层,是在是有些单一,若是能再加一个相似torch中的Sequential结构就perfect了,由于一 旦涉及到循环,就不得不回头去使用theano中的scan函数,说实话,scan函数设计得太复杂了点。(固然,做者是不这么认为的,设计者认为 lasagne并非要将theano彻底隔离开,相反,lasagne中的全部变量都应该相对theano是透明的Transparency)。

此外,lasagne中LSTM网络的实现与前面的大体相同,实现细节上,lasagne中的lstm类直接继承自MergeLayer,而后内部 采用scan函数实现,像其它库因为有循环结构的抽象实现,所以每一个lstm_cell类只须要完成单个结点内部的运算(也即只实现scan函数中的 _step辅助函数)

总的感受就是,lasagne在类的抽象上并无过分设计,整个网络中的参数采用自顶向下的宽度优先算法获取,所以,只要你愿意,你能够任意在这个网络上“凿”个洞,获得该局部网络的关系。有必定的扩展性优点。

Blocks

这个库是我最看好的一个库,做者应该从torch中借鉴了不少思想。

在这个库中,每个运算都看作是一块砖,这块砖涉及配置、分配、应用和初始化这四步。更重要的一点是,brick与brick之间能够嵌套,从而获得更抽象的brick。这下子解决了咱们前面一直碰到的一个问题:抽象层次的把握!前面大多都是根据抽象层次的不一样设计各自的类,而blocks经过嵌套将类统一块儿来,这样咱们在设计本身的模块时,能够很方便地选取合适尺寸的brick。

相比lasagne中直接根据layer.get_output来获取参数,blocks采用了ComputationGraph来管理整个网络结 构,个人理解是,lasagne的那种方式仍是有点野蛮……采用ComputationGraph以后,能够同时制定输入和输出对象,这样即便网络结构变 得更复杂了,咱们也能够为所欲为指定其中某个部分来更新。

下面用blocks文档中关于rnn的一个模型来讲明blocks在个性化定制方面是多么优雅。先看图:

若是要设计这样一个stack的模型,就须要make your hands dirty 了。在lasagne中,这个总体会被看作一个layer,因此须要本身重写一个layer,那跟直接用theano写无异了……keras中也没有提供 现有的模型,因此……对于tensorflow和torch来讲,须要重写AbstractRecurrent类,从而可让其接受两个输入。

相比之下Keras提供的解决方案就比较优雅,经过iterate将simplerecurrent在time_step维度上缩短到了1步,而后再将整个链接结构封装起来。(也许其它几个库也有相似的控制,暂时没发现)

固然,除了上面这些抽象层面的易用性,blocks还提供了丰富的可视化调试和控制接口,以及数据预处理的fuel模块。这些功能在整个工程变得愈来愈臃肿的时候仍是很实用的。

总结

Torch的学习成本比较低,建议稍微花点时间学习,这样之后碰到相关代码不至于看不懂;

在了解theano的基础上,若是只是想跑一下现有的模型不关注底层的实现,快速验证能够直接用Keras,上手快,模块清晰。若是打算持续投入, 涉及大量网络结构改进,须要深度定制的网络,推荐使用blocks,其对训练过程的控制有着独特的优点。对于一个相对复杂的实验,建议用blocks,主 要是预处理数据管理方便,图表信息很全。由于越到后面,这块话的时间甚至遇上建模的时间了.

另外,这里没有涉及Caffe和MxNet,Caffe听说图像处理中用的比较多,虽然最近也支持RNN相关模型了,但彷佛你们并不捧场。
MxNet支持多机多卡并行,这点就决定了其在工程项目中的应用。底层用c++写的,也提供了python接口,一样也是以CNN相关模型为主,网上评价其对RNN相关模型支持很好,没亲自试过。

另外须要注意的一点是,一样的数据,用不一样库的同一个算法时,结果极可能会出现几个点的差别,这每每是不一样库中对默认参数的初始化方式不一样引发的,须要仔细检查下。

 

from: http://jacoxu.com/?p=1836

相关文章
相关标签/搜索