caffe 框架梳理(待续)

本文详细介绍了Caffe框架,包括其起源、优点与局限性、目录结构、核心代码和关键组件。Caffe以其在图像处理领域的专长和高效性能而知名,但也存在灵活性不足的问题。文章深入探讨了Blob数据结构、Layer、Net的组成,以及各种层如Data、Convolution、Pooling、Neuron、Loss的功能和参数配置。此外,还讲解了优化方法如SGD、Adadelta等,并介绍了数据预处理、可视化和训练技巧。
摘要由CSDN通过智能技术生成

本文更多资料来源于罗韵北京深度学习资料和Ian Goodfellow的书籍《Deep Learning》
链接: http://pan.baidu.com/s/1jIRJ6mU
提取密码:xehi

caffe:全称Convolutional Architecture for Fast Feature Embedding,是一个计算CNN 相关算法的框架,用C++和Python实现的。

Caffe的优点与局限性

优点:
• 1. 第一个主流的工业级深度学习工具。
• 2. 专精于图像处理
• 局限性:
• 1. 它有很多扩展,但是由于一些遗留的架构问题,不够灵活且对递归网络和语言建模的支持很差。
• 2. 基于层的网络结构,其扩展性不好,对于新增加的层,需要
自己实现(forward, backward and gradient update)

Caffe目录结构

• data/ 用于存放下载的训练数据
• docs/ 帮助文档
• examples/ 代码样例
• matlab/ MATLAB接文件
• python/ PYTHON接文件
• models/ 一些配置好的模型参数
• scripts/ 一些文档和数据会用到的脚本核心代码
• tools/ 保存的源码是用于生成二进制处理程序的,caffe在训练时实际是直接调用这些二进制文件
• include/ Caffe的实现代码的头文件
• src/ 实现Caffe的源文件

src/ 文件结构

gtest/ google test 一个用于测试的库,你make runtest时看见的很多绿⾊色RUN OK就是它,这个与caffe的学习无关,不过是个有用的库

caffe/ 关键代码

• test/ 用gtest测试caffe的代码
• util/ 数据转换时用的一些代码。caffe速度快,很大程度得益于内存设计上的优化(blob数据结构采用proto)和对卷积的优化(部分与im2col相
关)
• proto/ 即所谓的“Protobuf”,全称“Google Protocol Buffer”,是一种数据存储格式,帮助caffe提速
• layers/ 深度神经网络中的基本结构就是一层层互不相同的网络了,这个
文件夹下的源文件以及目前位置“src/caffe”中包含所有.cpp文件就是caffe的核心目录下的核心代码了。

Caffe核心代码

• blob[.cpp .h] 基本的数据结构Blob类
• common[.cpp .h] 定义Caffe类
• internal_thread[.cpp .h] 使用boost::thread线程库
• net[.cpp .h] 网络结构类Net
• solver[.cpp .h] 优化方法类Solver
• data_transformer[.cpp .h] 输入数据的基本操作类DataTransformer
• syncedmem[.cpp .h] 分配内存和释放内存类CaffeMallocHost,用于同步GPU,CPU数据
• layer[.cpp .h] 层类Layer
• layers/ 此文件夹下面的代码全部至少继承了类Layer, 从layer_factory中注册继承

1. Caffe三级结构(Blobs,Layers,Nets)

• Blob:用于数据的保存、交换和操作,Caffe基础存储结构
• Layer:用于模型和计算的基础
• Net:整合连接Layers

1.1 Blobs结构

• 在内存中表示4维数组,在caffe/blob.hpp中,维度包括
(width_,height_,channels_,num_)
• num_用于存储数据或权值(data)和权值增量(diff)

• Blob 在caffe源码 blob.hpp中是一个模板类。
• protected 的成员变量有:data_ , diff_ , shape_ , count_ , capacity_ ,其中data_ 和diff_ 是共享SyncedMemory 类(在syncedmem的源码中定义)的智能指针,shape_是int型的vector,count_ 和capacity_ 是整型变量。
• 其成员函数主要有:Reshape 、ReshapeLike、SharedData、 Updata 等等
• blob.hpp 包含了caffe.pb.h ,说明caffe protobuf 会向blob 传递参数。

“caffe/proto/caffe.pb.h”
• caffe.pb.h是google protocol buffer根据caffe.proto自动生成的,可以到src/caffe/proto/caffe.proto里看下caffe里面用到的各个数据的定义,比如BlobProto,Datum,NetParameter等。使用这个protocol buffer看起来确实方便,一方面可以用文本文件定义结构化的数据类型,另一方面可以生成查询效率更高、占空间更小的二进制文件。

“caffe/common.hpp”
• 主要singleton化Caffe类,并封装了boost和CUDA随机数生成的函数,提供了统一的接口。

