转载链接: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. Huawei运维记录

    Huawei运维记录 01 Huawei运维记录-AC6005-8AP设备启动界面 02 Huawei运维记录-AC6005-8AP添加授权码 03 Huawei运维记录-AC6005版本升级步骤

  2. spring aop 获取request、response对象

    在网上看到有不少人说如下方式获取: 1.在web.xml中添加监听 <listener>          <listener-class>              org. ...

  3. C# winform C/S WebBrowser 微信第三方登录

    网上很多的资料都是B/S结构的,这里是基于C# C/S 结构的微信第三方授权登录 一.准备知识 1 http Get和Post方法.做第三方授权登录,获取信息基本上都是用get和post方法,做之前需 ...

  4. git中如何切换分支,拉取分支,合并分支

    idea中如何使用git来做分支的切换合并: https://blog.csdn.net/autfish/article/details/52513465 本地分支与远程分支: https://seg ...

  5. Linux中的Diff和Patch

    本文主要记录两个命令的学习情况:diff 和 patch.diff 和 patch 是一对工具,使用这对工具可以获取更新文件与历史文件的差异,并将更新应用到历史文件上.在数学上说,diff就是对两个集 ...

  6. ArrayList创建步骤及基本方法

    ArrayList创建变量的步骤 ArrayList ------>集合 1: 导入包 java.util.ArrayList包中 2: 创建引用类型的变量 数据类型< 集合存储的数据类型 ...

  7. UTF-8 GBK GB2312

    至于UTF-8编码则是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24位(三个字节)来编码.对于英文字符较多的论坛则用UTF-8节省空间. GBK包含全部中文字符:UT ...

  8. the difference __str__ and __repr__

    First, let me reiterate the main points in Alex’s post: The default implementation is useless (it’s ...

  9. TCP详解——传输控制协议(总述)

    初次熟读TCP,随着TCP的发展路线对他深入了解,真心觉得TCP协议的美妙之处.他比UDP这家伙更加可靠,深得我们信任.通过一个个英文简写,例如CRC.ARQ.RTT.ACK.SACK.DACK等,组 ...

  10. Python/spss-多元回归建模-共线性诊断1(推荐A)

    欢迎关注博主主页,学习python视频资源,还有大量免费python经典文章 sklearn实战-乳腺癌细胞数据挖掘 https://study.163.com/course/introduction ...