[従来] Caffe Python レイヤーを使用したモデル・オプティマイザーの拡張¶
危険
ここで説明されているコードは非推奨になりました。従来のソリューションの適用を避けるため使用しないでください。下位互換性を確保するためにしばらく保持されますが、最新のアプリケーションでは使用してはなりません。
このガイドでは、非推奨である TensorFlow 変換方法について説明します。新しい推奨方法に関するガイドは、フロントエンド拡張に記載されています。
ここでは、Python のみで記述されたカスタム Caffe 操作をサポートする方法について説明します。例えば、Caffe に実装された Faster-R-CNN モデルには、Python で記述されたカスタム提案レイヤーが含まれています。このレイヤーは、Faster-R-CNN prototxt で次のように記述されます。
layer {
name: 'proposal'
type: 'Python'
bottom: 'rpn_cls_prob_reshape'
bottom: 'rpn_bbox_pred'
bottom: 'im_info'
top: 'rois'
python_param {
module: 'rpn.proposal_layer'
layer: 'ProposalLayer'
param_str: "'feat_stride': 16"
}
}
ここでは、モデル・オプティマイザーでオペレーターの属性を抽出する方法の手順のみを説明します。パイプラインを有効にする操作の残りと、他の Caffe 操作 (C++ で記述された) をサポートする方法については、モデル・オプティマイザーのカスタマイズ・ガイドで説明されています。
Caffe Python レイヤーのエクストラクターの作成¶
カスタム Caffe Python レイヤーには、Python
と等しい属性 type
(操作のタイプを定義) と、python_param
辞書内の 2 つの必須属性 module
および layer
があります。module
はレイヤー実装で Python モジュール名を定義しますが、layer
値はユーザーによって定義された操作タイプです。このような操作の属性を抽出するには、標準フレームワーク・レイヤーに使用される FrontExtractorOp
クラスの代わりに、CaffePythonFrontExtractorOp
クラスから継承したエクストラクター・クラスを実装する必要があります。op
クラスの属性値は module + "." + layer
に設定する必要があります。これにより、この種の操作に対してエクストラクターがトリガーされます。
以下は、前述の Faster-R-CNN モデルからのカスタム操作のエクストラクターの簡略化された例です。 追加チェックを含む完全なコードはここにあります。
サンプルコードでは、利用可能な操作セットページで説明されている Proposal
操作に対応する操作 ProposalOp
を使用します。エクストラクターの詳細な説明については、以下のソースコードを参照してください。
from openvino.tools.mo.ops.proposal import ProposalOp
from openvino.tools.mo.front.extractor import CaffePythonFrontExtractorOp
class ProposalPythonFrontExtractor(CaffePythonFrontExtractorOp):
op = 'rpn.proposal_layer.ProposalLayer' # module + "." + layer
enabled = True # extractor is enabled
@staticmethod
def extract_proposal_params(node, defaults):
param = node.pb.python_param # get the protobuf message representation of the layer attributes
# parse attributes from the layer protobuf message to a Python dictionary
attrs = CaffePythonFrontExtractorOp.parse_param_str(param.param_str)
update_attrs = defaults
# the operation expects ratio and scale values to be called "ratio" and "scale" while Caffe uses different names
if 'ratios' in attrs:
attrs['ratio'] = attrs['ratios']
del attrs['ratios']
if 'scales' in attrs:
attrs['scale'] = attrs['scales']
del attrs['scales']
update_attrs.update(attrs)
ProposalOp.update_node_stat(node, update_attrs) # update the node attributes
@classmethod
def extract(cls, node):
# define default values for the Proposal layer attributes
defaults = {
'feat_stride': 16,
'base_size': 16,
'min_size': 16,
'ratio': [0.5, 1, 2],
'scale': [8, 16, 32],
'pre_nms_topn': 6000,
'post_nms_topn': 300,
'nms_thresh': 0.7
}
cls.extract_proposal_params(node, defaults)
return cls.enabled