什么是caffe中的`”Python”`层?

caffe有一个名为"Python"的层类型。

例如,这个层类型可以作为损失层使用。
在其他情况下,它可以用作输入层

这个层类型是什么?
如何使用这个层?


回答:

PruneBharat的回答给出了"Python"层的总体目的:这是一个用Python而不是C++实现的通用层。

我希望这个回答能作为使用"Python"层的教程。


"Python"层的教程

什么是"Python"层?

请查看PruneBharat的优秀回答。

前提条件

为了使用'Python"层,你需要在编译caffe时设置标志

WITH_PYTHON_LAYER := 1

'Makefile.config'中设置。

如何实现一个"Python"层?

一个"Python"层应该实现为从caffe.Layer基类派生的Python类。这个类必须有以下四个方法:

import caffeclass my_py_layer(caffe.Layer):  def setup(self, bottom, top):    pass  def reshape(self, bottom, top):    pass  def forward(self, bottom, top):    pass  def backward(self, top, propagate_down, bottom):    pass

这些方法是什么?

def setup(self, bottom, top): 这个方法在caffe构建网络时调用一次。这个函数应该检查输入的数量(len(bottom))和输出的数量(len(top))是否符合预期。
你也应该在这里分配网络的内部参数(即,self.add_blobs()),更多信息请参见这个讨论
这个方法可以访问self.param_str – 从prototxt传递给层的字符串。更多信息请参见这个讨论

def reshape(self, bottom, top): 这个方法在caffe重塑网络时调用。这个函数应该分配输出(每个top blob)。输出的形状通常与bottom的形状相关。

def forward(self, bottom, top): 实现从bottomtop的前向传递。

def backward(self, top, propagate_down, bottom): 这个方法实现反向传播,它将梯度从top传播到bottompropagate_downlen(bottom)长度的布尔向量,表示应该将梯度传播到哪些bottom

关于bottomtop输入的更多信息,你可以在这篇文章中找到。

示例
你可以在这里看到一些简化的Python层的示例:这里这里这里
“移动平均”输出层的示例可以在这里找到。

可训练参数
"Python"层可以有可训练参数(如"Conv""InnerProduct"等)。
关于添加可训练参数的更多信息,你可以在这个讨论这个讨论中找到。在caffe git中也有一个非常简化的示例。

如何在prototxt中添加"Python"层?

有关详细信息,请查看Bharat的回答。
你需要在你的prototxt中添加以下内容:

layer {  name: 'rpn-data'  type: 'Python'    bottom: 'rpn_cls_score'  bottom: 'gt_boxes'  bottom: 'im_info'  bottom: 'data'  top: 'rpn_labels'  top: 'rpn_bbox_targets'  top: 'rpn_bbox_inside_weights'  top: 'rpn_bbox_outside_weights'  python_param {    module: 'rpn.anchor_target_layer'  # python模块名称,你的实现所在    layer: 'AnchorTargetLayer'   # 类实现的名称    param_str: "'feat_stride': 16"   # 层的可选参数  }}

如何使用pythonic的NetSpec接口添加"Python"层?

这非常简单:

import caffefrom caffe import layers as Lns = caffe.NetSpec()# 在这里定义层...ns.rpn_labels, ns.rpn_bbox_targets, \  ns.rpn_bbox_inside_weights, ns.rpn_bbox_outside_weights = \    L.Python(ns.rpn_cls_score, ns.gt_boxes, ns.im_info, ns.data,              name='rpn-data',             ntop=4, # 告诉caffe期望四个输出blob             python_param={'module': 'rpn.anchor_target_layer',                           'layer': 'AnchorTargetLayer',                           'param_str': '"\'feat_stride\': 16"'})

如何使用包含"Python"层的网络?

从caffe调用Python代码无需担心。Caffe使用boost API从编译的C++中调用Python代码。
你需要做什么?
确保实现你的层的Python模块在$PYTHONPATH中,以便caffe在import时可以找到它。
例如,如果你的模块my_python_layer.py位于/path/to/my_python_layer.py,那么

PYTHONPATH=/path/to:$PYTHONPATH $CAFFE_ROOT/build/tools/caffe train -solver my_solver.prototxt

应该可以正常工作。

如何测试我的层?

在使用你的层之前,你应该始终测试它。
测试forward函数完全取决于你,因为每个层都有不同的功能。
测试backward方法是容易的,因为这个方法只实现forward的梯度,可以自动进行数值测试!
查看test_gradient_for_python_layer测试工具:

import numpy as npfrom test_gradient_for_python_layer import test_gradient_for_python_layer# 设置输入input_names_and_values = [('in_cont', np.random.randn(3,4)),                           ('in_binary', np.random.binomial(1, 0.4, (3,1))]output_names = ['out1', 'out2']py_module = 'folder.my_layer_module_name'py_layer = 'my_layer_class_name'param_str = 'some params'propagate_down = [True, False]# 调用测试test_gradient_for_python_layer(input_names_and_values, output_names,                                py_module, py_layer, param_str,                                propagate_down)# 你完成了!

特别注意

值得注意的是,Python代码只能在CPU上运行。因此,如果你计划在网络的中间使用Python层,你会看到性能显著下降,如果你计划使用GPU的话。这是因为caffe需要在调用Python层之前将blob从GPU复制到CPU,然后再复制回GPU以继续进行前向/后向传递。
如果Python层是输入层或最顶层的损失层,这种性能下降的影响要小得多。
更新: 2017年9月19日,PR #5904被合并到master中。这个PR通过Python接口暴露了blob的GPU指针。你可以直接从Python访问blob._gpu_data_ptr和blob._gpu_diff_ptr,但需自担风险

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注