转载链接:http://withwsf.github.io/2016/04/14/Caffe-with-Python-Layer/

Caffe通过Boost中的Boost.Python模块来支持使用Python定义Layer:

  • 使用C++增加新的Layer繁琐耗时而且很容易出错
  • 开发速度执行速度之间的trade-off

编译支持Python Layer的Caffe

如果是首次编译,修改Caffe根目录下的Makefile.cinfig,uncomment

1
WITH_PYTHON_LAYER:=1

如果已经编译过

1
2
make clean
WITH_PYTHON_LAYER=1 make&& make pycaffe

使用Python Layer

在网络的prototxt文件中添加一个Python定义的loss层如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
layer{
type: ’Python'
name: 'loss'
top: 'loss'
bottom: ‘ipx’
bottom: 'ipy'
python_param{
#module的名字,通常是定义Layer的.py文件的文件名,需要在$PYTHONPATH下
module: 'pyloss'
#layer的名字---module中的类名
layer: 'EuclideanLossLayer'
}
loss_weight: 1
}

定义Python Layer

根据上面的要求,我们在$PYTHONPAT在创建pyloss.py,并在其中定义EuclideanLossLayer。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import caffe
import numpy as np
class EuclideadLossLayer(caffe.Layer):#EuclideadLossLayer没有权值,反向传播过程中不需要进行权值的更新。如果需要定义需要更新自身权值的层,最好还是使用C++
def setup(self,bottom,top):
#在网络运行之前根据相关参数参数进行layer的初始化
if len(bottom) !=2:
raise exception("Need two inputs to compute distance")
def reshape(self,bottom,top):
#在forward之前调用,根据bottom blob的尺寸调整中间变量和top blob的尺寸
if bottom[0].count !=bottom[1].count:
raise exception("Inputs must have the same dimension.")
self.diff=np.zeros_like(bottom[0].date,dtype=np.float32)
top[0].reshape(1)
def forward(self,bottom,top):
#网络的前向传播
self.diff[...]=bottom[0].data-bottom[1].data
top[0].data[...]=np.sum(self.diff**2)/bottom[0].num/2.
def backward(self,top,propagate_down,bootm):
#网络的前向传播
for i in range(2):
if not propagate_down[i]:
continue
if i==0:
sign=1
else:
sign=-1
bottom[i].diff[...]=sign*self.diff/bottom[i].num

原理浅析

阅读caffe源码pythonlayer.hpp可以知道,类PythonLayer继承自Layer,并且新增私有变量boost::python::object self来表示我们自己定义的python layer的内存对象。

类PythonLayer类的成员函数LayerSetUP, Reshape, Forward_cpu和Backward_cpu分别是对我们自己定义的python layer中成员函数setup, reshape, forward和backward的封装调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class PythonLayer : public Layer<Dtype> {
public:
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("setup")(bottom, top);
}
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_;
};
整体流程大致为:首先从文件中读入solver并生成一个solver,然后根据solver的net路径生成一
个net,net调用layer_factory循环生成每个层,最后根据读入model或是filler来初始化参数。从上面的流程可以知道layer_factory是循环生成每个层,我看.cpp文件也的确写了#if
WITH_PYTHON_LAYER,然后有什么什么操作,比如储存python
layer的python_param,并调用setup,这里实际上已经是利用boost进行C++
Python混编了。这些操作的定义就在python_layer.hpp文件中。
layer_factory中python
layer的setup相关具体操作是,先根据param找到module的位置,再加载module,再根据层名加载层,然后前向计算反向计算什么的。
这些就已经算是达到目的了。不过只是知道相对路径,怎么可能加载成功呢?然后又继续找啊找,终于在faster
rcnn的tools文件中找到。_init_paths里有写一些预操作,比如将lib路径写入PYTHONPATH中,当然如果写入的话,这样就可以
直接加载了。

