深度学习500问——Chapter12:网络搭建及训练(2)

2024-06-21 13:30:02 浏览数 (2)

12.2 PyTorch

12.2.1 PyTorch是什么

PyTorch 是torch的python版本,是由Facebook开源的神经网络框架,专门针对GPU加速的深度神经网络(DNN)编程。Torch是一个经典的对多维矩阵数据进行操作的张量(tensor)库,在机器学习和其他数学密集型应用有广泛应用。与TensorFlow的静态计算图不同,pytorch的计算图是动态的,可以根据计算需要实时改变计算图。但由于Torch语言采用Lua,导致在国内一直很小众,并逐渐被支持Python的Tensorflow抢走用户。作为经典机器学习库Torch的端口,PyTorch为Python语言使用者提供了舒适的写代码选择。

12.2.2 为什么选择 Pytorch

1. 简洁

PyTorch的设计追求最少的封装,尽量避免重复造轮子。不像TensorFlow 中充斥着 session、graph、operation、name_scope、variable、tensor、layer等全新的概念,PyTorch的设计遵循 tensor → variable(autograd)→ nn.Module 三个由低到高的抽象层次,分别代表高维数组(张量)、自动求导(变量)和神经网络(层/模块),而且这三个抽象之间联系紧密,可以同时进行修改和操作。简洁的设计带来的另一个好处就是代码易于理解。PyTorch的源码只有TensorFlow的十分之一左右,更少的抽象、更直观的设计使得PyTorch的源码十分易于阅读。

2. 阅读

PyTorch的灵活性不以速度为代价,在许多测评中,PyTorch的速度表现胜过 TensorFlow 和 Keras等框架。框架的运行速度和程序员的编码水平有极大关系,但同样的算法,使用PyTorch实现的那个更有可能快过用其他框架实现的。

3. 易用

PyTorch是所有框架中面向对象设计的最优雅的一个。PyTorch的面向对象的接口设计来源于Torch,而Torch的接口设计以灵活易用而著称,Keras作者最初就是受Torch的启发才开发了Keras。PyTorch继承了Torch的衣钵,尤其是API的设计和模块的接口都与Torch高度一致。PyTorch的设计最符合人们的思维,它让用户尽可能地专注于实现自己的想法,即所思即所得,不需要考虑太多关于框架本身的束缚。

4. 活跃的社区

PyTorch 提供了完整的文档,循序渐进的指南,作者亲自维护的论坛 供用户交流和求教问题。Facebook 人工智能研究院对 PyTorch 提供了强力支持,作为当今排名前三的深度学习研究机构,FAIR的支持足以确保PyTorch获得持续的开发更新,不至于像许多由个人开发的框架那样昙花一现。

12.2.3 PyTorch的架构是怎样的

PyTorch(Caffe2)通过混合前端,分布式训练以及工具和库生态系统实现快速,灵活的实验和高效生产。PyTorch和TensorFlow具有不同计算图实现形式,TensorFlow采用静态图机制(预定义后再使用),PyTorch采用动态图机制(运行时动态定义)。PyTorch具有以下高级特征:

混合前端:新的混合前端在急切模式下提供易用性和灵活性,同时无缝转换到图形模式,以便在C 运行时环境中实现速度,优化和功能。

分布式训练:通过利用本地支持集合操作的异步执行和可从Python和C 访问的对等通信,优化了性能。

Python优先:PyTorch为了深入集成到Python中而构建的,因此它可以与流行的库和Cython和Numba等软件包一起使用。

丰富的工具和库:活跃的研究人员和开发人员社区建立了丰富的工具和库生态系统,用于扩展PyTorch并支持从计算机视觉到强化学习等领域的开发。

本机ONNX支持:以标准ONNX(开放式神经网络交换)格式导出模型,以便直接访问与ONXX兼容的平台,运行时,可视化工具等。

C 前端:C 前端是PyTorch的纯C 接口,它遵循已建立的Python前端的设计和体系结构。它旨在实现高性能,低延迟和裸机C 应用程序的研究。

使用GPU和CPU优化的深度学习张量。

12.2.4 Pytoch和tensorflow之间的差异在哪里

上面也讲了PyTorch最大优势是建立的神经网络动态的,对比静态的 Tensorflow,它能更有效地处理一些问题,比如说RNN变化时间长度的输出。各有各的优势和劣势。两者都是大公司发布的,Tensorflow(Google)宣称在分布式训练上下了很大的功夫,那就默认Tensorflow在分布式训练上要超出PyTorch(Facebook),还有tensorboard可视化工具,但是Tensorflow的静态计算图使得在RNN上有一点点被动(虽然它用其他途径解决了),不过用PyTorch的时候,会对这种动态的RNN有更好的理解。而且Tensorflow的高度工业化,它的底层代码很难看懂,Pytorch好那么一点点,如果深入PytorchAPI,至少能比看Tensorflow多看懂一点点Pytorch的底层在干啥。

