onnxruntime/python/_sources/auto_examples/plot_train_convert_predict.rst.txt

520 lines
10 KiB
Text
Raw Normal View History

.. note::
:class: sphx-glr-download-link-note
Click :ref:`here <sphx_glr_download_auto_examples_plot_train_convert_predict.py>` to download the full example code
.. rst-class:: sphx-glr-example-title
.. _sphx_glr_auto_examples_plot_train_convert_predict.py:
.. _l-logreg-example:
Train, convert and predict with ONNX Runtime
============================================
This example demonstrates an end to end scenario
starting with the training of a machine learned model
to its use in its converted from.
.. contents::
:local:
Train a logistic regression
+++++++++++++++++++++++++++
The first step consists in retrieving the iris datset.
.. code-block:: python
from sklearn.datasets import load_iris
iris = load_iris()
X, y = iris.data, iris.target
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y)
Then we fit a model.
.. code-block:: python
from sklearn.linear_model import LogisticRegression
clr = LogisticRegression()
clr.fit(X_train, y_train)
We compute the prediction on the test set
and we show the confusion matrix.
.. code-block:: python
from sklearn.metrics import confusion_matrix
pred = clr.predict(X_test)
print(confusion_matrix(y_test, pred))
.. rst-class:: sphx-glr-script-out
Out:
.. code-block:: none
[[ 9 0 0]
[ 0 15 1]
[ 0 1 12]]
Conversion to ONNX format
+++++++++++++++++++++++++
We use module
`sklearn-onnx <https://github.com/onnx/sklearn-onnx>`_
to convert the model into ONNX format.
.. code-block:: python
from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType
initial_type = [('float_input', FloatTensorType([None, 4]))]
onx = convert_sklearn(clr, initial_types=initial_type)
with open("logreg_iris.onnx", "wb") as f:
f.write(onx.SerializeToString())
We load the model with ONNX Runtime and look at
its input and output.
.. code-block:: python
import onnxruntime as rt
sess = rt.InferenceSession("logreg_iris.onnx")
print("input name='{}' and shape={}".format(
sess.get_inputs()[0].name, sess.get_inputs()[0].shape))
print("output name='{}' and shape={}".format(
sess.get_outputs()[0].name, sess.get_outputs()[0].shape))
.. rst-class:: sphx-glr-script-out
Out:
.. code-block:: none
input name='float_input' and shape=[None, 4]
output name='output_label' and shape=[1]
We compute the predictions.
.. code-block:: python
input_name = sess.get_inputs()[0].name
label_name = sess.get_outputs()[0].name
import numpy
pred_onx = sess.run([label_name], {input_name: X_test.astype(numpy.float32)})[0]
print(confusion_matrix(pred, pred_onx))
.. rst-class:: sphx-glr-script-out
Out:
.. code-block:: none
[[ 9 0 0]
[ 0 16 0]
[ 0 0 13]]
The prediction are perfectly identical.
Probabilities
+++++++++++++
Probabilities are needed to compute other
relevant metrics such as the ROC Curve.
Let's see how to get them first with
scikit-learn.
.. code-block:: python
prob_sklearn = clr.predict_proba(X_test)
print(prob_sklearn[:3])
.. rst-class:: sphx-glr-script-out
Out:
.. code-block:: none
[[0.00198628 0.71308408 0.28492964]
[0.00481246 0.83770353 0.15748401]
[0.00483108 0.75930899 0.23585993]]
And then with ONNX Runtime.
The probabilies appear to be
.. code-block:: python
prob_name = sess.get_outputs()[1].name
prob_rt = sess.run([prob_name], {input_name: X_test.astype(numpy.float32)})[0]
import pprint
pprint.pprint(prob_rt[0:3])
.. rst-class:: sphx-glr-script-out
Out:
.. code-block:: none
[{0: 0.0019862803164869547, 1: 0.7130840420722961, 2: 0.28492966294288635},
{0: 0.0048124659806489944, 1: 0.8377037048339844, 2: 0.15748386085033417},
{0: 0.004831086378544569, 1: 0.7593092322349548, 2: 0.23585963249206543}]
Let's benchmark.
.. code-block:: python
from timeit import Timer
def speed(inst, number=10, repeat=20):
timer = Timer(inst, globals=globals())
raw = numpy.array(timer.repeat(repeat, number=number))
ave = raw.sum() / len(raw) / number
mi, ma = raw.min() / number, raw.max() / number
print("Average %1.3g min=%1.3g max=%1.3g" % (ave, mi, ma))
return ave
print("Execution time for clr.predict")
speed("clr.predict(X_test)")
print("Execution time for ONNX Runtime")
speed("sess.run([label_name], {input_name: X_test.astype(numpy.float32)})[0]")
.. rst-class:: sphx-glr-script-out
Out:
.. code-block:: none
Execution time for clr.predict
Average 4.8e-05 min=4.63e-05 max=5.71e-05
Execution time for ONNX Runtime
Average 3.19e-05 min=3.08e-05 max=3.81e-05
Let's benchmark a scenario similar to what a webservice
experiences: the model has to do one prediction at a time
as opposed to a batch of prediction.
.. code-block:: python
def loop(X_test, fct, n=None):
nrow = X_test.shape[0]
if n is None:
n = nrow
for i in range(0, n):
im = i % nrow
fct(X_test[im: im+1])
print("Execution time for clr.predict")
speed("loop(X_test, clr.predict, 100)")
def sess_predict(x):
return sess.run([label_name], {input_name: x.astype(numpy.float32)})[0]
print("Execution time for sess_predict")
speed("loop(X_test, sess_predict, 100)")
.. rst-class:: sphx-glr-script-out
Out:
.. code-block:: none
Execution time for clr.predict
Average 0.00445 min=0.00423 max=0.00495
Execution time for sess_predict
Average 0.00151 min=0.00145 max=0.00164
Let's do the same for the probabilities.
.. code-block:: python
print("Execution time for predict_proba")
speed("loop(X_test, clr.predict_proba, 100)")
def sess_predict_proba(x):
return sess.run([prob_name], {input_name: x.astype(numpy.float32)})[0]
print("Execution time for sess_predict_proba")
speed("loop(X_test, sess_predict_proba, 100)")
.. rst-class:: sphx-glr-script-out
Out:
.. code-block:: none
Execution time for predict_proba
Average 0.00643 min=0.00632 max=0.00666
Execution time for sess_predict_proba
Average 0.00158 min=0.00152 max=0.00177
This second comparison is better as
ONNX Runtime, in this experience,
computes the label and the probabilities
in every case.
Benchmark with RandomForest
+++++++++++++++++++++++++++
We first train and save a model in ONNX format.
.. code-block:: python
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier()
rf.fit(X_train, y_train)
initial_type = [('float_input', FloatTensorType([1, 4]))]
onx = convert_sklearn(rf, initial_types=initial_type)
with open("rf_iris.onnx", "wb") as f:
f.write(onx.SerializeToString())
We compare.
.. code-block:: python
sess = rt.InferenceSession("rf_iris.onnx")
def sess_predict_proba_rf(x):
return sess.run([prob_name], {input_name: x.astype(numpy.float32)})[0]
print("Execution time for predict_proba")
speed("loop(X_test, rf.predict_proba, 100)")
print("Execution time for sess_predict_proba")
speed("loop(X_test, sess_predict_proba_rf, 100)")
.. rst-class:: sphx-glr-script-out
Out:
.. code-block:: none
Execution time for predict_proba
Average 0.516 min=0.483 max=0.572
Execution time for sess_predict_proba
Average 0.00176 min=0.00171 max=0.00188
Let's see with different number of trees.
.. code-block:: python
measures = []
for n_trees in range(5, 51, 5):
print(n_trees)
rf = RandomForestClassifier(n_estimators=n_trees)
rf.fit(X_train, y_train)
initial_type = [('float_input', FloatTensorType([1, 4]))]
onx = convert_sklearn(rf, initial_types=initial_type)
with open("rf_iris_%d.onnx" % n_trees, "wb") as f:
f.write(onx.SerializeToString())
sess = rt.InferenceSession("rf_iris_%d.onnx" % n_trees)
def sess_predict_proba_loop(x):
return sess.run([prob_name], {input_name: x.astype(numpy.float32)})[0]
tsk = speed("loop(X_test, rf.predict_proba, 100)", number=5, repeat=5)
trt = speed("loop(X_test, sess_predict_proba_loop, 100)", number=5, repeat=5)
measures.append({'n_trees': n_trees, 'sklearn': tsk, 'rt': trt})
from pandas import DataFrame
df = DataFrame(measures)
ax = df.plot(x="n_trees", y="sklearn", label="scikit-learn", c="blue", logy=True)
df.plot(x="n_trees", y="rt", label="onnxruntime",
ax=ax, c="green", logy=True)
ax.set_xlabel("Number of trees")
ax.set_ylabel("Prediction time (s)")
ax.set_title("Speed comparison between scikit-learn and ONNX Runtime\nFor a random forest on Iris dataset")
ax.legend()
.. image:: /auto_examples/images/sphx_glr_plot_train_convert_predict_001.png
:class: sphx-glr-single-img
.. rst-class:: sphx-glr-script-out
Out:
.. code-block:: none
5
Average 0.042 min=0.0412 max=0.0432
Average 0.00137 min=0.00136 max=0.00138
10
Average 0.065 min=0.0641 max=0.0662
Average 0.00151 min=0.00139 max=0.00159
15
Average 0.0886 min=0.0873 max=0.0911
Average 0.00145 min=0.00143 max=0.00148
20
Average 0.113 min=0.112 max=0.115
Average 0.0015 min=0.00149 max=0.00152
25
Average 0.14 min=0.135 max=0.15
Average 0.00161 min=0.0016 max=0.00164
30
Average 0.159 min=0.154 max=0.167
Average 0.00149 min=0.00146 max=0.00158
35
Average 0.183 min=0.177 max=0.195
Average 0.00153 min=0.0015 max=0.00159
40
Average 0.221 min=0.203 max=0.242
Average 0.0019 min=0.00153 max=0.0024
45
Average 0.23 min=0.22 max=0.248
Average 0.00177 min=0.00171 max=0.0018
50
Average 0.245 min=0.244 max=0.248
Average 0.0016 min=0.00157 max=0.00165
**Total running time of the script:** ( 2 minutes 25.165 seconds)
.. _sphx_glr_download_auto_examples_plot_train_convert_predict.py:
.. only :: html
.. container:: sphx-glr-footer
:class: sphx-glr-footer-example
.. container:: sphx-glr-download
:download:`Download Python source code: plot_train_convert_predict.py <plot_train_convert_predict.py>`
.. container:: sphx-glr-download
:download:`Download Jupyter notebook: plot_train_convert_predict.ipynb <plot_train_convert_predict.ipynb>`
.. only:: html
.. rst-class:: sphx-glr-signature
`Gallery generated by Sphinx-Gallery <https://sphinx-gallery.readthedocs.io>`_