OpenVINO™ ランタイムのモデル表現¶
OpenVINO™ ランタイムでは、モデルは ov::Model
クラスによって表されます。
ov::Model
オブジェクトは、入力、出力、グラフのシンクである ov::op::v0::Parameter
、ov::op::v0::Result
、および ov::op::Sink
操作への共有ポインターを格納します。グラフのシンクにはコンシューマーがなく、結果ベクトルには含まれません。他のすべての操作は共有ポインターを介して相互に保持され、子操作はハードリンクによって親を保持します。操作にコンシューマーがなく、共有ポインターカウンターが 0 である Result
操作でも Sink
操作でもない場合、操作は破棄されてアクセスできなくなります。
ov::Model
の各操作には std::shared_ptr<ov::Node>
タイプがあります。
OpenVINO ランタイムがモデルでどのように動作するか¶
OpenVINO™ ランタイムを使用すると、さまざまなアプローチによりモデルの入力/出力を操作できます。
ov::Model::inputs()
/ov::Model::outputs()
メソッドは、すべての入出力ポートのベクトルを取得するために使用されます。入力または出力が 1 つだけのモデルでは、引数なしで
ov::Model::input()
メソッドまたはov::Model::output()
メソッドを使用して、入力ポートまたは出力ポートをそれぞれ取得できます。ov::Model::input()
メソッドとov::Model::output()
メソッドをフレームワーク・モデルからの入力または出力のインデックスとともに使用して、インデックスによって特定のポートを取得できます。元のフレームワーク・モデルからの入力または出力のテンソル名を
ov::Model::input()
メソッドまたはov::Model::output()
メソッドとともに使用して、特定のポートを取得できます。これは、以前のように、フレームワークから OpenVINO への名前による追加のマッピングが必要ないことを意味します。OpenVINO ランタイムでは、次のようなネイティブ・フレームワーク・テンソル名が許可されます。
inputs = model.inputs
outputs = model.outputs
/* Take information about all topology inputs */
auto inputs = model->inputs();
/* Take information about all topology outputs */
auto outputs = model->outputs();
OpenVINO™ ランタイムでモデルを構築する方法の詳細については、OpenVINO ランタイムでモデルをビルドを参照してください。
OpenVINO™ ランタイムのモデル表現は、特別なクラスを使用してモデルのデータタイプと形状を操作します。ov::element::Type
はデータタイプに使用されます。形状の表現は、下記を参照してください。
形状の表現¶¶
OpenVINO™ ランタイムは、形状表現に 2 つのタイプを提供します。
ov::Shape
- 静的な (完全に定義された) 形状を表現します。ov::PartialShape
- 動的な形状を表現します。これは、ランクまたは一部の次元が動的であることを意味します (次元は間隔を定義するか未定義です)。
ov::PartialShape
は、すべての次元が静的である場合、get_shape()
メソッドを使用して ov::Shape
に変換できます。それ以外は、変換で例外がスローされます。
例:
partial_shape = node.output(0).get_partial_shape() # get zero output partial shape
if not partial_shape.is_dynamic: # or partial_shape.is_static
static_shape = partial_shape.get_shape()
ov::Shape static_shape;
ov::PartialShape partial_shape = node->output(0).get_partial_shape(); // get zero output partial shape
if (!partial_shape.is_dynamic() /* or partial_shape.is_static() */) {
static_shape = partial_shape.get_shape();
}
ただし、ほとんどの場合、get_shape()
メソッドで静的な形状を取得する前に、その形状が静的であるかどうか確認する必要があります。
操作セットの表現¶
操作セット (opset) は、モデルの構築に使用できる操作のコレクションです。ov::OpSet
クラスは、操作セットを操作する機能を提供します。OpenVINO™ ランタイムは、操作セットごとに、opset8
など個別の名前空間を提供します。
OpenVINO™ の各リリースでは、新しい操作が導入され、新しい操作セットに追加されます。新しい操作によって以前の操作の動作が変更されます。操作セットを使用すると、新しい操作が導入されたときにアプリケーションを変更する必要はありません。OpenVINO™ ツールキットでサポートされている操作セットの完全なリストについては、利用可能な操作セットを参照してください。カスタム操作のサポートを追加するには、OpenVINO 拡張メカニズムを参照してください。
OpenVINO™ ランタイムでモデルをビルド¶
ソースからモデルを作成できます。このセクションでは、利用可能な操作セットから操作で構成されるモデルを構築する方法を説明します。
操作セット opsetX
は、この目的のため機能する事前コンパイルされた操作のリストを統合します。言い換えれば、opsetX
はグラフを構築する一連の操作を定義します。
opset8
操作から ov::Model
インスタンスを構築するには、次のファイルをインクルードします。
import openvino as ov
#include <openvino/core/model.hpp>
#include <openvino/opsets/opset8.hpp>
次のコードは、単純なモデルを作成する方法を示します。
def create_simple_model():
# This example shows how to create ov::Function
#
# Parameter--->Multiply--->Add--->Result
# Constant---' /
# Constant---'
data = ops.parameter([3, 1, 2], ov.Type.f32)
mul_constant = ops.constant([1.5], ov.Type.f32)
mul = ops.multiply(data, mul_constant)
add_constant = ops.constant([0.5], ov.Type.f32)
add = ops.add(mul, add_constant)
res = ops.result(add)
return ov.Model([res], [data], "model")
std::shared_ptr<ov::Model> create_simple_model() {
// This example shows how to create ov::Model
//
// Parameter--->Multiply--->Add--->Result
// Constant---' /
// Constant---'
// Create opset8::Parameter operation with static shape
auto data = std::make_shared<ov::opset8::Parameter>(ov::element::f32, ov::Shape{3, 1, 2});
auto mul_constant = ov::opset8::Constant::create(ov::element::f32, ov::Shape{1}, {1.5});
auto mul = std::make_shared<ov::opset8::Multiply>(data, mul_constant);
auto add_constant = ov::opset8::Constant::create(ov::element::f32, ov::Shape{1}, {0.5});
auto add = std::make_shared<ov::opset8::Add>(mul, add_constant);
// Create opset8::Result operation
auto res = std::make_shared<ov::opset8::Result>(mul);
// Create OpenVINO function
return std::make_shared<ov::Model>(ov::ResultVector{res}, ov::ParameterVector{data});
}
次のコードは、複数の出力を持つモデルを作成します。
def create_advanced_model():
# Advanced example with multi output operation
#
# Parameter->Split---0-->Result
# | `--1-->Relu-->Result
# `----2-->Result
data = ops.parameter(ov.Shape([1, 3, 64, 64]), ov.Type.f32)
# Create Constant for axis value
axis_const = ops.constant(1, dtype=ov.Type.i64)
# Create opset12::Split operation that splits input to three slices across 1st dimension
split = ops.split(data, axis_const, 3)
# Create opset12::Relu operation that takes 1st Split output as input
relu = ops.relu(split.output(1))
# Results operations will be created automatically based on provided OutputVector
return ov.Model([split.output(0), relu.output(0), split.output(2)], [data], "model")
std::shared_ptr<ov::Model> create_advanced_model() {
// Advanced example with multi output operation
//
// Parameter->Split---0-->Result
// | `--1-->Relu-->Result
// `----2-->Result
auto data = std::make_shared<ov::opset8::Parameter>(ov::element::f32, ov::Shape{1, 3, 64, 64});
// Create Constant for axis value
auto axis_const = ov::opset8::Constant::create(ov::element::i64, ov::Shape{} /*scalar shape*/, {1});
// Create opset8::Split operation that splits input to three slices across 1st dimension
auto split = std::make_shared<ov::opset8::Split>(data, axis_const, 3);
// Create opset8::Relu operation that takes 1st Split output as input
auto relu = std::make_shared<ov::opset8::Relu>(split->output(1) /*specify explicit output*/);
// Results operations will be created automatically based on provided OutputVector
return std::make_shared<ov::Model>(ov::OutputVector{split->output(0), relu, split->output(2)},
ov::ParameterVector{data});
}
モデルのデバッグ機能¶
OpenVINO™ はいくつかのデバッグ機能を提供します。
適用されたモデルの変更に関する追加メッセージを受信するには、
-DENABLE_OPENVINO_DEBUG=ON
オプションを使用して OpenVINO™ ランタイム・ライブラリーを再ビルドします。モデルは xDot 形式の画像に視覚化できます。
def visualize_example(m : ov.Model):
# Need import:
# * import openvino.runtime.passes as passes
pass_manager = passes.Manager()
pass_manager.register_pass(passes.VisualizeTree(file_name='image.svg'))
pass_manager.run_passes(m)
void visualize_example(const std::shared_ptr<ov::Model>& m) {
// Need include:
// * openvino/pass/manager.hpp
// * openvino/pass/visualize_tree.hpp
ov::pass::Manager manager;
// Serialize ov::Model to before.svg file before transformation
manager.register_pass<ov::pass::VisualizeTree>("image.svg");
manager.run_passes(m);
}
`ov::pass::VisualizeTree` can be parametrized via environment variables:
OV_VISUALIZE_TREE_OUTPUT_SHAPES=1 - visualize shapes
OV_VISUALIZE_TREE_OUTPUT_TYPES=1 - visualize types
OV_VISUALIZE_TREE_MIN_MAX_DENORMAL=1 - pretty denormal values
OV_VISUALIZE_TREE_RUNTIME_INFO=1 - print runtime information
OV_VISUALIZE_TREE_IO=1 - print I/O ports
OV_VISUALIZE_TREE_MEMBERS_NAME=1 - print member names
モデルを IR にシリアル化することもできます。
def serialize_example(m : ov.Model):
ov.serialize(m, xml_path='model.xml', bin_path='model.bin')
void serialize_example(const std::shared_ptr<ov::Model>& model) {
ov::serialize(model, "/path/to/file/model.xml", "/path/to/file/model.bin");
}