Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transformations documentation add python API MatcherPass and ModelPass #24058

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.. {#openvino_docs_Extensibility_UG_matcher_pass}

OpenVINO Model Pass Python API
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need a separate page for Python API
I believe it's better to update C++ page with these python examples

==============================


.. meta::
:description: Learn how to create a pattern, implement a callback, register
the pattern and Matcher to execute MatcherPass transformation
on a model.

``MatcherPass`` is used for pattern-based transformations.
To create transformation you need:

1. Create a pattern
2. Implement a callback
3. Register the pattern and Matcher

In the next example we define transformation that searches for ``Relu`` layer and inserts after it another
``Relu`` layer.

.. doxygensnippet:: docs/snippets/ov_matcher_pass.py
:language: py
:fragment: [matcher_pass:ov_matcher_pass_py]

The next example shows MatcherPass-based transformation usage.

.. doxygensnippet:: docs/snippets/ov_matcher_pass.py
:language: py
:fragment: [matcher_pass_full_example:ov_matcher_pass_py]

After running this code you will see the next: text
```
model ops :
parameter
result
relu

model ops :
parameter
result
relu
new_relu
```

In oder to run this script you need to export PYTHONPATH as the path to binary OpenVINO python models.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.. {#openvino_docs_Extensibility_UG_model_pass}

OpenVINO Model Pass Python API
==============================


.. meta::
:description: Learn how to use Model Pass transformation class to take entire
ov::Model as input and process it.

``ModelPass`` can be used as base class for transformation classes that take entire ``Model`` and proceed it.
To create transformation you need:

1. Define class with ``ModelPass`` as a parent
2. Redefine run_on_model method that will receive ``Model`` as an argument

.. doxygensnippet:: docs/snippets/ov_model_pass.py
:language: py
:fragment: [model_pass:ov_model_pass_py]

In this example we define transformation that prints all model operation names.

The next example shows ModelPass-based transformation usage.

.. doxygensnippet:: docs/snippets/ov_model_pass.py
:language: py
:fragment: [model_pass_full_example:ov_model_pass_py]

We create Model with Relu, Parameter and Result nodes. After running this code you will see names of these three nodes.
In oder to run this script you need to export PYTHONPATH as the path to binary OpenVINO python models.
40 changes: 40 additions & 0 deletions docs/snippets/ov_model_pass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// ! [model_pass:ov_model_pass_py]
from openvino.runtime.passes import ModelPass

class MyModelPass(ModelPass):
def __init__(self):
super().__init__()

def run_on_model(self, model):
for op in model.get_ops():
print(op.get_friendly_name())
// ! [model_pass:ov_model_pass_py]

// ! [model_pass_full_example:ov_model_pass_py]
from openvino.runtime.passes import Manager, GraphRewrite, BackwardGraphRewrite, Serialize
from openvino import Model, PartialShape
from openvino.runtime import opset13 as ops
from openvino.runtime.passes import ModelPass, Matcher, MatcherPass, WrapType


def get_relu_model():
# Parameter->Relu->Result
param = ops.parameter(PartialShape([1, 3, 22, 22]), name="parameter")
relu = ops.relu(param.output(0))
res = ops.result(relu.output(0), name="result")
return Model([res], [param], "test")


class MyModelPass(ModelPass):
def __init__(self):
super().__init__()

def run_on_model(self, model):
for op in model.get_ops():
print(op.get_friendly_name())


manager = Manager()
manager.register_pass(MyModelPass())
manager.run_passes(get_relu_model())
// ! [model_pass_full_example:ov_model_pass_py]
76 changes: 76 additions & 0 deletions docs/snippets/src/ov_matcher_pass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// ! [matcher_pass:ov_matcher_pass_py]
from openvino.runtime.passes import MatcherPass

class PatternReplacement(MatcherPass):
def __init__(self):
MatcherPass.__init__(self)
relu = WrapType("opset13::Relu")

def callback(matcher: Matcher) -> bool:
root = matcher.get_match_root()
new_relu = ops.relu(root.input(0).get_source_output())

"""Use new operation for additional matching
self.register_new_node(new_relu)

Input->Relu->Result => Input->Relu->Relu->Result
"""
root.input(0).replace_source_output(new_relu.output(0))
return True

self.register_matcher(Matcher(relu, "PatternReplacement"), callback)
// ! [matcher_pass:ov_matcher_pass_py]

// ! [matcher_pass_full_example:ov_matcher_pass_py]
from openvino.runtime.passes import Manager, GraphRewrite, BackwardGraphRewrite, Serialize
from openvino import Model, PartialShape
from openvino.runtime import opset13 as ops
from openvino.runtime.passes import ModelPass, Matcher, MatcherPass, WrapType

class PatternReplacement(MatcherPass):
def __init__(self):
MatcherPass.__init__(self)
relu = WrapType("opset13::Relu")

def callback(matcher: Matcher) -> bool:
root = matcher.get_match_root()
new_relu = ops.relu(root.input(0).get_source_output())
new_relu.set_friendly_name('new_relu')

"""Use new operation for additional matching
self.register_new_node(new_relu)

Input->Relu->Result => Input->Relu->Relu->Result
"""
root.input(0).replace_source_output(new_relu.output(0))
return True

self.register_matcher(Matcher(relu, "PatternReplacement"), callback)


def get_relu_model():
# Parameter->Relu->Result
param = ops.parameter(PartialShape([1, 3, 22, 22]), name="parameter")
relu = ops.relu(param.output(0))
relu.set_friendly_name('relu')
res = ops.result(relu.output(0), name="result")
return Model([res], [param], "test")


def print_model_ops(model):
print('model ops : ')
for op in model.get_ops():
print(op.get_friendly_name())
print('')


manager = Manager()
manager.register_pass(PatternReplacement())


model = get_relu_model()
print_model_ops(model)
manager.run_passes(model)
print_model_ops(model)

// ! [matcher_pass_full_example:ov_matcher_pass_py]
Loading