最近在学习Caffe,来总结一下Caffe中基本知识吧。Caffe中最基本的概念包括blobs,layers和nets。Caffe中的模型是基于定义好的网络,它从下到上定义了整个模型(即从输入的数据层到最后的loss层)。而模型中数据存储在叫做blob的数据结构中,该结构是一个标准的数组,并且是整个框架的统一内存接口。
在计算机视觉领域,大多数的数据都是一个四维(4D)数组(但对于非图像应用也是可以使用blobs的),常见的blobs对于图像集数据的维度是(
一个blob同时存储data和diff。data是传递过去的正常的数据,而diff是由网络计算出来的梯度值(差分值)。其可能存储在CPU或GPU上,而且获得它们的方式也有两种(const和非const的),const类型的可以改变数据,另一种不能。代码如下(这是data的cpu实现,gpu类似,而diff也是类似的):
const Dtype* cpu_data() const;
Dtype* mutable_cpu_data();
这些blob数据在CPU和GPU中传递是无缝连接的,可以参考下面的代码来解释。
// Assuming that data are on the CPU initially, and we have a blob.
const Dtype* foo;
Dtype* bar;
foo = blob.gpu_data(); // data copied cpu->gpu.
foo = blob.cpu_data(); // no data copied since both have up-to-date contents.
bar = blob.mutable_gpu_data(); // no data copied.
// ... some operations ...
bar = blob.mutable_gpu_data(); // no data copied when we are still on GPU.
foo = blob.cpu_data(); // data copied gpu->cpu, since the gpu side has modified the data
foo = blob.gpu_data(); // no data copied since both have up-to-date contents
bar = blob.mutable_cpu_data(); // still no data copied.
bar = blob.mutable_gpu_data(); // data copied cpu->gpu.
bar = blob.mutable_cpu_data(); // data copied gpu->cpu.
数据的流向就是这样的,其中数据一共被改变了3次(除了初始的CPU版本)。
接下来讲层,每一层都有三个基本的模块:setup(初始设置),forward(前向计算),backward(后向传播,即计算梯度值)。
Setup:在模型初始化的时候初始化层和连接;
Forward:给定底层的输入计算输出,并传递给顶层;
Backward:给定顶层输出的梯度值,计算关于输入的梯度值,并传递给底层。拥有参数的层计算关于参数的梯度值并且在内部存储起来。
而对于net,它是由很多层连接起来的计算图——有向无环图(DAG)。一个典型的网络(net)起始于从磁盘加载出来数据的数据层,并且以一个loss层结束。网络可以完成分类、重建等任务。
下面是一个简单的逻辑回归分类器。网络的图示和定义如下:
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"
}