Caffe学习:Blobs, Layers, and Nets

目录:


原文

  • 深度神经网络(Deep networks)是由许多相互关联的Layer组成的。Caffe定义了一个layer-by-layer的network。底层是data,顶层是loss。运算数据在network中进行forward and backward passes(正向迭代和反向迭代),为此Caffe定义了Blob,用来存储、传递、处理数据。Blob是Caffe的标准数据结构、统一的内存接口。Layer是Caffe模型、运算的基础。network是Layer的集合。Blob描述了数据是如何在Layer和Net中存储和传递的。

  • Solving(求解方法)被单独定义,以解耦模型和配置。


Blob storage and communication

  • Blob是对数据的包装,用来存储、传递数据,并且能够实现CPU和GPU之间 的无缝切换。其实,Blob是一个N维数组。Blob提供了一个统一的内存接口用于存储数据,比如图片数据,模型参数,以及中间数据。Blob隐藏了CPU和GPU混合操作的细节,实现了CPU主机和GPU设备之间的无缝切换。

  • 常用的用于存储图片数据的Bolb的维度是: number N x channel K x height H x width W,按行(而不是列)存储,所以(n, k, h, w) 是指第 ((n * K + k) * H + h) * W + w个值。

  • Number / N是每一次处理的数据大小,使用批处理能够实现更好的效果。

  • Channel / K是特征的维度,例如对于RGB图片而言,K=3。

  • 作为参数的Blob,维度根据所在的Layer而不同。例如,对于一个96滤波器,11×11维度,3输入的Convolution Layer,其Blob维度是96×3×11×11。对于一个1000channels输出,1024channels输入的Inner Product Layer,其Blob维度是1000×1024。

Implementation Details

  • 对于网络中的数据,我们在意的是values(值)和gradients(梯度),所以一个Blob单元在内存中存储了两块数据 => data和diff。前者是我们输入网络的数据,后者是网络计算得出的gradients(梯度)。

  • 数据可以存放在CPU或者GPU,所以有两种不同的方式去访问数据:the const way(值不变方式)、the mutable way(值改变的方式):

const Dtype* cpu_data() const;
Dtype* mutable_cpu_data();
(similarly for gpu and diff).
  • 这样设计的原因是Blob中使用一个SyncedMem类在CPU和GPU中同步数据,以隐藏底层细节,最小化数据传输损失。经验:如果不想改变数据,使用the const way(值不变方式),但是不要在自定义类中存储指针。当要得到指针时,调用方法去得到指针,此时SyncedMem类会确定是否需要复制数据(在CPU和GPU之间)。

  • 当使用GPU时,CPU将数据读取到Blob中,调起设备进行GPU运算,忽略底层的细节,实现高效运算。所有的Layer都有GPU实现,所以所有中间 data and gradients (数据及运算得出的梯度)都会保存在GPU中。

  • 下面是一个例子,用于确定何时Blob会复制数据:

// 假设刚开始数据存储在CPU中,我们定义了一个Blob
const Dtype* foo;
Dtype* bar;
foo = blob.gpu_data(); // 数据复制:cpu->gpu
foo = blob.cpu_data(); // 没有数据复制过程,因为数据都是最新的
bar = blob.mutable_gpu_data(); // 没有数据复制过程
// ... 一些中间操作 ...
bar = blob.mutable_gpu_data(); // 如果此时还是GPU模式,没有数据复制过程
foo = blob.cpu_data(); // 数据复制:gpu->cpu, 如果GPU更改过数据
foo = blob.gpu_data(); // 没有数据复制过程,因为数据都是最新的
bar = blob.mutable_cpu_data(); // 没有数据复制过程
bar = blob.mutable_gpu_data(); // 数据复制:cpu->gpu
bar = blob.mutable_cpu_data(); // 数据复制:gpu->cpu

Layer computation and connections

  • Layer是Caffe模型最重要的部分,也是进行运算的基本单元。Layer可以进行很多运算,如:convolve(卷积)、pool(聚合)、inner product(内积)、rectified-linear (非线性)、sigmoid(阶跃)以及其他elementwise transformations,normalize(标准化)、load data(数据导入)、compute losses(损失计算)。在layer catalogue查看Layer种类,包括了所有深度学习任务所涉及的最先进的类型。

这里写图片描述

  • Layer从bottom接受input,从top输出output。每一个Layer都定义了3种至关重要的运算:setup-初始化、forward-前向迭代、backward-反向迭代。

  • Setup:初始化Layer以及该Layer与其他Layer的连接

  • Forward:从bottom接受input,进行该Layer定义的计算后,从top输出output
  • Backward:从top接受output的gradient,计算出input的gradient,从bottom输出
  • 对于Forward和Backward都有两种实现:CPU和GPU方式。

  • 由于Caffe的高度模块化,自定义Layer是很简单的(不信)。只要定义好:setup-初始化、forward-前向迭代、backward-反向迭代这三个方法,就可以将该Layer加入net之中。


