本文主要讨论的是在caffe中添加python layer的一般流程,自己设计的test_python_layer.py层只是起到演示作用,没有实际的功能。
1) Python layer 在caffe目录结构中放哪?
下图是caffe的目录结构,在本文中我是将python layer防止examples/pycaffe/layers/下
2)Python layer内容
我给这一个python layer取名为test_python_layer.py,其内容为
import caffe import numpy as np class TestPythonLayer(caffe.Layer): """ Compute the Euclidean Loss in the same manner as the C++ EuclideanLossLayer to demonstrate the class interface for developing layers in Python. """ def setup(self, bottom, top): # check input pair if len(bottom) != 1: raise Exception("Need two inputs to compute distance.") def reshape(self, bottom, top): # loss output is scalar top[0].reshape(1) def forward(self, bottom, top): top[0].data[...] = np.sum(bottom[0].data**2) / bottom[0].num / 2.;print('Test passed!') def backward(self, top, propagate_down, bottom): pass
大家一定要注意,我这样设计这个层(包括代码、代码所放位置)是有一个前提的,那就是我导出了相应的环境变量,如下图所示(红色部分遮住的是具体的路径,大家可以根据自己的实际情况进行调整)。如果没有设置环境变量,可能会出现模块找不到问题。
3)如何测试这个python layer的可行性
设计一个网络结构prototxt文件
name: "CIFAR10_quick" layer { name: "cifar" type: "Data" top: "data" top: "label" include { phase: TRAIN } transform_param { mean_file: "examples/cifar10/mean.binaryproto" } data_param { source: "examples/cifar10/cifar10_train_lmdb" batch_size: 100 backend: LMDB } } layer { name: "cifar" type: "Data" top: "data" top: "label" include { phase: TEST } transform_param { mean_file: "examples/cifar10/mean.binaryproto" } data_param { source: "examples/cifar10/cifar10_test_lmdb" batch_size: 100 backend: LMDB } } layer { name: "test" type: "Python" bottom: "data" top: "loss" python_param { module: "test_python_layer" layer: "TestPythonLayer" } }
及其对应solver文件
net: "examples/cifar10/test_python_layer.prototxt" base_lr: 0.001 lr_policy: "fixed" max_iter: 10 solver_mode: CPU
通过下面命令即可测试其效果
其输出为
我是在cifar10样例的基础上设计上述python layer的,这点请大家注意。可以看出,“test passed!”一共出现了10次,这符合我们的预期。
4)下面是问题的重点,在测试的时候我们可能会遇到如下问题
我自己在这个问题上摸索了一个上午(查了很多资料,始终没有解决这个问题),最后索性按照自己的理解来处理了。我的思路大致如下:在没有添加python layer的时候,我的caffe版本能够正常运行;protobuf版本不匹配问题,应该不是caffe C++部分引起的;这样问题就定位到python protobuf的版本问题,我发现自己python的protobuf版本为3.2.0,这样问题就可以轻而易举的按照如下方式解决了
先卸载已有的protobuf
然后按照2.5.0版本的protobuf(这个版本好应该根据自己的错误提示确定)
至此,问题得到解决!
5)关于python层,我谈谈自己的一些看法
- 可以用python layer实现on-the-fly的数据增强!
- GPU模式下,用python layer的时候应该牢记“数据是不是来回在GPU、CPU直接copy”!这样有助于你定位在什么地方应该用python layer!