《智能系统与技术丛书 深度学习实践:基于Caffe的解析》—1.2深度学习工具简介
1.2 深度学习工具简介
本节主要是比较TensorFlow、Caffe、Theano、Torch7、MXNet这几个主流的深度学习框架。本节对每个框架只做一个简单的说明,不做详细介绍,有兴趣的读者,请自行参阅各个框架的官方文档。
1. TensorFlow
TensorFlow是相对高阶的机器学习库,用户可以方便地使用TensorFlow设计神经网络结构,而不必为了追求高效率的实现亲自编写C++或CUDA代码。TensorFlow与Theano一样都支持自动求导,用户不需要再通过反向传播来求解梯度。其核心代码与Caffe一样都是用C++编写的,使用C++可以降低线上部署的复杂度,并且使得像手机这种内存和CPU资源都紧张的设备可以运行复杂的模型(Python则会比较消耗资源,并且执行效率也不高)。除了核心代码的C++接口之外,TensorFlow还有官方的Python、Go和Java接口,都是通过SWIG(Simplified Wrapper and Interface Generator)实现的,这样用户就可以在一个硬件配置较好的机器中使用Python进行实验了,并且还可以在资源比较紧张的嵌入式环境或需要低延迟的环境中用C++部署模型。SWIG支持对C/C++代码提供各种语言的接口,因此其他脚本语言的接口在未来也可以通过SWIG方便地添加进来。不过使用Python时有一个影响效率的问题,那就是每一个mini-batch都要从Python中输入到网络中,这个过程在mini-batch的数据量很小或者运算时间很短时,可能会造成影响比较大的延迟。
Google 在2016年2月开源了TensorFlow?Serving,这个组件可以将TensorFlow训
练好的模型导出,并部署成可以对外提供预测服务的RESTful接口,有了这一组件,TensorFlow实现了应用机器学习的全流程:从训练模型、调试参数,到打包模型,再到最后的部署服务,名副其实是一个从研究到生产整条流水线都齐备的框架。对此,可引用TensorFlow内部开发人员的描述来进行进一步的说明:“TensorFlow?Serving是一个为生产环境而设计的高性能的机器学习服务系统。它可以同时运行多个大规模的深度学习模型,支持模型生命周期管理、算法实验,并且可以高效地利用GPU资源,从而使得TensorFlow训练好的模型能够更快捷更方便地投入到实际生产环境中”。除了TensorFlow以外,其他框架都缺少生产环境部署相关的考虑,而Google作为在实际产品中广泛应用深度学习的巨头可能也意识到了这个机会,因此开发了TensorFlow Serving这个部署服务的平台。TensorFlow Serving可以说是一副王牌,它为TensorFlow成为行业标准做出了巨大的贡献。
TensorFlow拥有产品级的高质量代码,还有Google强大的开发、维护能力的加持,整体架构设计也非常优秀。相比于同样基于Python的老牌对手Theano,TensorFlow更成熟、更完善,同时Theano的很多主要开发者都去了Google开发TensorFlow(例如《Deep?Learning》一书的作者Ian?Goodfellow,他后来去了OpenAI)。Google作为巨头公司拥有比高校或者个人开发者多得多的资源投入到TensorFlow的研发中,可以预见,TensorFlow未来的发展将会是飞速的,可能会把大学或者个人维护的深度学习框架远远甩在身后。
2. Caffe
官方网址:caffe.berkeleyvision.org
GitHub:github.com/BVLC/caffe
Caffe全称为Convolutional?Architecture?for?Fast?Feature?Embedding,是一个应用广泛的开源深度学习框架(Caffe在TensorFlow出现之前一直是深度学习领域GitHub?star最多的项目),目前由伯克利视觉学中心(Berkeley?Vision?and?Learning?Center,BVLC)进行维护。Caffe的创始人是加州大学伯克利的Ph.D.贾扬清,他同时也是TensorFlow的作者之一,曾工作于MSRA、NEC和Google?Brain,目前就职于Facebook?FAIR实验室。Caffe的主要优势包括如下几点。
容易上手,网络结构都是以配置文件的形式进行定义,不需要用代码来设计网络。
训练速度快,能够训练state-of-the-art的模型与大规模的数据。
组件模块化,可以方便地拓展到新的模型和学习任务上。
Caffe的核心概念是Layer,每一个神经网络的模块都是一个Layer。Layer接收输入数据,同时经过内部计算产生输出数据。设计网络结构时,只需要把各个Layer拼接在一起构成完整的网络(通过写protobuf配置文件定义)即可。比如卷积的Layer,其输入就是图片的全部像素点,内部进行的操作是各种像素值与Layer参数的convolution操作,最后输出的是所有卷积核filter的结果。每一个Layer都需要定义两种运算,一种是正向(forward)的运算,即从输入数据计算输出结果,也就是模型的预测过程;另一种是反向(backward)的运算,即从输出端的gradient求解相对于输入的gradient,也就是反向传播算法,这部分就是模型的训练过程。实现新Layer时,需要将正向和反向两种计算过程的函数都加以实现,这部分计算需要用户自己编写C++或者CUDA(当需要在GPU中运行时)代码,因此对普通用户来说,Caffe还是非常难上手的。正如它的名字“Convolutional?Architecture?for?Fast?Feature?Embedding”所描述的,Caffe最初的设计目标只是针对图像,而没有考虑文本、语音或者时间序列的数据,因此Caffe对卷积神经网络的支持非常好,但对时间序列RNN、LSTM等的支持则不是特别充分。同时,基于Layer的模式也对RNN不是非常友好,对于RNN结构的定义比较麻烦。对于模型结构非常复杂的情况,可能需要编写冗长的配置文件才能设计好网络,阅读也比较费时费力,所以我们可能还需要使用网络可视化的一些辅助工具,这里提供一个网站http://ethereon.github.io/netscope/#/editor,在这里大家可以直接可视化自己的网络结构。
Caffe的一大优势是拥有大量的、已经训练好的经典模型,收藏在它的Model?Zoo(github.com/BVLC/caffe/wiki/Model-Zoo)中。因为其知名度较高,Caffe已广泛应用于前沿的工业界和学术界,许多提供源码的深度学习论文都是使用Caffe来实现其模型的。在计算机视觉领域Caffe的应用尤其多,可以用来进行人脸识别、图片分类、位置检测、目标追踪等。虽然Caffe最早主要是面向学术圈和研究者的,但程序运行非常稳定,代码质量较高,也深受工业界的欢迎,可用来处理对生产环境稳定性要求比较严格的应用,因此Caffe可以算是第一个主流的工业级深度学习框架。因为Caffe的底层是基于C++的,因此可以在各种硬件环境中进行编译,并且其还具有良好的移植性,Caffe支持Linux、Mac和Windows系统,甚至还可以编译部署到移动设备系统如Android和iOS上。与其他主流深度学习库类似,Caffe也提供了Python语言接口pycaffe,在接触新任务,设计新网络时可以使用该Python接口简化操作。不过,用户通常还是要使用Protobuf配置文件定义神经网络结构,再使用command line进行训练或者预测。Caffe的配置文件是一个结构化类型的“.prototxt”文件,其中使用了许多顺序连接的Layer来描述神经网络结构。Caffe的二进制可执行程序会提取这些“.prototxt”文件并按其定义来训练神经网络。理论上,Caffe的用户完全可以不用编写代码,只是定义网络结构就可以完成模型训练了。Caffe完成训练之后,用户可以把模型文件打包制作成简单易用的接口,比如可以封装成Python或MATLAB的API。不过在“.prototxt”文件内部设计网络结构可能会比较受限,不如TensorFlow或者Keras那样方便、自由。目前所受的限制主要是,Caffe的配置文件不能用编程的方式来调整超参数,如果想要做超参数训练网络模型,那么Caffe可能还需要花费大量的时间进行编程改写。Caffe在GPU上训练的性能表现良好(使用单块GTX?1080训练AlexNet时一天可以训练上百万张图片),但是Caffe目前仅支持单机多GPU的训练,并没有原生支持分布式的训练。比较幸运的是,Caffe拥有很多第三方开发者的支持,比如雅虎开源的CaffeOnSpark,可以借助Spark的分布式框架来实现Caffe的大规模分布式训练。
3. Theano
官方网址:http://www.deeplearning.net/software/theano/?
GitHub:github.com/Theano/Theano
Theano诞生于2008年,由蒙特利尔大学Lisa?Lab团队开发并维护,是一个高性能的符号计算及深度学习库。因为其出现的时间较早,因此可以算是这类库的始祖之一,也曾一度被认为是深度学习研究和应用的重要标准之一。Theano的核心是一个数学表达式的编译器,专门为处理大规模神经网络训练的计算而设计。Theano可以将用户定义的各种计算编译为高效的底层代码,并链接各种可以加速的库,比如BLAS、CUDA等。Theano允许用户定义、优化和评估包含多维数组的数学表达式,它支持将计算装载到GPU上(Theano在GPU上的性能不错,但是在CPU上却性能较差)。与Scikit-learn一样,Theano也很好地整合了NumPy,对GPU的透明使得Theano可以较为方便地进行神经网络设计,而不必直接编写CUDA代码。Theano的主要优势具体如下。
集成NumPy,可以直接使用NumPy的ndarray,API接口学习成本较低。
计算稳定性好,比如可以精准地计算输出值很小的函数(像log(1+x))。
动态地生成C或者CUDA代码,用以编译出高效的机器代码。
因为Theano在学术界非常流行,已经有很多人为它编写出了高质量的文档和教程,所以用户可以方便地查找Theano的各种FAQ,比如如何保存模型、如何运行模型等问题。不过Theano大多被当作研究工具,而不是当作产品来使用。虽然Theano支持Linux、Mac和Windows,但是因为没有底层C++的接口,因此模型的部署非常不方便,它依赖于各种Python库,并且不支持各种移动设备,所以Theano几乎没有在工业生产环境下的应用。Theano目前主要应用于教学和科研上,Theano在调试时输出的错误信息非常难以让人看懂,因此调试Theano程序(DEBUG)时会非常痛苦。同时,Theano在生产环境中使用已经训练好的模型进行预测时其性能比较差,因为预测通常使用服务器CPU(生产环境中的服务器一般没有GPU,而且GPU预测单条样本延迟高,反而不如CPU),但是Theano在CPU上的执行性能比较差。
Theano在单GPU上的执行效率不错,其性能与其他框架类似。但是运算时需要将用户的Python代码转换成CUDA代码,再编译为二进制可执行文件,因此其编译复杂模型的时间会非常久。此外,Theano在导入时也比较慢,而且一旦设定了选择某块GPU,就会无法切换到其他设备。目前,Theano在CUDA和cuDNN上并不支持多GPU,只在OpenCL和Theano自己的gpuarray库上支持多GPU训练,速度暂时还比不上CUDA的版本,并且Theano目前还没有分布式的实现。不过,Theano在训练简单网络(比如很浅的MLP)时其性能可能比TensorFlow好,因为所有代码都是运行时编译,不需要像TensorFlow那样每次喂入(feed)?mini-batch数据时都得通过低效的Python循环来实现。
Theano是一个完全基于Python(C++/CUDA代码也是打包为Python字符串的)的符号计算库。用户定义的各种运算,Theano都可以自动求导,这样就省去了完全手工编写神经网络反向传播算法的麻烦,也不需要像Caffe那样为Layer编写C++或CUDA代码。Theano对卷积神经网络的支持很好,同时它的符号计算API支持循环控制(内部名为scan),这就使得RNN的实现非常简单并且性能很高,其全面的功能也使得Theano能够支持大部分state-of-the-art的网络。Theano派生出了大量的基于它的深度学习库,包括一系列的上层封装,其中包括大名鼎鼎的Keras,Keras对神经网络抽象得非常合适,以至于可以随意切换执行计算的后端(目前同时支持Theano和TensorFlow)。Keras比较适合在探索阶段快速地尝试各种网络结构,组件都是可插拔的模块,只需要将一个个组件(比如卷积层、激活函数等)连接起来即可,但是设计新模块或者新的Layer时就不太方便了。对于新入门的工业界程序员来说,编写一个新的模块是一件很困难的事情,即使能够做到,也要考虑是否有必要花费这个时间。毕竟不是所有人都是基础科学工作者,大部分使用场景还是在工业应用中。所以简单易用是一个很重要的特性,这也是其他上层封装库的价值所在:不需要总是从最基础的tensor粒度开始设计网络,而是从更上层的Layer粒度进行网络设计。这也是此库未能在工业界流行开来的原因。
4. Torch
官方网址:http://torch.ch/?
GitHub:github.com/torch/torch7
Torch对自己的定位是LuaJIT上的一个高效的科学计算库,其支持大量的机器学习算法,同时以GPU上的计算为优先。Torch的历史悠久,但真正使其发扬光大的是在Facebook上开源了其深度学习的组件,此后包括Google、Twitter、NYU、IDIAP、Purdue等组织都大量使用Torch。Torch的设计理念是让设计机器学习算法变得更加便捷,它包含了大量的机器学习、计算机视觉、信号处理、并行运算、图像、视频、音频、网络处理的库。与Caffe类似,Torch拥有大量的已经训练好的深度学习模型。它可以支持设计非常复杂的神经网络的拓扑图结构,再并行化到CPU和GPU上,在Torch上设计新的Layer是相对比较简单的。它与TensorFlow一样,使用了底层C++加上层脚本语言调用的方式,只不过Torch使用的是Lua。Lua的性能是非常优秀的(该语言经常被用来开发游戏),常见的代码可以通过透明的JIT优化达到C语言性能的80%;在便利性上,Lua的语法简单易读,拥有漂亮和统一的结构,易于掌握,比写C/C++简洁很多,曾经,魔兽世界的插件也是使用此语言完成的;同时,Lua拥有一个非常直接的调用C程序的接口,可以简便地使用大量的基于C的库,由于底层核心是C语言编写的,因此其可以方便地移植到各种环境中。Lua支持Linux、Mac,还支持各种嵌入式系统(iOS、Android、FPGA等),只不过运行时还是必须要有LuaJIT的环境,所以工业生产环境的使用相对较少,没有Caffe和TensorFlow那么多。
为什么不使用Python而是使用LuaJIT呢?官方给出了以下几点理由。
LuaJIT的通用计算性能远胜于Python,而且可以直接在LuaJIT中操作C的pointers。Lua天然就是为了与C、C++配合而生。
Torch的框架,包含Lua是非常合适的,Lua的解释器编译后只有仅仅几百KB,而完全基于Python的程序对不同平台、系统的移植性较差,所依赖的外部库也较多。
LuaJIT的FFI拓展接口非常易学,可以方便地链接其他库到Torch中。Torch中还专门设计了N-Dimension?array?type的对象Tensor,Torch中的Tensor是一块内存的视图,同时一块内存也可能会有许多视图(Tensor)指向它,这样的设计同时兼顾了性能(直接面向内存)和便利性。此外,Torch还提供了不少相关的库,包括线性代数、卷积、傅里叶变换、绘图和统计等。
Torch的nn库支持神经网络、自编码器、线性回归、卷积网络、循环神经网络等,同时还支持定制的损失函数及梯度计算。因为Torch使用了LuaJIT,所以用户在Lua中做数据预处理等操作时可以随意使用循环等操作,而不需要像在Python中那样担心性能问题,也不需要学习Python中各种加速运算的库。不过,Lua相比Python来说还不是那么主流,对大多数用户来说还有一定的学习成本。Torch在CPU上的计算将使用OpenMP、SSE进行优化,GPU上使用CUDA、cutorch、cunn、cuDNN进行优化,同时还有cuda-convnet的wrapper。Torch拥有很多第三方的扩展可以支持RNN,使得Torch基本支持所有主流的网络。与Caffe相同的是,Torch主要是基于Layer的连接来定义网络的。Torch中新的Layer依然需要用户自己实现,不过定义新Layer和定义网络的方式很相似,非常简便,不像Caffe那么麻烦,用户需要使用C++或者CUDA定义新Layer。同时,Torch属于命令式编程模式,不像Theano、TensorFlow属于声明性编程(计算图是预定义的静态的结构),所以用它来实现某些复杂的操作(比如beam?search)比Theano和TensorFlow方便很多。但是笔者一直没有使用Torch作为笔者的主要开发工具,主要是因为现在找到合适的会写好Lua的人实在是太少了,工业界还是需要各方面配合的。
5. MXNet
官方网址:mxnet.io
GitHub:https://github.com/apache/incubator-mxnet
MXNet是DMLC(Distributed?Machine?Learning?Community)开发的一款开源的、轻量级的、可移植的、灵活的深度学习库,不过目前它已经成为了Apache下面的一个开源项目,使用的是Apache2.0的协议,大家可以放心大胆地使用。此框架可以混合使用符号编程模式和指令式编程模式来最大化效率和灵活性,目前MXNet已经是AWS官方推荐的深度学习框架。MXNet的很多作者都是中国人,其最大的贡献组织为百度,同时很多作者都来自于cxxnet、minerva和purine2等深度学习项目,博采众长,又形成了自己独立的风格。它是各个框架中率先支持多GPU和分布式的,同时其分布式性能也非常高。MXNet的核心是一个动态的依赖调度器,支持将计算任务自动并行化到多个GPU或分布式集群(支持AWS、Azure、Yarn等)中。其上层的计算图优化算法可以让符号计算执行得非常快,而且还能够节约内存,开启mirror模式会更加节省内存,甚至还可以在某些小内存GPU上训练其他框架因显存不够而训练不了的深度学习模型,也可以在移动设备(Android、iOS)上运行基于深度学习的图像识别等任务。此外,MXNet的一个很大的优点是支持非常多的语言封装,如C++、Python、R、Julia、Scala、Go、MATLAB和JavaScript等,基本上主流的脚本语言全部都支持了。在MXNet中构建一个网络需要的时间可能要比Keras、Torch这类高度封装的框架更长,但是比直接用Theano等要快。不过由于MXNet框架封装得比较完美,所以阅读它的源码并不是一件快乐的事情,因为各种地方都为了追求极致的性能将代码进行了优化。所以笔者没有选择MXNet框架为大家进行深入介绍,虽然目前的工作中MXNet框架的使用还是比较多的。
- 点赞
- 收藏
- 关注作者
评论(0)