转载链接: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. 23个Python爬虫开源项目代码,包含微信、淘宝、豆瓣、知乎、微博等

    今天为大家整理了23个Python爬虫项目.整理的原因是,爬虫入门简单快速,也非常适合新入门的小伙伴培养信心,所有链接指向GitHub,微信不能直接打开,老规矩,可以用电脑打开. 关注公众号「Pyth ...

  2. Leetcode 283.移动零 By Python

    思路 我们可以用python的list comprehension来取出所以非0的元素,而且这样取出来会保持原有的相对顺序,再统计先后变化的长度,补上相应的0即可 代码 class Solution( ...

  3. android 使用广播 接收和拦截 android系统短信

    package com.app.sms_broadcastreceiver; import android.app.Activity; import android.content.Broadcast ...

  4. 【转】位置式、增量式PID算法C语言实现

    位置式.增量式PID算法C语言实现 芯片:STM32F107VC 编译器:KEIL4 作者:SY 日期:2017-9-21 15:29:19 概述 PID 算法是一种工控领域常见的控制算法,用于闭环反 ...

  5. A1073. Scientific Notation

    Scientific notation is the way that scientists easily handle very large numbers or very small number ...

  6. MySQL索引原理及慢查询优化-来自美团网的技术blog(写的深入浅出)

    MySQL索引原理及慢查询优化 转:http://tech.meituan.com/mysql-index.html MySQL凭借着出色的性能.低廉的成本.丰富的资源,已经成为绝大多数互联网公司的首 ...

  7. PowerDesigner使用(设置继承,实现)

    1.File—New Mode 2添加4个class,1个接口(基本的添加工具都在这里面) 3.class1的设置名字,设置方法 3.设置继承,实现 4.编辑class2,class3继承父类的属性. ...

  8. 不跳转修改url(history.pushState)

    有时候我们会想不跳转的情况下修改url 直接上代码吧: history.pushState(null,"","?test=123") 值得注意的是,为了用户安全 ...

  9. How the Bitcoin protocol actually works

    sklearn实战-乳腺癌细胞数据挖掘(博客主亲自录制视频教程) https://study.163.com/course/introduction.htm?courseId=1005269003&a ...

  10. python3简单实现微信爬虫

    Python爬虫视频教程零基础小白到scrapy爬虫高手-轻松入门 https://item.taobao.com/item.htm?spm=a1z38n.10677092.0.0.482434a6E ...