Caffeにはレイヤータイプ"Python"
。
たとえば、このレイヤータイプは 損失レイヤー として使用できます。
それ以外の場合は 入力層 として使用されます。
このレイヤータイプは何ですか?
このレイヤーはどのように使用できますか?
Prune と Bharat の回答は、"Python"
レイヤーの全体的な目的を提供します。C++ではなくpythonで実装される汎用レイヤーです。
この回答は、"Python"
レイヤーを使用するためのチュートリアルとして機能することを意図しています。
"Python"
レイヤーのチュートリアル"Python"
レイヤーとはPrune および Bharat の優れた答えをご覧ください。
'Python"
レイヤーを使用するには、フラグ付きのカフェをコンパイルする必要があります
WITH_PYTHON_LAYER := 1
'Makefile.config'
で設定します。
"Python"
レイヤーを実装するには?"Python"
レイヤーは、caffe.Layer
基本クラスから派生したpythonクラスとして実装する必要があります。このクラス must には、次の4つのメソッドがあります。
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)
:このメソッドは、カフェがネットを構築するときに一度呼び出されます。この関数は、入力の数(len(bottom)
)と出力の数(len(top)
)が期待どおりであることを確認する必要があります。
ネットの内部パラメータもここに割り当てる必要があります(つまり、self.add_blobs()
)。詳細は this thread を参照してください。
このメソッドは、self.param_str
-プロトテキストからレイヤーに渡される文字列にアクセスできます。詳細は this thread を参照してください。
def reshape(self, bottom, top)
:このメソッドは、カフェがネットを再形成するたびに呼び出されます。この関数は、出力(各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
sのどれに伝播するかを示します。
this post にあるbottom
およびtop
入力に関する詳細情報。
例
簡略化されたpythonレイヤー here 、 here および here の例をいくつか示します。
「移動平均」出力レイヤーの例を見つけることができます ここ 。
トレーニング可能なパラメータ"Python"
レイヤーは、トレーニング可能なパラメーター("Conv"
、"InnerProduct"
など)を持つことができます。
this thread および this 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
}
}
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
にあることを確認してください。これにより、カフェ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でのみ実行されることに注意してください。したがって、ネットのmiddleにPythonレイヤーを配置する場合は、 significant が表示されますGPUの使用を計画している場合、パフォーマンスの低下。これは、カフェがpythonレイヤーを呼び出す前にGPUからCPUにblobをコピーし、次にGPUにコピーしてフォワード/バックワードパスを続行する必要があるために発生します。
pythonレイヤーが入力レイヤーまたは最上位の損失レイヤーのいずれかである場合、この低下はそれほど重要ではありません。
更新:2017年9月19日に PR#5904 がマスターに統合されました。このPRは、pythonインターフェイスを介してblobのGPUポインターを公開します。 blob._gpu_data_ptrとblob._gpu_diff_ptrには、python から直接ご自身の責任で直接アクセスできます。
非常に簡単に言うと、これは、youが実装コードを提供するレイヤーであり、事前定義されたタイプの1つを使用するのではなく、すべて効率的な機能。
カスタム損失関数を定義する場合は、先に進んでください。自分で記述し、タイプPythonでレイヤーを作成してください。非標準の入力が必要な場合、おそらくデータ固有の前処理があれば問題ありません。自分で記述し、タイプPythonでレイヤーを作成します。
Pythonレイヤーは、コンパイルする必要があるC++レイヤーとは異なり、それらのパラメーターをprotoファイルに追加する必要があり、最後にレイヤーをlayer_factoryに登録する必要があります。 pythonレイヤーを作成する場合、これらのことについて心配する必要はありません。レイヤーパラメーターは、Pythonで文字列としてアクセス可能な文字列として定義できます。次に例を示します。レイヤーにパラメーターがある場合、prototxtファイルでparam_strが定義されていれば、 'self.param_str'を使用してそのパラメーターにアクセスできます。他のレイヤーと同様に、次の関数でクラスを定義する必要があります。
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で、下と上はそれぞれレイヤーの入力と出力の詳細です。 python_paramは、Python=レイヤーのパラメーターを定義します。「モジュール」は、レイヤーのファイル名を指定します。「anchor_target_layer.py」というファイルが「rpn」というフォルダー内にある場合'、パラメーターは' rpn.anchor_target_layer 'になります。'layer'パラメーターはクラスの名前、この場合は 'AnchorTargetLayer'です。'param_str 'はレイヤーのパラメーターで、キー「feat_stride」。
C++/CUDAレイヤーとは異なり、Pythonレイヤーは現在のところcaffeのマルチGPU設定では機能しないため、それらを使用することの欠点です。