“caffe/syncedmem.hpp”
• 定义了以下的接⼝口:
• inline void CaffeMallocHost(void** ptr, size_t size)
• inline void CaffeFreeHost(void* ptr)
• 主要是分配内存和释放内存的。而class SyncedMemory定义了内存分配管理和CPU与GPU之间同步的函数。

“caffe/util/math_functions.hpp”
• 封装了很多cblas矩阵运算

caffe.proto里面BlobProto的定义

message BlobProto {
  optional BlobShape shape = 7;
  repeated float data = 5 [packed = true];
  repeated float diff = 6 [packed = true];
  repeated double double_data = 8 [packed = true];
  repeated double double_diff = 9 [packed = true];

  // 4D dimensions -- deprecated.  Use "shape" instead.
  optional int32 num = 1 [default = 0];
  optional int32 channels = 2 [default = 0];
  optional int32 height = 3 [default = 0];
  optional int32 width = 4 [default = 0];
}

• 对于BlobProto,可以看到定义了四个optional的int32类型的名字(name)num、channels、height和width,optional意味着Blob可以有一个或者没有这个参数,每个名字(name)后面都有一个数字,这个数字是其名字的一个标签。这个数字就是用来在生成的二进制文件中搜索查询的标签。关于这个数字,115会花费1byte的编码空间,162047花费2byte。所以⼀一般建议把那些频繁使用的名字的标签设为115之间的值。而后面的repeated意味着float类型的data和diff可以重复任意次,而加上[packed = true]是为了更高效的编码。
• 主要数据有两个data和diff,用num、channels、height和width这四个维度来确定数据的具体位置,做一些数据查询和Blob reshape的操作。

Blobs封装了运行时的数据信息,提供了CPU和GPU的同步。从数学上来说, Blob就是一个N维数组。它是caffe中的数据操作基本单位,就像matlab中以矩阵为基本操作对象一样。只是矩阵是二维的,而Blob是N维的。N可以是2,3,4等等。
对于图片数据来说,Blob可以表示为(N*C*H*W)这样一个4D数组。其中N表示图片的数量,C表示图片的通道数,H和W分别表示图片的高度和宽度。
当然,除了图片数据,Blob也可以用于非图片数据。比如传统的多层感知机,就是比较简单的全连接网络,用2D的Blob,调用innerProduct层来计算就可以了。

在模型中设定的参数,也是用Blob来表示和运算。它的维度会根据参数的类型不同而不同。比如:在一个卷积层中,输入一张3通道图片,有96个卷积核,每个核大小为11*11,因此这个Blob是96*3*11*11. 而在一个全连接层中,假设输入1024通道图片,输出1000个数据,则Blob为1000*1024。


1.2 Layer的五种类型

• Layer
• 所有的Pooling,Convolve,apply nonlinearities等操作都在这里实现。在Layer中input data用bottom表示,output data用top表示。每一层定义了三种操作setup(Layer初始化), forward(正向传导,根据input计算output), backward(反向传导计算,根据output计算input的梯度)。forward和backward有GPU和CPU两个版本的实现。


层是网络模型的组成要素和计算的基本单位。层的类型比较多,如Data,Convolution,Pooling,ReLU,Softmax-loss,Accuracy等,一个层的定义大至如下图:
这里写图片描述

从bottom进行数据的输入 ,计算后,通过top进行输出。图中的黄色多边形表示输入输出的数据,蓝色矩形表示层。

每一种类型的层都定义了三种关键的计算:setup,forward and backword

setup: 层的建立和初始化,以及在整个模型中的连接初始化。

forward: 从bottom得到输入数据,进行计算,并将计算结果送到top,进行输出。

backward: 从层的输出端top得到数据的梯度,计算当前层的梯度,并将计算结果送到bottom,向前传递。

正向传播的是数据,反向传播的是误差损失和梯度。


• 5种衍生Layers:

• data_layer


layer {
  name: "cifar"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    mean_file: "examples/cifar10/mean.binaryproto"
  }
  data_param {
    source: "examples/cifar10/cifar10_train_lmdb"
    batch_size: 100
    backend: LMDB
  }
}
name: 表示该层的名称,可随意取

type: 层类型,如果是Data,表示数据来源于LevelDB或LMDB。根据数据的来源不同,数据层的类型也不同。一般都是采 用的LevelDB或LMDB数据,因此层类型设置为Data。

top或bottom: 每一层用bottom来输入数据,用top来输出数据。如果只有top没有bottom,则此层只有输出,没有输入。反之亦然。如果有多个 top或多个bottom,表示有多个blobs数据的输入和输出。

data 与 label: 在数据层中,至少有一个命名为data的top。如果有第二个top,一般命名为label。 这种(data,label)配对是分类模型所必需的。