12.2.5 Pytorch有哪些常用工具包
  • torch:类似Numpy的张量库,强GPU支持;
  • torch.autograd:基于tape的自动区别库,支持torch之中的所有可区分张量运行;
  • torch.nn:为最大化灵活性未涉及,与autograd深度整合的神经网络库;
  • torch.optim:与torch.nn一起使用的优化包,包含SGD、RMSProp、LBFGS、Adam等标准优化方式;
  • torch.multiprocessing:python多进程并发,进程之间torch Tensors的内存共享;
  • torch.utils:数据载入器,具有训练器和其他便利功能;
  • torch.legacy(.nn/.optim):处于向后兼容性考虑,从Torch移植来的legacy代码。

12.3 Caffe

12.3.1 什么是Caffe

Caffe的全称应该是 Convolutional Architecture for Fast Feature Embedding,它是一个清晰、高效的深度学习框架,它是开源的,核心语言是C ,它支持命令行、Python和Matlab接口,它既可以在CPU上运行也可以在GPU上运行,它的license是BSD 2-Clause。

12.3.2 Caffe是特点是什么

(1)、模块化:Caffe从一开始就设计得尽可能模块化,允许对新数据格式、网络层和损失函数进行扩展。

(2)、表示和实现分离:Caffe的模型(model)定义是用Protocol Buffer语言写进配置文件的。以任意有向无环图的形式,Caffe支持网络架构。Caffe会根据网络的需要来正确占用内存。通过一个函数调用,实现CPU和GPU之间的切换。

(3)、测试覆盖:在Caffe中,每一个单一的模块都对应一个测试。

(4)、python和Matlab接口:同时提供Python和Matlab接口。

(5)、预训练参考模型:针对视觉项目,Caffe提供了一些参考模型,这些模型仅应用在学术和非商业领域,它们的license不是BSD。

12.3.3 Caffe的设计思想怎样的

基本上,Caffe 沿用了神经网络的一个简单假设----所有的计算都是以layer的形式表示的,layer做的事情就是take一些数据,然后输出一些计算以后的结果,比如说卷积,就是输入一个图像,然后和这一层的参数(filter)做卷积,然后输出卷积的结果。每一个layer需要做两个计算:forward是从输入计算输出,然后backward是从上面给的gradient来计算相对于输入的gradient,只要这两个函数实现了以后,我们就可以把很多层连接成一个网络,这个网络做的事情就是输入我们的数据(图像或者语音或者whatever),然后来计算我们需要的输出(比如说识别的label),在training的时候,我们可以根据已有的label来计算loss和gradient,然后用gradient来update网络的参数,这个就是Caffe的一个基本流程。

  基本上,最简单地用Caffe上手的方法就是先把数据写成Caffe的格式,然后设计一个网络,然后用Caffe提供的solver来做优化看效果如何,如果你的数据是图像的话,可以从现有的网络,比如说alexnet或者googlenet开始,然后做fine tuning,如果你的数据稍有不同,比如说是直接的float vector,你可能需要做一些custom的configuration,Caffe的logistic regression example兴许会很有帮助。

  Fine tune方法:fine tuning的想法就是说,在imagenet那么大的数据集上train好一个很牛的网络了,那别的task上肯定也不错,所以我们可以把pretrain的网络拿过来,然后只重新train最后几层,重新train的意思是说,比如我以前需要classify imagenet的一千类,现在我只想识别是狗还是猫,或者是不是车牌,于是我就可以把最后一层softmax从一个40961000的分类器变成一个40962的分类器,这个strategy在应用中非常好使,所以我们经常会先在imagenet上pretrain一个网络,因为我们知道imagenet上training的大概过程会怎么样。

12.3.4 Caffe架构是怎样的

Caffe的架构与其它的深度学习框架稍微不同,它没有根据算法实现过程的方式来进行编码,而是以系统级的抽象作为整体架构,逐层的封装实现细节,使得上层的架构变得很清晰。Caffe的整体架构如下:

1. SyncedMem

这个类的主要功能是封装CPU和GPU的数据交互操作。一般来说,数据的流动形式都是:硬盘->CPU内存->GPU内存->CPU内存->(硬盘),所以在写代码的过程中经常会写CPU/GPU之间数据传输的代码,同时还要维护CPU和GPU两个处理端的内存指针。这些事情处理起来不会很难,但是会很繁琐。因此SyncedMem的出现就是把CPU/GPU的数据传输操作封装起来,只需要调用简单的接口就可以获得两个处理端同步后的数据。

