[従来] 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 # 抽出機能を有効にします 

    @staticmethod 
    def extract_proposal_params(node, defaults): 
        param = node.pb.python_param # レイヤー属性の protobuf メッセージ表現を取得 
        # レイヤーの protobuf メッセージから Python 辞書に属性を解析 
        attrs = CaffePythonFrontExtractorOp.parse_param_str(param.param_str) 
        update_attrs = defaults 

        # この操作では、比率とスケールの値が "ratio" と "scale" と呼ばれることを期待していますが、Caffe では異なる名前を使用 
        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) # ノード属性を更新 

    @classmethod 
    def extract(cls, node):         # 提案レイヤー属性のデフォルト値を定義 
            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

関連情報#