Net definition and operation

  • Caffe Net的所有Layer的output(前向迭代)实现要完成的任务,反向迭代计算loss的gradient以进行学习,优化参数。Caffe模型是端到端的学习引擎。

  • Net是由一系列Layer组合形成的网状图,a directed acyclic graph(一个有向无环图)。Caffe会板保存所有中间运算值以确保forward and backward passes(前向迭代和反向迭代)的正确性。典型的Net开始于一个data layer,用于接受数据输入,结束于一个loss layer,用于实现最终的任务,例如classification or reconstruction(分类与重建)。

  • Net被定义为一系列的Layer及其连接表示,in a plaintext modeling language(用一种明文建模语言表示)。一个简单的logistic regression classifier(逻辑回归分类器),如下图:

logreg

可以如下定义:

name: "LogReg"
layer {
  name: "mnist"
  type: "Data"
  top: "data"
  top: "label"
  data_param {
    source: "input_leveldb"
    batch_size: 64
  }
}
layer {
  name: "ip"
  type: "InnerProduct"
  bottom: "data"
  top: "ip"
  inner_product_param {
    num_output: 2
  }
}
layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "ip"
  bottom: "label"
  top: "loss"
}
  • Net::Init()是模型初始化函数,主要完成两件事:新建Blob和Layer对象以搭建整个网络图,调用Layer的SetUp()方法。同时会确认整个Net的结构是否正确,打印初始化日志:
I0902 22:52:17.931977 2079114000 net.cpp:39] Initializing net from parameters:
name: "LogReg"
[...model prototxt printout...]
# construct the network layer-by-layer
I0902 22:52:17.932152 2079114000 net.cpp:67] Creating Layer mnist
I0902 22:52:17.932165 2079114000 net.cpp:356] mnist -> data
I0902 22:52:17.932188 2079114000 net.cpp:356] mnist -> label
I0902 22:52:17.932200 2079114000 net.cpp:96] Setting up mnist
I0902 22:52:17.935807 2079114000 data_layer.cpp:135] Opening leveldb input_leveldb
I0902 22:52:17.937155 2079114000 data_layer.cpp:195] output data size: 64,1,28,28
I0902 22:52:17.938570 2079114000 net.cpp:103] Top shape: 64 1 28 28 (50176)
I0902 22:52:17.938593 2079114000 net.cpp:103] Top shape: 64 (64)
I0902 22:52:17.938611 2079114000 net.cpp:67] Creating Layer ip
I0902 22:52:17.938617 2079114000 net.cpp:394] ip <- data
I0902 22:52:17.939177 2079114000 net.cpp:356] ip -> ip
I0902 22:52:17.939196 2079114000 net.cpp:96] Setting up ip
I0902 22:52:17.940289 2079114000 net.cpp:103] Top shape: 64 2 (128)
I0902 22:52:17.941270 2079114000 net.cpp:67] Creating Layer loss
I0902 22:52:17.941305 2079114000 net.cpp:394] loss <- ip
I0902 22:52:17.941314 2079114000 net.cpp:394] loss <- label
I0902 22:52:17.941323 2079114000 net.cpp:356] loss -> loss
# set up the loss and configure the backward pass
I0902 22:52:17.941328 2079114000 net.cpp:96] Setting up loss
I0902 22:52:17.941328 2079114000 net.cpp:103] Top shape: (1)
I0902 22:52:17.941329 2079114000 net.cpp:109]     with loss weight 1
I0902 22:52:17.941779 2079114000 net.cpp:170] loss needs backward computation.
I0902 22:52:17.941787 2079114000 net.cpp:170] ip needs backward computation.
I0902 22:52:17.941794 2079114000 net.cpp:172] mnist does not need backward computation.
# determine outputs
I0902 22:52:17.941800 2079114000 net.cpp:208] This network produces output loss
# finish initialization and report memory usage
I0902 22:52:17.941810 2079114000 net.cpp:467] Collecting Learning Rate and Weight Decay.
I0902 22:52:17.941818 2079114000 net.cpp:219] Network initialization done.
I0902 22:52:17.941824 2079114000 net.cpp:220] Memory required for data: 201476

-注意:网络结构是设备无关的,Blob和Layer=隐藏了模型定义的具体实现细节。定义网络结构后,可以通过Caffe::mode()或者Caffe::set_mode()在CPU和GPU模式间切换。Layer在CPU和GPU模式下运算的结果是一致的(忽略计算误差)。CPU和GPU模式间是无缝切换的,并且独立于模型定义。

模型定义

  • 模型定义在prototxt文件中,而学习到的模型被二进制序列化为caffemodel文件。模型格式在caffe.proto文件中定义,源文件是self-explanatory的,所以鼓励大家去看。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值