include: 一般训练的时候和测试的时候,模型的层是不一样的。该层(layer)是属于训练阶段的层,还是属于测试阶段的层,需要用include来指定。如果没有include参数,则表示该层既在训练模型中,又在测试模型中。

Transformations: 数据的预处理,可以将数据变换到定义的范围内。如设置scale为0.00390625,实际上就是1/255, 即将输入数据由0-255归一化到0-1之间

mirror # 1表示开启镜像,0表示关闭,也可用ture和false来表示
crop_size: 227剪裁一个 227*227的图块,在训练阶段随机剪裁,在测试阶段从中间裁剪

data_layer主要包含与数据有关的文件。在官方文档中指出data是caffe数据的入口是网络的最低层,并且支持多种格式,在这之中又有5种LayerType

• DATA 用于LevelDB或LMDB数据格式的输入的类型,输入参数有source,batch_size, (rand_skip), (backend)。后两个是可选。

数据来自于数据库(如LevelDB和LMDB)
层类型(layer type):Data
必须设置的参数:
source: 包含数据库的目录名称,如examples/mnist/mnist_train_lmdb
batch_size: 每次处理的数据个数,如64
可选的参数:
rand_skip: 在开始的时候,路过某个数据的输入。通常对异步的SGD很有用。
backend: 选择是采用LevelDB还是LMDB, 默认是LevelDB.

• MEMORY_DATA 这种类型可以直接从内存读取数据使用时需要调用MemoryDataLayer::Reset,输入参数有batch_size, channels, height, width。
数据来自于内存层类型:MemoryData必须设置的参数:
batch_size:每一次处理的数据个数,比如2,channels:通道数
height:高度,width: 宽度
示例:

layer {
top: "data"      
top: "label"
name: "memory_data"   
type: "MemoryData"    
memory_data_param{
batch_size: 2
height: 100
width: 100
channels: 1
}
transform_param {
scale: 0.0078125
mean_file: "mean.proto"
mirror: false
}
}

• HDF5_DATA HDF5数据格式输入的类型,输入参数有source, batch_size。
• HDF5_OUTPUT HDF5数据格式输出的类型,输入参数有file_name。

数据来自于HDF5
层类型:HDF5Data
必须设置的参数:
source: 读取的文件名称
batch_size: 每一次处理的数据个数
示例:

layer {
name: "data"
type: "HDF5Data"
top: "data"
top: "label"
hdf5_data_param {
source: "examples/hdf5_classification/data/train.txt"
batch_size: 10
}
}

• IMAGE_DATA 图像格式数据输入的类型,输入参数有source, batch_size,(rand_skip), (shuffle), (new_height), (new_width)。

数据来自于图片
层类型:ImageData
必须设置的参数:
source: 一个文本文件的名字,每一行给定一个图片文件的名称和标签(label)
batch_size: 每一次处理的数据个数,即图片数
可选参数:
rand_skip: 在开始的时候,路过某个数据的输入。通常对异步的SGD很有用。
shuffle: 随机打乱顺序,默认值为false
new_height,new_width: 如果设置,则将图片进行resize
示例:

layer {
name: "data"
type: "ImageData"
top: "data"
top: "label"
transform_param {
mirror: false
crop_size: 227
mean_file: "data/ilsvrc12/imagenet_mean.binaryproto"
}
image_data_param {
source: "examples/_temp/file_list.txt"
batch_size: 50
new_height: 256
new_width: 256
}

• 其实还有两种WINDOW_DATA, DUMMY_DATA⽤用于测试和预留的接⼝口,不重要。

数据来源于Windows
层类型:WindowData
必须设置的参数:
source: 一个文本文件的名字
batch_size: 每一次处理的数据个数,即图片数
示例:

layer {
  name: "data"
  type: "WindowData"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    mirror: true
    crop_size: 227
    mean_file: "data/ilsvrc12/imagenet_mean.binaryproto"
  }
  window_data_param {
    source: "examples/finetune_pascal_detection/window_file_2007_trainval.txt"
    batch_size: 128
    fg_threshold: 0.5
    bg_threshold: 0.5
    fg_fraction: 0.25
    context_pad: 16
    crop_mode: "warp"
  }
}

• neuron_layer

同样是数据的操作层,neuron_layer实现里大量激活函数,主要是元素级别的操作,具有相同的bottom,top size。
• Caffe中实现了大量激活函数GPU和CPU的都有很多。它们的父类都是
NeuronLayer

• template <typename Dtype>
• class NeuronLayer : public Layer<Dtype>

1、Sigmoid

对每个输入数据,利用sigmoid函数执行操作。这种层设置比较简单,没有额外的参数。
层类型:Sigmoid

这里写图片描述

示例

layer {
  name: "encode1neuron"
  bottom: 
  • 5
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值