caffe 中的 `"Python"` 层是什么?
What is a `"Python"` layer in caffe?
Caffe 有层类型 "Python"
。
例如,此图层类型可用作 loss layer。
在其他情况下,它被用作 .
这个图层类型是什么?
这个图层怎么用?
非常简单,它是您提供实现代码的层,而不是使用其中一种预定义类型——它们都由高效函数支持。
如果要定义自定义损失函数,请继续:自己编写,并创建类型为 Python 的图层。如果您有非标准的输入需求,也许是一些特定于数据的预处理,没问题:自己编写,并创建类型为 Python.[=10 的层=]
Python层不同于需要编译的C++层,它们的参数需要添加到proto文件中,最后需要在layer_factory中注册层。如果你写一个 python 层,你不需要担心这些事情。层参数可以定义为字符串,在python中可以作为字符串访问。例如:如果您在层中有一个参数,您可以使用 'self.param_str' 访问它,如果 param_str 在您的 prototxt 文件中定义。和其他图层一样,需要定义一个class,函数如下:
- 设置 - 使用从图层变量获得的参数初始化图层
- Forward - 层的输入和输出是什么
- 向后 - 给定下一层的预测和梯度,计算上一层的梯度
- Reshape - 如果需要,重塑你的 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 层的参数。 'module' 指定图层的文件名。如果名为 'anchor_target_layer.py' 的文件位于名为 'rpn' 的文件夹内,则参数将为 'rpn.anchor_target_layer'。 'layer' 参数是您的 class 的名称,在本例中为 'AnchorTargetLayer'。 'param_str' 是层的参数,其中包含键值 16 'feat_stride'。
与 C++/CUDA 层不同,Python 层目前无法在 caffe 的多 GPU 设置中工作,因此这是使用它们的缺点。
's and 的答案给出了 "Python"
层的总体目的:一个通用层,用 python 而不是 c++ 实现。
我打算将此答案作为使用 "Python"
图层的教程。
"Python"
层教程
什么是 "Python"
层?
请看 and 的优秀回答。
先决条件
为了使用'Python"
层你需要用flag
编译caffe
WITH_PYTHON_LAYER := 1
设置在'Makefile.config'
.
如何实现"Python"
层?
"Python"
层应作为 python class 派生自 caffe.Layer
基础 class 来实现。这个class必须有以下四种方法:
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
- 从 prototxt 传递到图层的字符串。有关详细信息,请参阅 。
def reshape(self, bottom, top)
:每当caffe重塑网络时调用该方法。此函数应分配输出(每个 top
blob)。输出的形状通常与 bottom
s 的形状有关。
def forward(self, bottom, top)
:实现从bottom
到top
的前向传递。
def backward(self, top, propagate_down, bottom)
:这个方法实现了反向传播,它将梯度从top
传播到bottom
。 propagate_down
是 len(bottom)
的布尔向量,指示应将梯度传播到 bottom
中的哪个。
有关 bottom
和 top
输入的更多信息,您可以在 中找到。
例子
您可以看到一些简化的 python 层 here, and here.
示例
可以找到 "moving average" 输出层的示例 。
可训练参数
"Python"
层可以有可训练的参数(如"Conv"
、"InnerProduct"
等)。
您可以在 and . There's also a very simplified example in caffe git.
中找到有关添加可训练参数的更多信息
如何在 prototxt 中添加 "Python"
图层?
详见的回答。
您需要将以下内容添加到您的 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 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 NetSpec
接口添加"Python"
层?
很简单:
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
s 它时 - 它可以被找到。
例如,如果您的模块 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
方法是easy,因为这个方法只实现了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 以继续进行 forward/backward 传递。
如果 python 层是输入层或最顶层的损失层,这种退化就不那么明显了。
更新: 2017 年 9 月 19 日 PR #5904 被合并到 master 中。此 PR 通过 python 接口公开 blob 的 GPU 指针。
您可以直接从 python 访问 blob._gpu_data_ptr 和 blob._gpu_diff_ptr,风险自负.
Caffe 有层类型 "Python"
。
例如,此图层类型可用作 loss layer。
在其他情况下,它被用作
这个图层类型是什么?
这个图层怎么用?
非常简单,它是您提供实现代码的层,而不是使用其中一种预定义类型——它们都由高效函数支持。
如果要定义自定义损失函数,请继续:自己编写,并创建类型为 Python 的图层。如果您有非标准的输入需求,也许是一些特定于数据的预处理,没问题:自己编写,并创建类型为 Python.[=10 的层=]
Python层不同于需要编译的C++层,它们的参数需要添加到proto文件中,最后需要在layer_factory中注册层。如果你写一个 python 层,你不需要担心这些事情。层参数可以定义为字符串,在python中可以作为字符串访问。例如:如果您在层中有一个参数,您可以使用 'self.param_str' 访问它,如果 param_str 在您的 prototxt 文件中定义。和其他图层一样,需要定义一个class,函数如下:
- 设置 - 使用从图层变量获得的参数初始化图层
- Forward - 层的输入和输出是什么
- 向后 - 给定下一层的预测和梯度,计算上一层的梯度
- Reshape - 如果需要,重塑你的 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 层的参数。 'module' 指定图层的文件名。如果名为 'anchor_target_layer.py' 的文件位于名为 'rpn' 的文件夹内,则参数将为 'rpn.anchor_target_layer'。 'layer' 参数是您的 class 的名称,在本例中为 'AnchorTargetLayer'。 'param_str' 是层的参数,其中包含键值 16 'feat_stride'。
与 C++/CUDA 层不同,Python 层目前无法在 caffe 的多 GPU 设置中工作,因此这是使用它们的缺点。
"Python"
层的总体目的:一个通用层,用 python 而不是 c++ 实现。
我打算将此答案作为使用 "Python"
图层的教程。
"Python"
层教程
什么是 "Python"
层?
请看
先决条件
为了使用'Python"
层你需要用flag
WITH_PYTHON_LAYER := 1
设置在'Makefile.config'
.
如何实现"Python"
层?
"Python"
层应作为 python class 派生自 caffe.Layer
基础 class 来实现。这个class必须有以下四种方法:
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
- 从 prototxt 传递到图层的字符串。有关详细信息,请参阅
def reshape(self, bottom, top)
:每当caffe重塑网络时调用该方法。此函数应分配输出(每个 top
blob)。输出的形状通常与 bottom
s 的形状有关。
def forward(self, bottom, top)
:实现从bottom
到top
的前向传递。
def backward(self, top, propagate_down, bottom)
:这个方法实现了反向传播,它将梯度从top
传播到bottom
。 propagate_down
是 len(bottom)
的布尔向量,指示应将梯度传播到 bottom
中的哪个。
有关 bottom
和 top
输入的更多信息,您可以在
例子
您可以看到一些简化的 python 层 here,
示例
可以找到 "moving average" 输出层的示例
可训练参数
"Python"
层可以有可训练的参数(如"Conv"
、"InnerProduct"
等)。
您可以在
如何在 prototxt 中添加 "Python"
图层?
详见
您需要将以下内容添加到您的 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 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 NetSpec
接口添加"Python"
层?
很简单:
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
s 它时 - 它可以被找到。
例如,如果您的模块 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
方法是easy,因为这个方法只实现了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 以继续进行 forward/backward 传递。
如果 python 层是输入层或最顶层的损失层,这种退化就不那么明显了。
更新: 2017 年 9 月 19 日 PR #5904 被合并到 master 中。此 PR 通过 python 接口公开 blob 的 GPU 指针。
您可以直接从 python 访问 blob._gpu_data_ptr 和 blob._gpu_diff_ptr,风险自负.