caffe中的“" Python"”层是什么?

时间:2016-12-27 11:17:14

标签: python neural-network deep-learning caffe pycaffe

Caffe的图层类型为"Python"

例如,此图层类型可用作loss layer 在其他情况下,它用作input layer

这种图层类型是什么?
如何使用这一层?

3 个答案:

答案 0 :(得分:33)

PruneBharat的答案给出了"Python"图层的总体目的:通用图层,它是用python而不是c ++实现的。

我打算将此答案作为使用"Python"图层的教程。

"Python"图层

的教程

什么是"Python"图层?

请参阅PruneBharat的优秀答案。

预备知识

要使用'Python"图层,您需要使用标记

编译caffe
WITH_PYTHON_LAYER := 1

'Makefile.config'中设置。

如何实施"Python"图层?

"Python"层应该实现为从caffe.Layer基类派生的python类。此类必须具有以下四种方法:

import caffe
class 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()),有关详细信息,请参阅this thread
此方法可以访问self.param_str - 从原型文本传递到图层的字符串。有关详细信息,请参阅this thread

def reshape(self, bottom, top) :只要caffe重塑网络,就会调用此方法。此函数应分配输出(每个top blob)。输出的形状通常与bottom s'的形状有关。

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

def backward(self, top, propagate_down, bottom) :此方法实现反向传播,它将渐变从top传播到bottompropagate_downlen(bottom)的布尔向量,表示应该传播渐变的bottom

您可以在this post中找到有关bottomtop输入的更多信息。

<强>实施例
您可以看到一些简化的python图层hereherehere的示例 可以找到“移动平均”输出图层的示例here

可训练参数
"Python"图层可以包含可训练的参数(例如"Conv""InnerProduct"等) 您可以在this threadthis one中找到有关添加可训练参数的详细信息。 caffe git中还有一个非常简化的例子。

如何在原型文件中添加"Python"图层?

有关详细信息,请参阅Bharat的答案 您需要将以下内容添加到您的原型文本中:

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 module name where your implementation is
    layer: 'AnchorTargetLayer'   # the name of the class implementation
    param_str: "'feat_stride': 16"   # optional parameters to the layer
  }
}

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

这很简单:

import caffe
from caffe import layers as L

ns = caffe.NetSpec()
# define layers here...
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, # tell caffe to expect four output blobs
             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 np
from test_gradient_for_python_layer import test_gradient_for_python_layer

# set the inputs
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]

# call the test
test_gradient_for_python_layer(input_names_and_values, output_names, 
                               py_module, py_layer, param_str, 
                               propagate_down)

# you are done!

特别通知

值得注意的是,python代码仅在CPU上运行。因此,如果您计划在网络的中间中安装Python层,那么如果您计划使用GPU,则会看到重大性能下降。这是因为caffe需要在调用python层之前将blob从GPU复制到CPU,然后复制回GPU以继续前进/后退传递。
如果python层是输入层或最顶层的丢失层,那么这种降级就不那么重要了 更新: 2017年9月19日PR #5904合并为主人。这个PR通过python接口暴露了blob的GPU指针。 您可以直接从python 访问blob._gpu_data_ptr和blob._gpu_diff_ptr,风险自负

答案 1 :(得分:8)

很简单,它是提供实现代码的层,而不是使用其中一种预定义类型 - 这些都是高效函数支持。

如果要定义自定义丢失函数,请继续:自己编写,然后创建类型为 Python 的图层。如果您有非标准的输入需求,也许是一些特定于数据的预处理,没问题:自己编写,并创建类型为 Python 的图层。

答案 2 :(得分:7)

Python层与需要编译的C ++层不同,需要将它们的参数添加到proto文件中,最后需要在layer_factory中注册层。如果你写了一个python层,你不必担心这些事情。层参数可以定义为字符串,可以在python中作为字符串访问。例如:如果图层中有参数,则可以使用&#39; self.param_str&#39;来访问它,如果在原型文件文件中定义了param_str。与其他图层一样,您需要使用以下函数定义类:

  • 设置 - 使用从图层变量
  • 获取的参数初始化图层
  • 转发 - 图层的输入和输出是什么
  • 向后 - 给定下一层的预测和渐变,计算前一层的渐变
  • 重塑 - 根据需要重塑您的blob

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'
    layer: 'AnchorTargetLayer'
    param_str: "'feat_stride': 16"
  }
}

这里,图层的名称是rpn-data,bottom和top分别是图层的输入和输出细节。 python_param定义了Python层的参数。 &#39;模块&#39;指定图层的文件名。如果该文件名为&#39; anchor_target_layer.py&#39;它位于名为&#39; rpn&#39;的文件夹中,参数为&#39; rpn.anchor_target_layer&#39;。 &#39;层&#39; parameter是您的类的名称,在这种情况下,它是&#39; AnchorTargetLayer&#39;。 &#39; param_str&#39;是图层的参数,其中包含键值#16; feat_stride&#39;。

与C ++ / CUDA图层不同,截至目前,Python图层在caffe中的多GPU设置中不起作用,因此使用它们是不利的。