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

Revise Transformation docs: python API #26008

Merged
95 changes: 95 additions & 0 deletions docs/articles_en/assets/snippets/ov_matcher_pass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# ! [matcher_pass:ov_matcher_pass_py]
'''
``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.
'''

from openvino.runtime.passes import MatcherPass
from snippets import get_model

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)


'''
After running this code you will see the next:

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.
'''
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 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_model()
print_model_ops(model)
manager.run_passes(model)
print_model_ops(model)

# ! [matcher_pass:ov_matcher_pass_py]
47 changes: 47 additions & 0 deletions docs/articles_en/assets/snippets/ov_model_pass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# ! [model_pass:ov_model_pass_py]

'''
``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
'''

from openvino.runtime.passes import ModelPass
from snippets import get_model

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())


'''
In this example we define transformation that prints all model operation names.
The next example shows ModelPass-based transformation usage.
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.
'''

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 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_model())
# ! [model_pass:ov_model_pass_py]
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,21 @@ Template for MatcherPass transformation class
:language: cpp
:fragment: [graph_rewrite:template_transformation_hpp]

.. doxygensnippet:: docs/articles_en/assets/snippets/template_pattern_transformation.cpp
:language: cpp
:fragment: [graph_rewrite:template_transformation_cpp]
.. tab-set::

.. tab-item:: C++
:sync: cpp

.. doxygensnippet:: docs/articles_en/assets/snippets/template_pattern_transformation.cpp
:language: cpp
:fragment: [graph_rewrite:template_transformation_cpp]

.. tab-item:: Python
:sync: py

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

To use ``ov::pass::MatcherPass``, you need to complete these steps:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,21 @@ Template for ModelPass transformation class
:language: cpp
:fragment: [model_pass:template_transformation_hpp]

.. doxygensnippet:: docs/articles_en/assets/snippets/template_model_transformation.cpp
:language: cpp
:fragment: [model_pass:template_transformation_cpp]
.. tab-set::

.. tab-item:: C++
:sync: cpp

.. doxygensnippet:: docs/articles_en/assets/snippets/template_model_transformation.cpp
:language: cpp
:fragment: [model_pass:template_transformation_cpp]

.. tab-item:: Python
:sync: py

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

Using ``ov::pass::ModelPass``, you need to override the ``run_on_model`` method where you will write the transformation code.
Return value is ``true`` if the original model has changed during transformation (new operation was added, or operations replacement was made, or node attributes were changed); otherwise, it is ``false``.
Expand Down
Loading