导语
在目前学术界中,使用Caffe来做计算机视觉方面的,还是比较主流的。我一开始对Caffe的了解还是只停留下跑过caffe的代码,用caffe进行过训练,但是自己对其各个依赖包和原理还不是特比了解,主要就参考赵永科的《深度学习:21天实战caffe》这本书来了解一下caffe的原理,并整理下笔记。主要看了他介绍caffe各个依赖包和架构的部分,书本大概有一半的内容贴的是caffe的源码以及作者的注释,整体来说只能说是比较适合入门者,适合刚刚接触caffe框架的人快速了解整体的框架。
想要了解Caffe入门使用,如何使用caffe在猫狗分类的数据集上进行训练可以参考我的GitHub:caffe-beginner
PS: 此处未包含Caffe依赖包安装,默认服务器已经安装,详细可以参考Caffe官网 查看更多安装细节。
深度学习框架选择
- Caffe
- Caffe2
- Tensorflow( wrapper : Keras)
- torch( in lua)
- pytorch
我接触过Caffe,Tensorflow和Keras,学习keras时觉得很简洁很好写,但是后来发现它存在不足的是包装过度,可能并不是特别适合做research,存在效率问题。而Tensorflow虽然有着强大的社区支持,但是对图的定义、debug自己在写的过程中也感觉是比较复杂的。
在接下来做research的过程中,会继续深入学习一下caffe,了解caffe2(拥有更好的效率和速度)。以及接触学习facebook在2017年年初刚发布的pytorch,使用的是python,更加像是过程式编程,可以自动完成图的构建。主要应该是会关注caffe和pytorch两个框架。
更多关于框架的选择可以参考知乎上面的讨论Keras,Theano,pytorch,caffe2 哪个更好一些,应该怎么尝试学习?
Caffe
介绍
Caffe,全称Convolutional Architecture for Fast Feature Embedding,是一个计算CNN相关算法的框架,由Yangqing Jia老师编写,Caffe主要是用C++实现的,并提供了C++、Python、Matlab的接口。
- Caffe 主页:http://caffe.berkeleyvision.org/
- Github:https://github.com/BVLC/caffe
依赖包
ProtoBuffer
ProtoBUffer是由Google开发的一种可以实现内存与非易失存储介质(如硬盘文件)交换的协议接口。Caffe源码中大量使用ProtoBuffer作为权值和模型参数的载体。如solver.prototxt
, deploy.prototxt
, train.prototxt
. Caffe训练时会读取这些文件,获取特定字段数值,并据此设置内存中模型训练时的超参数变量值,通过ProtoBUffer自动完成复杂的接口实现。相比于结构体能够更方便的实现序列化和反序列化,可以做到接口标准化。
Boost
Caffe中使用了Boost的智能指针,避免共享指针的时候造成内存泄漏或多次释放。pycaffe使用Boost Python实现了C/c++和Python语言的连接。
GFLAGS
在Caffe中主要起倒命令行参数解析的作用,具体使用参考tools/caffe.cpp
GLOG
记录日志
BLAS
CPU端的矩阵、向量计算,GPU端的计算使用cuBLAS
HDF5
Caffe训练模型可以选择保存为HDF5格式或者ProtoBuffer格式。HDF( Hierachical Data File )是美国国家高级计算应用中心(NCSA)为了满足各种领域研究需求而研制的一种高效存储和分发科学数据的新型数据格式。
Opencv
开源计算机视觉库
LMDB和LEVELDB
LMDB( Lightning Memory-Mapped Database Manager ),在Caffe中主要提供数据管理,将原始数据(JPEG图片、二进制数据)转换为统一的Key-Value存储,便于Caffe的DataLayer获取这些数据。LEVELDB是caffe早期版本所使用的,由Goggle开发,现多使用LMDB代替。
Snappy
用来压缩和解压的C++库
Layer
卷积层在输出特征图维度实现了权值共享,降低了参数量。卷积的局部连接特性(相比全连接)也大幅减少了参数量。
计算加速优化重点放在卷积层,参数优化和权值剪裁重点放在全连接层。
数据结构
Blob
Caffe使用称为Blob的4维数组用于存储和交换数据。Blob提供了统一的存储器接口,持有一批图像或其他数据、权值、权值更新值。类似Torch/Theano/TensorFlow中的Tensor。使用BlobProto可以方便的实现序列化和反序列化。
有两种类型的Blob,以param开头的权值Blob和以blob开头的Layer输入/输出Blob。权值Blob会随着学习过程而更新,归属于“模型”。Layer输入/输出Blob则只会随网络输入变化,归属于“数据”。深度学习的目的急速不断从“数据”中学习,存储到“模型”中,应用于后来的“数据”。
Layer
Layer是Caffe的基本计算单元,至少有一个输入Blob( Bottom Blob )和一个输出Blob( Top Blob ),部分Layer带有权值( Weight )和偏置项( Bias ),有两个运算方向:前向传播和反向传播,其中前向传播计算会对输入Blob进行处理,得到输出Blob,而反向传播计算则会对输出Blob的diff进行处理,得到输出Blob的diff。
Net
Net在Caffe中代表一个完成的CNN模型,它包含若干Layer实例。
Net是一张图纸,对应描述文件为*.prototxt,Net既包含Layer对象又包含Blob对象,其中Blob对象用于存放每个Layer输入/输出中间结果,Layer则根据Net描述对指定的输入Blob进行某些计算处理(卷积、下采样、全连接、非线性变换、计算代价函数等),输出结果放到指定的输出Blob中。输入Blob和输出Blob可能为同一个。所有的Layer的Blob对象都用名字区分,同名的Blob表示同一个Blob对象,同名的Layer表示同一个Layer对象。而Blob和Layer同名则不代表它们有任何直接关系。
I/O 模块
数据读取层
Caffe数据读取层(DataLayer)是Layer的派生类。除了读取LMDB、LEVELDB之外,也可以从原始图像直接读取(ImageDataLayer)。
数据变换器
Caffe的数据变换器(DataTransformer)主要提供了对原始输入图像的预处理方法,包括随机切块、随机镜像、幅度缩放、去均值、灰度/色度变换等。
模型
参数
- 可学习参数(Learnable Parameter):又称可训练参数、神经网络权系数、权重,其数值由模型初始化参数、误差反向传播过程控制,一般不可人工干预。在Caffe中,在内存中使用Blob对象保持,必要时以二进制ProtoBuffer文件(.caffemodel)形态序列化并存储于磁盘上,以便进一步fine-tune、共享、性能评估(benchmark)
- 结构参数(Archetecture Parameter),包括卷积层/全连接层/下采样层数目、卷积核数目、卷积核大小等描述网络结构的参数,一旦设定好,在网络训练阶段不能更改:值得注意的是,训练阶段网络结构参数和预测阶段结构参数可能不同。在Caffe中,使用ProtoBuffer文本格式(*.prototxt)描述,网络初始化时通过该描述文件构建Net对象、Layer对象形成有向无环图结构,在Layer与Layer之间、Net输入源和输出均为持有数据和中间结果的Blob对象。
- 训练超参数(Hyper-Parameter),用来控制网络训练收敛的参数,训练阶段可以自动或手动调节以获得更好的效果,预测阶段不需要该参数。在Caffe中同样使用ProtoBuffer文本格式(.prototxt)描述,训练阶段利用该描述文件构建求解器(Solver)对象(Sovler.prototxt)。该对象按照一定规则在*训练**网络时自动调节这些超参数,如学习速率,优化器。
前向传播
传统的BP算法在训练CNN的时候包括了两个阶段:前向传播计算(Forward)和反向传播计算(Backward)。
通常只有在训练阶段才需要反向传播计算,预测任务就只需要前向传播。
反向传播
CNN进行前向传播阶段,依次调用每个Layer和Forward函数,得到逐层的输出,最后一层与目标函数比较得到损失函数,计算误差更新值,通过反向传播路径逐层达到第一层,所有权值层在反向传播结束后一起更新。
损失函数
损失层(Loss Layer)是CNN训练阶段的终点,接受两个Blob作为输入,其中一个为CNN的预测值,另一个是真实标签。
工具
特征提取
build/tools/extract_features.bin
实现了特征提取功能,该程序需要一个训练好的网络和一个数据输入层,运行后可以得到相应数据通过网络某个中间层产生的特征图并保存到磁盘。
计算图像均值
tools/compute_image_mean.cpp
GPU 加速
GPU:(Graphics Processing Unit)
CUDA
CUDA(Compute Unified Device Architecture)是NVIDIA在2006年推出的一套针对异构计算资源(Intel CPU + NVIDIA GPU)下的大规模并行计算的架构,包括编译器(nvcc)、开发工具、运行时库和驱动等模块。
CUDA语法和C语言高度像素,大大降低了GPU编程的门槛。使用的时候直接利用CUDA提供的cuBLAS软件库进行运算即可。
cuDNN
NVIDIA从2014年开始推出了面向深度学习的专用加速库cuDNN,支持常见的深度学习计算模型(卷积、下采样、非线性、Softmax)
参考
- Caffe 贾扬清
- 《深度学习:21天实战caffe》 赵永科