Skip to content
This repository was archived by the owner on Jan 13, 2024. It is now read-only.
Merged
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
567 changes: 567 additions & 0 deletions _doc/notebooks/numpy_api_onnx.ipynb

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions _doc/sphinxdoc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
epkg_dictionary.update({
'_PredictScorer': 'https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/metrics/scorer.py#L168',
'airspeed-velocity': 'https://github.com/airspeed-velocity/asv',
'ast': 'https://docs.python.org/3/library/ast.html',
'asv': 'https://github.com/airspeed-velocity/asv',
'bench1': 'http://www.xavierdupre.fr/app/mlprodict_bench/helpsphinx/index.html',
'bench2': 'http://www.xavierdupre.fr/app/mlprodict_bench2/helpsphinx/index.html',
Expand All @@ -73,6 +74,7 @@
'DOT': 'https://en.wikipedia.org/wiki/DOT_(graph_description_language)',
'einsum': 'https://numpy.org/doc/stable/reference/generated/numpy.einsum.html',
'exec': 'https://docs.python.org/3/library/functions.html#exec',
'FunctionTransformer': 'https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.FunctionTransformer.html',
'GaussianProcessRegressor': 'https://scikit-learn.org/stable/modules/generated/sklearn.gaussian_process.GaussianProcessRegressor.html',
'Iris': 'https://en.wikipedia.org/wiki/Iris_flower_data_set',
'IR_VERSION': 'https://github.com/onnx/onnx/blob/master/docs/IR.md#onnx-versioning',
Expand Down Expand Up @@ -105,6 +107,7 @@
'run_asv.sh': 'https://github.com/sdpython/mlprodict/blob/master/bin/run_asv.sh',
'Rust': 'https://www.rust-lang.org/',
'sklearn-onnx': 'https://github.com/onnx/sklearn-onnx',
'sklearn-onnx tutorial': 'http://www.xavierdupre.fr/app/onnxcustom/helpsphinx/tutorial.html',
'tensorflow': 'https://www.tensorflow.org/',
'Tokenizer': 'https://github.com/microsoft/onnxruntime/blob/master/docs/ContribOperators.md#com.microsoft.Tokenizer',
'tqdm': 'https://github.com/tqdm/tqdm',
Expand Down
2 changes: 2 additions & 0 deletions _doc/sphinxdoc/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ does not have any dependency on :epkg:`scikit-learn`.

.. runpython::
:showcode:
:warningout: DeprecationWarning

import numpy
from sklearn.linear_model import LinearRegression
Expand Down Expand Up @@ -157,6 +158,7 @@ predictions.

.. runpython::
:showcode:
:warningout: DeprecationWarning

from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
Expand Down
1 change: 1 addition & 0 deletions _doc/sphinxdoc/source/onnx.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ of modules below:

.. runpython::
:showcode:
:warningout: DeprecationWarning
:rst:

from mlprodict.onnxrt.validate.validate_helper import modules_list
Expand Down
2 changes: 2 additions & 0 deletions _doc/sphinxdoc/source/onnx_bench.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ of modules below:

.. runpython::
:showcode:
:warningout: DeprecationWarning
:rst:

from mlprodict.onnxrt.validate.validate_helper import modules_list
Expand Down Expand Up @@ -80,6 +81,7 @@ describes the list of considered problems.

.. runpython::
:showcode:
:warningout: DeprecationWarning
:rst:

from mlprodict.onnxrt.validate.validate import sklearn_operators, find_suitable_problem
Expand Down
1 change: 1 addition & 0 deletions _doc/sphinxdoc/source/onnx_conv.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ can be fully converted.

.. runpython::
:rst:
:warningout: DeprecationWarning
:showcode:

from mlprodict.onnx_conv.register import register_converters
Expand Down
9 changes: 5 additions & 4 deletions _doc/sphinxdoc/source/onnx_runtime.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Main class is :class:`OnnxInference

.. runpython::
:showcode:
:warningout: DeprecationWarning

import numpy
from sklearn.linear_model import LinearRegression
Expand Down Expand Up @@ -94,7 +95,7 @@ the cause of the error if it does not work.
.. runpython::
:showcode:
:rst:
:warningout: PendingDeprecationWarning UserWarning RuntimeWarning FutureWarning
:warningout: DeprecationWarning PendingDeprecationWarning UserWarning RuntimeWarning FutureWarning

from logging import getLogger
from pyquickhelper.loghelper import noLOG
Expand Down Expand Up @@ -142,7 +143,7 @@ intermediate node anymore.

.. runpython::
:showcode:
:warningout: FutureWarning
:warningout: FutureWarning DeprecationWarning

import numpy
from sklearn.ensemble import AdaBoostRegressor
Expand Down Expand Up @@ -171,7 +172,7 @@ We create a table similar to :ref:`l-onnx-pyrun-tbl`.
.. runpython::
:showcode:
:rst:
:warningout: PendingDeprecationWarning UserWarning RuntimeWarning
:warningout: DeprecationWarning PendingDeprecationWarning UserWarning RuntimeWarning

from logging import getLogger
from pyquickhelper.loghelper import noLOG
Expand Down Expand Up @@ -240,7 +241,7 @@ object to :epkg:`ONNX`. We create a table similar to
.. runpython::
:showcode:
:rst:
:warningout: PendingDeprecationWarning UserWarning RuntimeWarning
:warningout: DeprecationWarning PendingDeprecationWarning UserWarning RuntimeWarning

from logging import getLogger
from pyquickhelper.loghelper import noLOG
Expand Down
1 change: 1 addition & 0 deletions _doc/sphinxdoc/source/tutorial/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ one piece this module can do. More should follow.
:maxdepth: 1

onnx
onnx_numpy
optim
benchmark
125 changes: 7 additions & 118 deletions _doc/sphinxdoc/source/tutorial/onnx.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ to convert many :epkg:`scikit-learn` models.

.. runpython::
:showcode:
:warningout: DeprecationWarning

import numpy
from sklearn.datasets import load_iris
Expand All @@ -48,6 +49,7 @@ begin.

.. runpython::
:showcode:
:warningout: DeprecationWarning

import numpy
from sklearn.datasets import load_iris
Expand All @@ -74,6 +76,7 @@ The verbosity can be increased.

.. runpython::
:showcode:
:warningout: DeprecationWarning

import numpy
from sklearn.datasets import load_iris
Expand Down Expand Up @@ -103,6 +106,7 @@ can also call :epkg:`onnxruntime` to compute the predictions by using

.. runpython::
:showcode:
:warningout: DeprecationWarning

import numpy
from sklearn.datasets import load_iris
Expand All @@ -129,6 +133,7 @@ to look into intermediate results.

.. runpython::
:showcode:
:warningout: DeprecationWarning

import numpy
from sklearn.datasets import load_iris
Expand Down Expand Up @@ -157,6 +162,7 @@ As a consequence, interdiate results cannot be seen anymore.

.. runpython::
:showcode:
:warningout: DeprecationWarning

import numpy
from sklearn.datasets import load_iris
Expand Down Expand Up @@ -190,6 +196,7 @@ It works exactly the same:

.. runpython::
:showcode:
:warningout: DeprecationWarning

import numpy
from sklearn.datasets import load_iris
Expand All @@ -209,121 +216,3 @@ It works exactly the same:

oinf = OnnxInference(model_def, runtime='python')
print(oinf.run({'X': X_test[:5]}))

From ONNX to Python
+++++++++++++++++++

The Python Runtime can be optimized by generating
custom python code and dynamically compile it.
:class:`OnnxInference <mlprodict.onnxrt.OnnxInference>`
computes predictions based on an ONNX graph with a
python runtime or :epkg:`onnxruntime`.
Method :meth:`to_python
<mlprodict.onnxrt.onnx_inference_exports.OnnxInferenceExport.to_python>`
goes further by converting the ONNX graph into a standalone
python code.

.. _l-numpy2onnx-tutorial:

From numpy to ONNX
++++++++++++++++++

.. index:: algebric function

*mlprodict* implements function
:func:`translate_fct2onnx
<mlprodict.onnx_grammar.onnx_translation.translate_fct2onnx>`
which converts the code
of a function written with :epkg:`numpy` and :epkg:`scipy`
into an :epkg:`ONNX` graph.

The kernel *ExpSineSquared*
is used by :epkg:`sklearn:gaussian_process:GaussianProcessRegressor`
and its conversion is required to convert the model.
The first step is to write a standalone function which
relies on :epkg:`scipy` or :epkg:`numpy` and which produces
the same results. The second step calls this function to
produces the :epkg:`ONNX` graph.

.. runpython::
:showcode:
:process:
:store_in_file: fct2onnx_expsine.py

import numpy
from scipy.spatial.distance import squareform, pdist
from sklearn.gaussian_process.kernels import ExpSineSquared
from mlprodict.onnx_grammar import translate_fct2onnx
from mlprodict.onnx_grammar.onnx_translation import squareform_pdist, py_make_float_array
from mlprodict.onnxrt import OnnxInference

# The function to convert into ONNX.
def kernel_call_ynone(X, length_scale=1.2, periodicity=1.1, pi=3.141592653589793):

# squareform(pdist(X, ...)) in one function.
dists = squareform_pdist(X, metric='euclidean')

# Function starting with 'py_' --> must not be converted into ONNX.
t_pi = py_make_float_array(pi)
t_periodicity = py_make_float_array(periodicity)

# This operator must be converted into ONNX.
arg = dists / t_periodicity * t_pi
sin_of_arg = numpy.sin(arg)

t_2 = py_make_float_array(2)
t__2 = py_make_float_array(-2)

t_length_scale = py_make_float_array(length_scale)

K = numpy.exp((sin_of_arg / t_length_scale) ** t_2 * t__2)
return K

# This function is equivalent to the following kernel.
kernel = ExpSineSquared(length_scale=1.2, periodicity=1.1)

x = numpy.array([[1, 2], [3, 4]], dtype=float)

# Checks that the new function and the kernel are the same.
exp = kernel(x, None)
got = kernel_call_ynone(x)

print("ExpSineSquared:")
print(exp)
print("numpy function:")
print(got)

# Converts the numpy function into an ONNX function.
fct_onnx = translate_fct2onnx(kernel_call_ynone, cpl=True,
output_names=['Z'])

# Calls the ONNX function to produce the ONNX algebric function.
# See below.
onnx_model = fct_onnx('X')

# Calls the ONNX algebric function to produce the ONNX graph.
inputs = {'X': x.astype(numpy.float32)}
onnx_g = onnx_model.to_onnx(inputs, target_opset=12)

# Creates a python runtime associated to the ONNX function.
oinf = OnnxInference(onnx_g)

# Compute the prediction with the python runtime.
res = oinf.run(inputs)
print("ONNX output:")
print(res['Z'])

# Displays the code of the algebric function.
print('-------------')
print("Function code:")
print('-------------')
print(translate_fct2onnx(kernel_call_ynone, output_names=['Z']))

The output of function
:func:`translate_fct2onnx
<mlprodict.onnx_grammar.onnx_translation.translate_fct2onnx>`
is not an :epkg:`ONNX` graph but the code of a function which
produces an :epkg:`ONNX` graph. That's why the function is called
twice. The first call compiles the code and a returns a new
:epkg:`python` function. The second call starts all over but
returns the code instead of its compiled version.
Loading