caffe中使用python定义新的层的更多相关文章

  1. 在caffe中增加和convolution相同的层

    1.打开vision_layers.hpp,复制ConvolutionLayer的代码,把类名还有构造函数的名字改为WtfLayer,把里面的带GPU的函数删掉. 2.Wtf_layer.cpp 添加 ...

  2. Anaconda3中的python安装新模块

    1.确认安装位置:D:\Anaconda3 2.进入: D:\Anaconda3\Scripts 3.pip install -i https://pypi.tuna.tsinghua.edu.cn/ ...

  3. caffe中使用crop_size剪裁训练图片

    layer { name: "data" type: "Data" top: "data" top: "label" i ...

  4. caffe 中 python 数据层

    caffe中大多数层用C++写成. 但是对于自己数据的输入要写对应的输入层,比如你要去图像中的一部分,不能用LMDB,或者你的label 需要特殊的标记. 这时候就需要用python 写一个输入层. ...

  5. caffe中python接口的使用

    下面是基于我自己的接口,我是用来分类一维数据的,可能不具通用性: (前提,你已经编译了caffe的python的接口) 添加 caffe塻块的搜索路径,当我们import caffe时,可以找到. 对 ...

  6. caffe中各层的作用:

    关于caffe中的solver: cafffe中的sover的方法都有: Stochastic Gradient Descent (type: "SGD"), AdaDelta ( ...

  7. 【神经网络与深度学习】如何在Caffe中配置每一个层的结构

    如何在Caffe中配置每一个层的结构 最近刚在电脑上装好Caffe,由于神经网络中有不同的层结构,不同类型的层又有不同的参数,所有就根据Caffe官网的说明文档做了一个简单的总结. 1. Vision ...

  8. caffe中关于(ReLU层,Dropout层,BatchNorm层,Scale层)输入输出层一致的问题

    在卷积神经网络中.常见到的激活函数有Relu层 layer { name: "relu1" type: "ReLU" bottom: "pool1&q ...

  9. python开发_python中的函数定义

    下面是我做的几个用列: #python中的函数定义,使用和传参 def_str = '''\ python中的函数以如下形式声明: def 函数名称([参数1,参数2,参数3......]): 执行语 ...

随机推荐

  1. 自学Zabbix3.12.4-动作Action-Operation配置

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 3.12.4 自学Zabbix3.12.4-动作Action-Operation配置 1. 概述 ...

  2. 隐藏SharePoint 2013 team sites里的follow按钮

    cls $featureid = 'a7a2793e-67cd-4dc1-9fd0-43f61581207a'$webapps = Get-spWebApplicationforeach($webap ...

  3. luogu4268 Directory Traversal (dfs)

    题意:给一个树状的文件结构,让你求从某个文件夹出发访问到所有文件,访问路径字符串长度之和的最小值,其中,访问父节点用..表示,两级之间用/分割 做两次dfs,第一次算DownN[x]和DownS[x] ...

  4. go vendor目录

    参考 https://blog.csdn.net/u010649766/article/details/80327035 那么查找依赖包路径的解决方案如下: 当前包下的vendor目录. 向上级目录查 ...

  5. ormlite 文档

    目录[-] A Fast, Simple, Typed ORM for .NET Download 8 flavours of OrmLite is on NuGet: Docs and Downlo ...

  6. Some Interesting Problems(持续更新中)

    这种题目详解,是“一日一测”与“一句话题解”栏目所无法覆盖的,可能是考试用题,也可能是OJ题目.常常非常经典,可以见微知著.故选其精华,小列如下. T1:fleet 给定一个序列,询问[L,R]间有多 ...

  7. maveb安装与配置(win10)

    转载:https://www.cnblogs.com/eagle6688/p/7838224.html 看了几篇博客,感觉这篇博客写的含金量最高了,因为我电脑的系统是win10的,所以配置有细微的差别 ...

  8. 读取数据库配置信息的两种方式(以后开发项目用java链接数据库)-------java基础知识

    第一步:先建立jdbc.properties user=root password url/yanlong driver=com.mysql.jdbc.Driver 第一种方式:直接文件读取 pack ...

  9. ElasticSearch入门介绍一

    ElasticSearch 关于es的几个概念: 集群:多个运行es节点可以组成一个集群,它们拥有相同的cluster.name. 节点:运行es的实例 索引:相当于数据库database,一个集群可 ...

  10. 面向对象【day07】:新式类和经典类(八)

    本节内容 1.概述 2.类的多继承 3.经典类VS新式类 4.总结 一.概述 在python还支持多继承,但是一般我们很少用,有些语言干脆就不支持多继承,有多继承,就会带来两个概念,经典类和新式类,下 ...