.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples_proto/plot_translate.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_proto_plot_translate.py: .. _l-example-plot-translate: translate: turn an ONNX model back into Python code ==================================================== :func:`~onnx_light.tools.translate` converts an existing ``ModelProto`` (or ``GraphProto``) into Python code that rebuilds an equivalent model. Two *flavours* are available: * ``api="onnx-compact"`` — a single nested :mod:`onnx_light.onnx.helper` expression (``oh.make_model(oh.make_graph([...], ...))``). * ``api="builder"`` — an incremental script driving the :class:`~onnx_light.onnx_core.graph_builder.GraphBuilder` (``g.inp(...)``, ``g.init(...)``, ``g.op.(...)``, ``g.out(...)``, ``g.to_onnx(...)``). * ``api="cpp"`` — a C++ function that rebuilds the model with :cpp:class:`~onnx_light::core::builder::GraphBuilder`. :func:`~onnx_light.tools.translate_header` returns the matching import header, so ``translate_header(api) + translate(model, api)`` is a fully runnable Python snippet. The example below builds a small model, prints both flavours and then executes the generated code to rebuild the model. .. GENERATED FROM PYTHON SOURCE LINES 26-43 .. code-block:: Python # sphinx_gallery_thumbnail_path = "_static/gallery_thumbnails/translate.png" from __future__ import annotations import numpy as np import onnx_light.onnx as onnx import onnx_light.onnx.defs as defs import onnx_light.onnx.helper as oh import onnx_light.onnx.numpy_helper as onh from onnx_light.tools import translate, translate_header # Built-in operator schemas are registered so the rebuilt models validate. defs.register_onnx_operator_set_schema() .. GENERATED FROM PYTHON SOURCE LINES 44-49 Build the model +++++++++++++++ A tiny graph ``Y = Add(Mul(X, W), B)`` with two initializers so the translation exercises nodes, inputs/outputs and initializers. .. GENERATED FROM PYTHON SOURCE LINES 49-66 .. code-block:: Python model = oh.make_model( oh.make_graph( [oh.make_node("Mul", ["X", "W"], ["XW"]), oh.make_node("Add", ["XW", "B"], ["Y"])], "linear", [oh.make_tensor_value_info("X", onnx.TensorProto.FLOAT, ["N", 3])], [oh.make_tensor_value_info("Y", onnx.TensorProto.FLOAT, ["N", 3])], [ onh.from_array(np.array([1.0, 2.0, 3.0], dtype=np.float32), name="W"), onh.from_array(np.array([0.5, 0.5, 0.5], dtype=np.float32), name="B"), ], ), opset_imports=[oh.make_opsetid("", 18)], ir_version=8, ) .. GENERATED FROM PYTHON SOURCE LINES 67-73 onnx-compact flavour ++++++++++++++++++++ ``translate_header("onnx-compact")`` returns the imports and ``translate(model, api="onnx-compact")`` the nested ``oh.make_model`` expression. .. GENERATED FROM PYTHON SOURCE LINES 73-79 .. code-block:: Python compact_code = translate_header("onnx-compact") + translate(model, api="onnx-compact") print("=== onnx-compact ===") print(compact_code) .. rst-class:: sphx-glr-script-out .. code-block:: none === onnx-compact === import numpy as np import ml_dtypes import onnx_light.onnx as onnx import onnx_light.onnx.helper as oh import onnx_light.onnx.numpy_helper as onh model = oh.make_model( oh.make_graph( [ oh.make_node('Mul', ['X', 'W'], ['XW']), oh.make_node('Add', ['XW', 'B'], ['Y']), ], 'linear', [ oh.make_tensor_value_info('X', onnx.TensorProto.FLOAT, ('N', 3)), ], [ oh.make_tensor_value_info('Y', onnx.TensorProto.FLOAT, ('N', 3)), ], [ onh.from_array(np.array([1.0, 2.0, 3.0], dtype=np.float32), name='W'), onh.from_array(np.array([0.5, 0.5, 0.5], dtype=np.float32), name='B'), ], ), opset_imports=[oh.make_opsetid('', 18)], ir_version=8, ) .. GENERATED FROM PYTHON SOURCE LINES 80-86 builder flavour +++++++++++++++ The ``builder`` flavour rebuilds the same model step by step with the compact :class:`~onnx_light.onnx_core.graph_builder.GraphBuilder` API (``g.inp``, ``g.init``, ``g.op`` and ``g.out``). .. GENERATED FROM PYTHON SOURCE LINES 86-92 .. code-block:: Python builder_code = translate_header("builder") + translate(model, api="builder") print("\n=== builder ===") print(builder_code) .. rst-class:: sphx-glr-script-out .. code-block:: none === builder === import numpy as np import ml_dtypes import onnx_light.onnx as onnx import onnx_light.onnx.helper as oh import onnx_light.onnx.numpy_helper as onh from onnx_light.onnx_core.graph_builder import GraphBuilder g = GraphBuilder('linear') g.set_opset_version('', 18) g.inp('X', onnx.TensorProto.FLOAT, ('N', 3)) g.init(np.array([1.0, 2.0, 3.0], dtype=np.float32), name='W') g.init(np.array([0.5, 0.5, 0.5], dtype=np.float32), name='B') g.op.Mul('X', 'W', outputs=['XW']) g.op.Add('XW', 'B', outputs=['Y']) g.out('Y', onnx.TensorProto.FLOAT, ('N', 3)) model = g.to_onnx('model', ir_version=8) .. GENERATED FROM PYTHON SOURCE LINES 93-98 C++ flavour +++++++++++ The ``cpp`` flavour emits a standalone ``BuildModel`` function using the native :cpp:class:`~onnx_light::core::builder::GraphBuilder`. .. GENERATED FROM PYTHON SOURCE LINES 98-104 .. code-block:: Python cpp_code = translate_header("cpp") + translate(model, api="cpp") print("\n=== cpp ===") print(cpp_code) .. rst-class:: sphx-glr-script-out .. code-block:: none === cpp === #include "onnx_core/builder/graph_builder.h" #include "onnx_op/operator_sets.h" #include #include #include namespace onnx_light = ONNX_LIGHT_NAMESPACE; onnx_light::ModelProto BuildModel() { onnx_light::core::builder::GraphBuilder g( "linear", [](const std::string &op_type) { return onnx_light::onnx_op::GetAllOnnxOpSchemasWithHistory(op_type, false); }); g.SetOpsetVersion("", 18); g.MakeInput("X", onnx_light::core::symbolic::TensorType::kFloat, onnx_light::core::symbolic::SymShape{onnx_light::core::symbolic::SymDim('N'), onnx_light::core::symbolic::SymDim(3)}); onnx_light::TensorProto initializer_0; initializer_0.set_name("W"); initializer_0.set_data_type(onnx_light::TensorProto::DataType::FLOAT); initializer_0.add_dims(3); initializer_0.set_raw_data(std::string({static_cast(static_cast(0)), static_cast(static_cast(0)), static_cast(static_cast(128)), static_cast(static_cast(63)), static_cast(static_cast(0)), static_cast(static_cast(0)), static_cast(static_cast(0)), static_cast(static_cast(64)), static_cast(static_cast(0)), static_cast(static_cast(0)), static_cast(static_cast(64)), static_cast(static_cast(64))})); g.MakeInitializer(initializer_0); onnx_light::TensorProto initializer_1; initializer_1.set_name("B"); initializer_1.set_data_type(onnx_light::TensorProto::DataType::FLOAT); initializer_1.add_dims(3); initializer_1.set_raw_data(std::string({static_cast(static_cast(0)), static_cast(static_cast(0)), static_cast(static_cast(0)), static_cast(static_cast(63)), static_cast(static_cast(0)), static_cast(static_cast(0)), static_cast(static_cast(0)), static_cast(static_cast(63)), static_cast(static_cast(0)), static_cast(static_cast(0)), static_cast(static_cast(0)), static_cast(static_cast(63))})); g.MakeInitializer(initializer_1); g.MakeNode("Mul", {"X", "W"}, {"XW"}); g.MakeNode("Add", {"XW", "B"}, {"Y"}); g.MakeOutput("Y", onnx_light::core::symbolic::TensorType::kFloat, onnx_light::core::symbolic::SymShape{onnx_light::core::symbolic::SymDim('N'), onnx_light::core::symbolic::SymDim(3)}); return g.ToModel(8); } .. GENERATED FROM PYTHON SOURCE LINES 105-111 Round-trip ++++++++++ The generated code is plain Python: executing it rebuilds an equivalent model. Here we run the ``builder`` snippet and check that the rebuilt graph has the same nodes as the original. .. GENERATED FROM PYTHON SOURCE LINES 111-122 .. code-block:: Python namespace: dict = {} exec(builder_code, namespace) # noqa: S102 rebuilt = namespace["model"] original_ops = [node.op_type for node in model.graph.node] rebuilt_ops = [node.op_type for node in rebuilt.graph.node] print("\n=== round-trip ===") print("original ops:", original_ops) print("rebuilt ops :", rebuilt_ops) assert original_ops == rebuilt_ops .. rst-class:: sphx-glr-script-out .. code-block:: none === round-trip === original ops: ['Mul', 'Add'] rebuilt ops : ['Mul', 'Add'] .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.011 seconds) .. _sphx_glr_download_auto_examples_proto_plot_translate.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_translate.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_translate.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_translate.zip ` .. include:: plot_translate.recommendations .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_