caffe框架相关知识-基层layer
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
caffe框架相关知识-基层
layer
父类Layer
数据成员:
protected:
/** The protobuf that stores the layer parameters
LayerParameter layer_param_;
-------------------------------------------------
/** The phase: TRAIN or TEST */
Phase phase_;
-------------------------------------------------
/** The vector that stores the learnable parameters as a set of blobs. */
-------------------------------------------------
vector<shared_ptr<Blob<Dtype> > > blobs_;
-------------------------------------------------
/** Vector indicating whether to compute the diff of each param blob. */
vector<bool> param_propagate_down_;
-------------------------------------------------
/** The vector that indicates whether each top blob has a non-zero weight in
* the objective function. */
-------------------------------------------------
vector<Dtype> loss_;
blobs_ :存的是神经网络层的权重参数,和偏置参数
1、构造函数
/**
* You should not implement your own constructor. Any set up code should go to SetUp(), where the dimensions of the bottom blobs are provided to the layer.
*/
// 显示的构造函数不需要重写,任何初始工作在SetUp()中完成
// 构造方法只复制层参数说明的值,如果层说明参数中提供了权值和偏置参数,也复制
explicit Layer(const LayerParameter& param)
: layer_param_(param) {
// Set phase and copy blobs (if there are any).
phase_ = param.phase();
if (layer_param_.blobs_size() > 0) {
blobs_.resize(layer_param_.blobs_size());
for (int i = 0; i < layer_param_.blobs_size(); ++i) {
blobs_[i].reset(new Blob<Dtype>());
blobs_[i]->FromProto(layer_param_.blobs(i));
}
}
}
// 虚析构
virtual ~Layer() {}
初始化函数SetUp,每个Layer对象都必须遵循固定的调用模式, * @brief Implements common layer setup functionality.
* @brief 实现每个layer对象的setup函数
* @param bottom the preshaped input blobs
* @param bottom 层的输入数据,blob中的存储空间已申请
* @param top
* the allocated but unshaped output blobs, to be shaped by Reshape
* @param top 层的输出数据,blob对象以构造但是其中的存储空间未申请,
* 具体空间大小需根据bottom blob大小和layer_param_共同决定,具体在Reshape函数现实
*
* Checks that the number of bottom and top blobs is correct. * Calls LayerSetUp to do special layer setup for individual layer types, 对不同的层,调用不同的函数
* followed by Reshape to set up sizes of top blobs and internal buffers.
* Sets up the loss weight multiplier blobs for any non-zero loss weights.
* This method may not be overridden.
* 1. 检查输入输出blob个数是否满足要求,每个层能处理的输入输出数据不一样
* 2. 调用LayerSetUp函数初始化特殊的层,每个Layer子类需重写这个函数完成定制的初始化
* 3. 调用Reshape函数为top blob分配合适大小的存储空间
* 4. 为每个top blob设置损失权重乘子,非LossLayer为的top blob其值为零
* 此方法非虚函数,不用重写,模式固定
*/
void SetUp(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
CheckBlobCounts(bottom, top);
LayerSetUp(bottom, top);
Reshape(bottom, top);
SetLossWeights(top);
}
每个子类Layer必须重写的初始化函数LayerSetUp
/**
* @brief Does layer-specific setup: your layer should implement this function
* as well as Reshape.
* @brief 定制初始化,每个子类layer必须实现此虚函数
* @param bottom
* the preshaped input blobs, whose data fields store the input data for
* this layer
* @param bottom
* 输入blob, 数据成员data_和diff_存储了相关数据
* @param top
* the allocated but unshaped output blobs
* @param top
* 输出blob, blob对象已构造但数据成员的空间尚未申请 *
* This method should do one-time layer specific setup. This includes reading
* and processing relevent parameters from the
<code>layer_param_</code>.
* Setting up the shapes of top blobs and internal buffers should be done in
* <code>Reshape</code>, which will be called before the forward pass to
* adjust the top blob sizes.
* 此方法执行一次定制化的层初始化,包括从layer_param_读入并处理相关的层权值和偏置参数,
* 调用Reshape函数申请top blob的存储空间
*/
virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {}
每个子类Layer必须重写的Reshape函数,完成top blob形状的设置并为其分配存储空间
/**
* @brief Adjust the shapes of top blobs and internal buffers to accomodate
* the shapes of the bottom blobs.
* @brief 根据bottom blob的形状和layer_param_计算top blob 的形状并为其分配存储空间
*
* @param bottom the input blobs, with the requested input shapes
* @param top the top blobs, which should be reshaped as needed
*
* This method should reshape top blobs as needed according to the shapes
* of the bottom (input) blobs, as well as reshaping any internal buffers
* and making any other necessary adjustments so that the layer can
* accomodate the bottom blobs.
*/
virtual void Reshape(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) = 0;
前向传播函数Forward和反向传播函数Backward
inline Dtype Forward(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top);
inline void Backward(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down,
const vector<Blob<Dtype>*>& bottom);
根据:
// Forward and backward wrappers. You should implement the cpu and gpu specific implementations instead, and should not change these functions.
template <typename Dtype>
inline Dtype Layer<Dtype>::Forward(const
vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
Dtype loss = 0;
switch (Caffe::mode()) {
case Caffe::CPU:
Forward_cpu(bottom, top);
for (int top_id = 0; top_id < top.size(); ++top_id) { if (!this->loss(top_id)) { continue; }
const int count = top[top_id]->count();
const Dtype* data = top[top_id]->cpu_data();
const Dtype* loss_weights = top[top_id]->cpu_diff();
loss += caffe_cpu_dot(count, data, loss_weights);
}
break;
case Caffe::GPU:
Forward_gpu(bottom, top);
#ifndef CPU_ONLY
for (int top_id = 0; top_id < top.size(); ++top_id) { if (!this->loss(top_id)) { continue; }
const int count = top[top_id]->count();
const Dtype* data = top[top_id]->gpu_data();
const Dtype* loss_weights = top[top_id]->gpu_diff(); Dtype blob_loss = 0;
caffe_gpu_dot(count, data, loss_weights, &blob_loss); loss += blob_loss;
}
#endif
break;
default:
LOG(FATAL) << "Unknown caffe mode.";
}
return loss;
}
Backward同理。
这两个函数非虚函数,它们内部会调用如下虚函数完成数据前向传递和误差反向传播,根据执行环境的不同每个子类Layer必须重写CPU和GPU版本
virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) = 0;
virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
// LOG(WARNING) << "Using CPU code as backup.";
return Forward_cpu(bottom, top);
}
virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down,
const vector<Blob<Dtype>*>& bottom) = 0;
virtual void Backward_gpu(const vector<Blob<Dtype>*>& top, const vector<bool>& propagate_down,
const vector<Blob<Dtype>*>& bottom) {
// LOG(WARNING) << "Using CPU code as backup.";
Backward_cpu(top, propagate_down, bottom);
Layer的序列化函数,将layer的层说明参数layer_param_,层权值和偏置参数blobs_复制到LayerParameter对象,便于写到磁盘
// Serialize LayerParameter to protocol buffer
template <typename Dtype>
void Layer<Dtype>::ToProto(LayerParameter* param, bool
write_diff) {
param->Clear();
param->CopyFrom(layer_param_); // 复制层说明参数
layer_param_
param->clear_blobs();
// 复制层权值和偏置参数blobs_
for (int i = 0; i < blobs_.size(); ++i) {
blobs_[i]->ToProto(param->add_blobs(), write_diff); }
}。