1. 官网介绍
1. Caffe
Caffe是一个以表达式、速度和模块化为核心的深度学习框架,由BLVC(Berkeley Vision and Learning Center)和社区贡献者开发。项目创建者是贾扬清。
2. Feature
- Expressive architecture
具有表现力的结构鼓励应用和创新。模型及优化是通过配置定义的,而不是使用硬编码的方式。可以在GPU和CPU之间无缝切换,可以用GPU训练,然后部署到集群或移动设备上。
- Extensible code
具有扩展性的代码促进了Caffe的积极发展。Caffe第一年fork超过一千次,有许多有意义的贡献和反馈。由于众多的贡献者,Caffe框架跟踪并实现了当前最新的代码和模型。
- Speed
快速性使Caffe适合研究实验和工业开发。Caffe在单个的NVIDIA K40 GPU上每天能处理6千万张图片。识别时速度为1ms/张,训练时速度为4ms/张,BLVC相信Caffe具有最快的卷积神经网络实现。
- Community
Caffe已经支持学术研究项目,启动原型,甚至支持大规模视觉、语音和多媒体的工业应用。
3. Document
- DIY Deep Learning for Vision with Caffe
一个介绍Caffe的PPT
- Tutorial Documentation
实践指导和框架参考
- Installation instructions
安装,已经在Ubuntu,Red Hat,OS X上测试过了。
- Model Zoo
模型规范及已经训练的模型
- API Documentation
API文档,通过代码中的注释生成的。
4. Demo
- ImageNet tutorial
在ImageNet上训练和测试CaffeNet
。
- LeNet MNIST Tutorial
Yann LeCun的手写字符识别,训练和测试。
- CIFAR-10 tutorial
CIFAR-10数据集上Caffe的训练与测试。
- Fine-tuning for style recognition
ImageNet上训练的CaffeNet在Flickr Style
数据集上的调优。
- Feature extraction with Caffe C++ code
用Caffe工具提取CaffeNet和AlexNet特征。
- CaffeNet C++ Classification example
用底层API进行图像的简单分类
- Web demo
运行在Flask web服务器上的图像分类Demo
- Siamese Network Tutorial
在MNIST数据集上训练和测试siamese网络。
5. NoteBook Demo
- Image Classification and Filter Visualization
通过预先训练的模型进行图像实时识别,对神经网络的每层特征和参数进行可视化,可以了解可视化的神经网络接口。
- Learning LeNet
使用Python定义、训练、测试经典的LeNet。
- Fine-tuning for Style Recognition
在新数据集上对ImageNet上训练的CaffeNet进行调优。
- Off-the-shelf SGD for classification
使用Caffe作为一般的SGD优化器在非图像的HDF5数据上训练逻辑回归。
- Multilabel Classification with Python Data Layer
使用Python数据层在PASCAL VOC上进行多标签分类。
- Editing model parameters
怎样修改神经网络,手动改变模型参数来进行定制化使用。
- R-CNN detection
在Python中使用预先训练的模型作为检测器来进行目标检测。
- Siamese network embedding
提取特征、绘制Siamese网络嵌入。
6. Philosophy
- Expression
模型和优化都是通过纯文本模式定义的而不是通过代码的方式。
- Speed
对于研究和工业而言,在最新的模型和大规模数据上具有同样的速度是关键。
- Modularity
新任务及设置要求灵活性和可扩展性
- Openness
科学和应用进展需要通用的代码、参考模型和再现性。
- Community
学术研究、启动原型和工业应用通过在BSD-2项目中的联合讨论和开发实现所有共享。
7. Tour
- Net,Lays and Blobs
Caffe模型的结构组成
- Forward/Backward
分层结构模型的基本计算
- Loss
通过损失函数定义要学习的任务
- Solver
求解程序协调模型优化
- Layer Catalogue
这一层是建模和计算的基本单元,Caffe的目录包含最新模型的层
- Interfaces
命令行,Python,MATLAB
- Data
怎样将模型输入变为Caffe能处理的数据
- Caffeinated Convolution
Caffe怎样计算卷积
2. 普通介绍
1. Caffe介绍
在深度学习领域,Caffe框架是人们无法绕过的一座山。Caffe是一个用C++编写的深度学习框架,作者是UC Berkeley博士贾扬清,Caffe。由于Caffe清晰、高效,因此在深度学习中被广泛使用,用户逐渐地也形成了一个开放的社区,一些重要的研究成果(主要是各种模型)被引入到了Caffe中,例如著名的AlexNet。
Caffe无论在结构、性能上,还是在代码质量上,都是一款非常出色的开源框架。它将深度学习的每一个细节都原原本本地展现出来,大大降低了人们学习、研究和开发的难度。
Caffe是纯粹的C++/CUDA架构,支持命令行、Python和MATLAB接口。Caffe的清晰性表现在网络结构与参数都独立于代码,用户只要以普通文本(但需遵循一定的简单格式)就可以定义好自己的神经网络,并按自己的需要进行调整。而高效性则体现在对CUDA的支持,GPU 运算能极大地提高图像处理的速度,同时Caffe提供了在CPU模式和GPU模式之间的无缝切换。
2. Caffe特点
-
上手快:模型与相应优化都是以文本形式而非代码形式给出。Caffe给出了模型的定义、最优化设置以及预训练的权重,方便立即上手。
-
速度快:能够运行最棒的模型与海量的数据。Caffe与cuDNN结合使用,测试AlexNet模型,在K40上处理每张图片只需要1.17ms.
-
模块化:方便扩展到新的任务和设置上。可以使用Caffe提供的各层类型来定义自己的模型。
-
开放性:公开的代码和参考模型用于再现。
-
社区好:可以通过开源社区和Github参与讨论和开发。
参考资料:
-
Caffe官网
-
http://www.zmonster.me/2015/07/21/caffe-base-usage.html
-
http://www.cnblogs.com/zdz8207/p/DeepLearning-Caffe.html
Caffe是一个开源的深度学习框架,其实现依赖于许多其它的库,下面将分别介绍Caffe所需的依赖库。
1. OpenCV
OpenCV的全称是Open Source Computer Vision Library,是一个跨平台的计算机视觉库。OpenCV是由英特尔公司发起并参与开发,以BSD许可证授权发行,可以在商业和研究领域中免费使用。OpenCV可用于开发实时的图像处理、计算机视觉以及模式识别程序。
2. Boost
Boost C++库是一个经过千锤百炼、可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的发动机之一。 Boost库由C++标准委员会库工作组成员发起,在C++社区中影响甚大。 Boost库为我们带来了最新、最酷、最实用的技术,是不折不扣的“准”标准库。Boost作为一个准标准库,相当于STL的延续和扩充,它的设计理念和STL比较接近,都是利用泛型让复用达到最大化。不过相比于STL,Boost更加实用。STL集中在算法部分,而Boost包含了不少工具类,可以完成比较具体的工作。Boost主要包含以下几个大类:字符串及文本处理、容器、迭代器(Iterator)、算法、函数对象和高阶编程、泛型编程、模板元编程、预处理元编程、并发编程、数学相关、纠错和测试、数据结构、输入/输出、跨语言支持、内存相关、语法分析、杂项。
3. CUDA
CUDA(Compute Unified Device Architecture,统一计算架构)是由NVIDIA所推出的一种集成技术,是NVIDIA推出的运算平台。CUDA是由NVIDIA推出的通用并行计算架构,该架构使GPU能够解决复杂的计算问题。 它包含了CUDA指令集架构(ISA)以及GPU内部的并行计算引擎。从CUDA体系结构的组成来说,包含了三个部分:开发库、运行期环境和驱动。开发库是基于CUDA技术所提供的应用开发库。运行期环境提供了应用开发接口和运行期组件,包括基本数据类型的定义和各类计算、类型转换、内存管理、设备访问和执行调度等函数。驱动部分基本上可以理解为是CUDA-enable的GPU的设备抽象层,提供硬件设备的抽象访问接口。CUDA提供运行期环境也是通过这一层来实现各种功能的。
4. BLAS
BLAS(Basic Linear Algebra Subprograms,基础线性代数程序集)是一个应用程序接口(API)标准,用以规范发布基础线性代数操作的数值库(如矢量或矩阵乘法)。在高性能计算领域,BLAS被广泛使用。Caffe推荐的BLAS(Basic Linear Algebra Subprograms)有三个选择ATLAS,Intel MKL,OpenBLAS。其中ATLAS是caffe是默认选择的,其开源免费,如果没有安装CUDA的不太推荐使用,因为对CPU多线程的支持不太好;Intel MKL是商业库要收费,学生可申请试用,贾扬清安装的是MKL,估计效果应该是最好的;OpenBLAS开源免费,支持CPU多线程。
5. LevelDB
LevelDB是一个由Google公司所研发的键/值对(Key/Value Pair)嵌入式数据库管理系统编程库,以开源的BSD许可证发布,是Caffe支持的数据格式之一。LevelDb有如下一些特点:
-
首先,LevelDb是一个持久化存储的KV系统,和Redis这种内存型的KV系统不同,LevelDb不会像Redis一样狂吃内存,而是将大部分数据存储到磁盘上。
-
其次,LevleDb在存储数据时,是根据记录的key值有序存储的,就是说相邻的key值在存储文件中是依次顺序存储的,而应用可以自定义key大小比较函数,LevleDb会按照用户定义的比较函数依序存储这些记录。
-
再次,像大多数KV系统一样,LevelDb的操作接口很简单,基本操作包括写记录,读记录以及删除记录。也支持针对多条操作的原子批量操作。
-
另外,LevelDb支持数据快照(snapshot)功能,使得读取操作不受写操作影响,可以在读操作过程中始终看到一致的数据。
6. LMDB
LMDB是一种小型的键值对数据库,具有一些非常优异的特性:
-
有序的映射接口(键一直是按字典排序的)
-
读写事务:读不会锁住写,写也不会锁住读
-
读取数据代价很低
-
内存映射,允许零拷贝查找和迭代
-
维护不需要外部进程或后台线程
虽然LMDB的内存消耗是LevelDB的1.1倍,但是LMDB的速度比LevelDB快10%至15%,更重要的是LMDB允许多种训练模型同时读取同一组数据集。因此LMDB取代了LevelDB成为Caffe默认的数据集生成格式。
7. GLog
Google的Glog是一个应用程序的日志库。它提供基于C++风格的流的日志API,以及各种辅助的宏。打印日志只需以流的形式传给 LOG(level) 。
8. GFlags
GFlags是Google的一个开源的处理命令行参数的库,使用C++开发,具备Python接口,可以替代getopt。GFlags使用起来比getopt方便,但是不支持参数的简写。
9. Protobuff
Google Protocol Buffer(简称Protobuf) 是Google公司内部的混合语言数据标准,它提供了一种灵活、高效、自动序列化结构数据的机制,但是比XML更小、更快、更简单。仅需要自定义一次你所需的数据格式,然后用户就可以使用Protobuf编译器自动生成各种语言的源码,方便的读写用户自定义的格式化的数据。与语言无关,与平台无关,还可以在不破坏原数据格式的基础上,依据老的数据格式,更新现有的数据格式。它们用于RPC 系统和持续数据存储系统。Protobuf是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或RPC数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了C++、Java、Python三种语言的API。
10. HDF5
HDF(英语:Hierarchical Data Format)指一种为存储和处理大容量科学数据设计的文件格式及相应库文件。HDF最早由NCSA开发,目前在非盈利组织HDF小组维护下继续发展。当前流行的版本是HDF5。
HDF5文件包含两种基本数据对象:
-
群组(group):类似文件夹,可以包含多个数据集或下级群组。
-
数据集(dataset):数据内容,可以是多维数组,也可以是更复杂的数据类型。
群组和数据集都支持元数据,用户可以自定义其属性,提供附加信息。HDF现在被众多商业与非商业平台支持,包括Java,MATLAB/Scilab,Octave,IDL,Python和R。
11. Snappy
Snappy(以前称Zippy)是Google基于LZ77的思路用C++语言编写的快速数据压缩与解压程序库,并在2011年开源。它的目标并非最大压缩率或与其他压缩程序库的兼容性,而是非常高的速度和合理的压缩率。LevelDB需要Snappy的支持。
Caffe的设计
根据贾扬清的分享整理
Caffe遵循了神经网络的一个假设:所有的计算都是以layer形式表示的,layer的作用就是根据输入数据,输出一些计算以后的结果。以卷积为例,就是输入一幅图像,然后与这一层的参数(filter)进行卷积运算,然后输出卷积的结果。每一个layer需要进行两种运算:1.forward,从输入计算输出;2.backward根据上面的梯度(gradient)来计算相对于输入的梯度。在每个layer都实现了这两个函数以后,我们可以将很多层连接成一个网络,这个网络做的事情就是输入我们的数据(图像或者语音或者whatever),然后来计算我们需要的输出(比如说识别的label)。在训练时,我们可以根据已有的label来计算loss和gradient,然后用gradient来update网络的参数。这个就是Caffe的一个基本流程!
Caffe主要结构
Caffe代码本身非常模块化,主要由4部分组成Blob,Layer,Net和Solver。
- Blob
Blob主要用来表示网络中的数据,包括训练数据,网络各层自身的参数,网络之间传递的数据都是通过Blob来实现的,同时Blob数据也支持在CPU与GPU上存储,能够在两者之间做同步。
- Layer
Layer是对神经网络中各种层的一个抽象,包括卷积层和下采样层,还有全连接层和各种激活函数层等等。同时每种Layer都实现了前向传播和反向传播,并通过Blob来传递数据。
- Net
Net是对整个神经网络的表示,由各种Layer前后连接组合而成,也是我们要构建的网络模型。
- Solver
Solver定义了针对Net网络模型的求解方法,记录神经网络的训练过程,保存神经网络模型参数,中断并恢复网络的训练过程。自定义Solver能够实现不同的神经网络求解方式。
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方法可以对模型进行持久化。
参考资料:
- https://zhuanlan.zhihu.com/p/21796890