2. Blob

Blob是用于存储数据的对象,在Caffe中各种数据(图像输入、模型参数)都是以Blob的形式在网络中传输的,Blob提供统一的存储操作接口,可用来保存训练数据、模型参数等,同时Blob还能在CPU和GPU之间进行同步以支持CPU/GPU的混合运算。

这个类做了两个封装:一个是操作数据的封装,使用Blob可以操纵高维的数据,快速访问其中的数据,变换数据的维度等;另一个是对原始数据和更新量的封装,每一个Blob中都有data和diff两个数据指针,data用于存储原始数据,diff 用于存储反向传播(Backpropagation)的梯度更新值。Blob使用了SyncedMem,这样便于访问不同的处理端。Blob基本实现了整个Caffe数据结构部分的封装,在Net类中可以看到所有的前后向数据和参数都用Blob来表示就足够了。数据的抽象到这个就可以了,接下来作层级的抽象。神经网络的前后向计算可以做到层与层之间完全独立,只要每个层按照一定的接口规则实现,就可以确保整个网络的正确性。

3. Layer

Layer是网络Net的基本单元,也是Caffe中能在外部进行调整的最小网络结构单元,每个Layer都有输入Blob和输出Blob。Layer(层)是Caffe中最庞大最繁杂的模块,它是神经网络的基本计算单元。由于Caffe强调模块化设计,因此只允许每个layer完成一类特定的计算,例如convolution操作、pooling、非线性变换、内积运算,以及数据加载、归一化和损失计算等。Caffe中layer的种类有很多,具体的种类及功能请看官方文档。在创建一个Caffe模型的时候,也是以Layer为基础进行的。Layer是一个父类,它的下面还有各种实现特定功能的子类,例如data_layer,conv_layer,loss_layer等。Layer是通过LayFactory来创建的。

4. Net

Net是一个完整的深度网络,包含输入层、隐藏层、输出层,在Caffe中一般是一个卷积神经网络(Convolution Neural Networ,CNN)。通过定义不同类型的Layer,并用Blob将不同的Layer连接起来,就能产生一个Net。Net将数据Blob和层Layer组合起来做进一步的封装,对外提供了初始化和前后传播的接口,使得整体看上去和一个层的功能类似,但内部的组合可以是多种多样的。值得一提的是,每一层的输入输出数据统一保存在Net中,同时每个层内的参数指针也保存在Net中,不同的层可以通过WeightShare共享相同的参数,因此可以通过配置来实现多个神经网络层之间共享参数的功能。一个Net由多个Layer组成。一个典型的网络从data layer(从磁盘中载入数据)出发到loss layer结束。

5. Solver

有了Net就可以进行神经网络的前后向传播计算了,但是还缺少神经网络的训练和预测功能,Solver类进一步封装了训练和预测相关的一些功能。它还提供了两个接口:一个是更新参数的接口,继承Solver可以实现不同的参数更新方法,如Momentum,Nesterov,Adagrad等,因此可以使用不同的优化算法。另一个接口是训练过程中每一轮特定状态下的可注入的一些回调函数,在代码中这个回调点的直接使用者就是多GPU训练算法。Solver定义了针对Net网络模型的求解方法,记录网络的训练过程,保存网络模型参数,中断并恢复网络的训练过程。自定义Solver能够实现不同的神经网络求解方式。阅读Solver的代码可以了解网络的求解优化过程。Solver是一个父类,它下面还有实现不同优化方法的子类,例如sgd_solver,adagrad_sovler等,Solver是通过SolverFactory来创建的。

6. Proto

caffe.proto位于…/src/caffe/proto目录下,在这个文件夹下还有一个.pb.cc和一个.pb.h文件,这两个文件都是由caffe.proto编译而来的。 在caffe.proto中定义了很多结构化数据,包括: BlobProto、Datum、FillerParameter、NetParameter、SolverParameter、SolverState、LayerParameter、ConcatParameter、ConvolutionParameter、DataParameter、DropoutParameter、HDF5DataParameter、HDF5OutputParameter、ImageDataParameter、InfogainLossParameter、InnerProductParameter、LRNParameter、MemoryDataParameter、PoolingParameter、PowerParameter、WindowDataParameter、V0LayerParameter。

7. IO

除了上面的东西之外,还需要输入数据和参数。DataReader和DataTransformer帮助准备输入数据,Filler对参数进行初始化,一些Snapshot方法可以对模型进行持久化。

0 人点赞