首先来看官网给出的该层的定义:
The Python layer allows users to add customized layers without modifying the Caffe core code.
在不改变caffe核心代码的情况下,可以使用Python 来定义Layer层。
caffe编译:
修改caffe根目录下的Makefile.config文件(WITH_PYTHON_LAYER :=1),使其支持通过python新建层。
参数定义:
layer {
name: 'data'
type: 'Python'
top: 'data'
top: 'gt_boxes'
python_param {
module: 'roi_data_layer.layer'//module的名字通常是定义层的.py文件的文件名
layer: 'RoIDataLayer'//module中的类名,即对应的layer.py中定义的class类
param_str: "'num_classes': 21"
}
}
结合以上代码分析,首先该数据层的类型(type)为Python,参数配置在src/caffe/proto/caffe.proto
message PythonParameter {
optional string module = 1;
optional string layer = 2;
optional string param_str = 3 [default = ''];
optional bool share_in_parallel = 4 [default = false];
}
源码解析:
头文件定义在根目录./include/caffe/layers/python_layer.hpp
#ifndef CAFFE_PYTHON_LAYER_HPP_
#define CAFFE_PYTHON_LAYER_HPP_
#include <boost/python.hpp>
#include <vector>
#include "caffe/layer.hpp"
namespace bp = boost::python;
namespace caffe {
template <typename Dtype>
class PythonLayer : public Layer<Dtype> {
public:
//通过PyObject,输入参数内容
PythonLayer(PyObject* self, const LayerParameter& param)
: Layer<Dtype>(param), self_(bp::handle<>(bp::borrowed(self))) { }
//输入数据
virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
// Disallow PythonLayer in MultiGPU training stage, due to GIL issues
// Details: https://github.com/BVLC/caffe/issues/2936
if (this->phase_ == TRAIN && Caffe::solver_count() > 1
&& !ShareInParallel()) {
LOG(FATAL) << "PythonLayer is not implemented in Multi-GPU training";
}
self_.attr("param_str") = bp::str(
this->layer_param_.python_param().param_str());
self_.attr("phase") = static_cast<int>(this->phase_);
self_.attr("setup")(bottom, top);
}
//通过reshape,调整数据的形状
virtual void Reshape(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
self_.attr("reshape")(bottom, top);
}
//采用并行线程
virtual inline bool ShareInParallel() const {
return this->layer_param_.python_param().share_in_parallel();
}
virtual inline const char* type() const { return "Python"; }
protected:
//前向传播
virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
self_.attr("forward")(bottom, top);
}
//后向传播
virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {
self_.attr("backward")(top, propagate_down, bottom);
}
private:
bp::object self_;
};
} // namespace caffe
#endif