.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/plot_abegin_convert_pipeline.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note Click :ref:`here ` to download the full example code or to run this example in your browser via Binder .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_plot_abegin_convert_pipeline.py: .. _l-simple-deploy-1: Train and deploy a scikit-learn pipeline ======================================== .. index:: pipeline, deployment This program starts from an example in :epkg:`scikit-learn` documentation: `Plot individual and voting regression predictions `_, converts it into ONNX and finally computes the predictions a different runtime. .. contents:: :local: Training a pipeline +++++++++++++++++++ .. GENERATED FROM PYTHON SOURCE LINES 22-49 .. code-block:: default from pyquickhelper.helpgen.graphviz_helper import plot_graphviz import numpy from onnxruntime import InferenceSession from sklearn.datasets import load_diabetes from sklearn.ensemble import ( GradientBoostingRegressor, RandomForestRegressor, VotingRegressor) from sklearn.linear_model import LinearRegression from sklearn.model_selection import train_test_split from sklearn.pipeline import Pipeline from skl2onnx import to_onnx from mlprodict.onnxrt import OnnxInference X, y = load_diabetes(return_X_y=True) X_train, X_test, y_train, y_test = train_test_split(X, y) # Train classifiers reg1 = GradientBoostingRegressor(random_state=1) reg2 = RandomForestRegressor(random_state=1) reg3 = LinearRegression() ereg = Pipeline(steps=[ ('voting', VotingRegressor([('gb', reg1), ('rf', reg2), ('lr', reg3)])), ]) ereg.fit(X_train, y_train) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none Pipeline(steps=[('voting', VotingRegressor(estimators=[('gb', GradientBoostingRegressor(random_state=1)), ('rf', RandomForestRegressor(random_state=1)), ('lr', LinearRegression())]))]) .. GENERATED FROM PYTHON SOURCE LINES 50-58 Converts the model ++++++++++++++++++ The second argument gives a sample of the data used to train the model. It is used to infer the input type of the ONNX graph. It is converted into single float and ONNX runtimes may not fully support doubles. .. GENERATED FROM PYTHON SOURCE LINES 58-61 .. code-block:: default onx = to_onnx(ereg, X_train[:1].astype(numpy.float32)) .. GENERATED FROM PYTHON SOURCE LINES 62-66 Prediction with ONNX ++++++++++++++++++++ The first example uses :epkg:`onnxruntime`. .. GENERATED FROM PYTHON SOURCE LINES 66-74 .. code-block:: default sess = InferenceSession(onx.SerializeToString()) pred_ort = sess.run(None, {'X': X_test.astype(numpy.float32)})[0] pred_skl = ereg.predict(X_test.astype(numpy.float32)) pred_ort[:5], pred_skl[:5] .. rst-class:: sphx-glr-script-out Out: .. code-block:: none (array([[ 93.86803], [109.67433], [ 71.22099], [198.35121], [224.00291]], dtype=float32), array([ 93.8680252 , 109.67432835, 71.22099321, 198.35120823, 224.00290167])) .. GENERATED FROM PYTHON SOURCE LINES 75-82 .. _l-diff-dicrepencies: Comparison ++++++++++ Before deploying, we need to compare that both *scikit-learn* and *ONNX* return the same predictions. .. GENERATED FROM PYTHON SOURCE LINES 82-93 .. code-block:: default def diff(p1, p2): p1 = p1.ravel() p2 = p2.ravel() d = numpy.abs(p2 - p1) return d.max(), (d / numpy.abs(p1)).max() print(diff(pred_skl, pred_ort)) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none (3.023320937245444e-05, 1.6594571332594726e-07) .. GENERATED FROM PYTHON SOURCE LINES 94-100 It looks good. Biggest errors (absolute and relative) are within the margin error introduced by using floats instead of doubles. We can save the model into ONNX format and compute the same predictions in many platform using :epkg:`onnxruntime`. .. GENERATED FROM PYTHON SOURCE LINES 102-110 Python runtime ++++++++++++++ A python runtime can be used as well to compute the prediction. It is not meant to be used into production (it still relies on python), but it is useful to investigate why the conversion went wrong. It uses module :epkg:`mlprodict`. .. GENERATED FROM PYTHON SOURCE LINES 110-114 .. code-block:: default oinf = OnnxInference(onx, runtime="python_compiled") print(oinf) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none OnnxInference(...) def compiled_run(dict_inputs): # init: w0 (w0) # inputs X = dict_inputs['X'] (var_2, ) = n0_linearregressor(X) (dpath95, ) = n1_treeensembleregressor(X) (dpath96, ) = n2_treeensembleregressor(X) (dpath97, ) = n3_treeensembleregressor(X) (dpath98, ) = n4_treeensembleregressor(X) (dpath99, ) = n5_treeensembleregressor(X) (dpath93, ) = n6_treeensembleregressor(X) (dpath94, ) = n7_treeensembleregressor(X) (dpath88, ) = n8_treeensembleregressor(X) (dpath89, ) = n9_treeensembleregressor(X) (dpath90, ) = n10_treeensembleregressor(X) (dpath91, ) = n11_treeensembleregressor(X) (dpath92, ) = n12_treeensembleregressor(X) (dpath86, ) = n13_treeensembleregressor(X) (dpath87, ) = n14_treeensembleregressor(X) (dpath82, ) = n15_treeensembleregressor(X) (dpath83, ) = n16_treeensembleregressor(X) (dpath84, ) = n17_treeensembleregressor(X) (dpath85, ) = n18_treeensembleregressor(X) (dpath79, ) = n19_treeensembleregressor(X) (dpath80, ) = n20_treeensembleregressor(X) (dpath81, ) = n21_treeensembleregressor(X) (dpath75, ) = n22_treeensembleregressor(X) (dpath76, ) = n23_treeensembleregressor(X) (dpath77, ) = n24_treeensembleregressor(X) (dpath78, ) = n25_treeensembleregressor(X) (dpath73, ) = n26_treeensembleregressor(X) (dpath74, ) = n27_treeensembleregressor(X) (dpath68, ) = n28_treeensembleregressor(X) (dpath69, ) = n29_treeensembleregressor(X) (dpath70, ) = n30_treeensembleregressor(X) (dpath71, ) = n31_treeensembleregressor(X) (dpath72, ) = n32_treeensembleregressor(X) (dpath64, ) = n33_treeensembleregressor(X) (dpath65, ) = n34_treeensembleregressor(X) (dpath66, ) = n35_treeensembleregressor(X) (dpath67, ) = n36_treeensembleregressor(X) (dpath61, ) = n37_treeensembleregressor(X) (dpath62, ) = n38_treeensembleregressor(X) (dpath63, ) = n39_treeensembleregressor(X) (dpath57, ) = n40_treeensembleregressor(X) (dpath58, ) = n41_treeensembleregressor(X) (dpath59, ) = n42_treeensembleregressor(X) (dpath60, ) = n43_treeensembleregressor(X) (dpath55, ) = n44_treeensembleregressor(X) (dpath56, ) = n45_treeensembleregressor(X) (dpath50, ) = n46_treeensembleregressor(X) (dpath51, ) = n47_treeensembleregressor(X) (dpath52, ) = n48_treeensembleregressor(X) (dpath53, ) = n49_treeensembleregressor(X) (dpath54, ) = n50_treeensembleregressor(X) (dpath48, ) = n51_treeensembleregressor(X) (dpath49, ) = n52_treeensembleregressor(X) (dpath43, ) = n53_treeensembleregressor(X) (dpath44, ) = n54_treeensembleregressor(X) (dpath45, ) = n55_treeensembleregressor(X) (dpath46, ) = n56_treeensembleregressor(X) (dpath47, ) = n57_treeensembleregressor(X) (dpath41, ) = n58_treeensembleregressor(X) (dpath42, ) = n59_treeensembleregressor(X) (dpath37, ) = n60_treeensembleregressor(X) (dpath38, ) = n61_treeensembleregressor(X) (dpath39, ) = n62_treeensembleregressor(X) (dpath40, ) = n63_treeensembleregressor(X) (dpath34, ) = n64_treeensembleregressor(X) (dpath35, ) = n65_treeensembleregressor(X) (dpath36, ) = n66_treeensembleregressor(X) (dpath30, ) = n67_treeensembleregressor(X) (dpath31, ) = n68_treeensembleregressor(X) (dpath32, ) = n69_treeensembleregressor(X) (dpath33, ) = n70_treeensembleregressor(X) (dpath28, ) = n71_treeensembleregressor(X) (dpath29, ) = n72_treeensembleregressor(X) (dpath23, ) = n73_treeensembleregressor(X) (dpath24, ) = n74_treeensembleregressor(X) (dpath25, ) = n75_treeensembleregressor(X) (dpath26, ) = n76_treeensembleregressor(X) (dpath27, ) = n77_treeensembleregressor(X) (dpath19, ) = n78_treeensembleregressor(X) (dpath20, ) = n79_treeensembleregressor(X) (dpath21, ) = n80_treeensembleregressor(X) (dpath22, ) = n81_treeensembleregressor(X) (dpath14, ) = n82_treeensembleregressor(X) (dpath15, ) = n83_treeensembleregressor(X) (dpath16, ) = n84_treeensembleregressor(X) (dpath17, ) = n85_treeensembleregressor(X) (dpath18, ) = n86_treeensembleregressor(X) (dpath7, ) = n87_treeensembleregressor(X) (dpath8, ) = n88_treeensembleregressor(X) (dpath9, ) = n89_treeensembleregressor(X) (dpath10, ) = n90_treeensembleregressor(X) (dpath11, ) = n91_treeensembleregressor(X) (dpath12, ) = n92_treeensembleregressor(X) (dpath13, ) = n93_treeensembleregressor(X) (dpath3, ) = n94_treeensembleregressor(X) (dpath4, ) = n95_treeensembleregressor(X) (dpath5, ) = n96_treeensembleregressor(X) (dpath6, ) = n97_treeensembleregressor(X) (dpath1, ) = n98_treeensembleregressor(X) (dpath2, ) = n99_treeensembleregressor(X) (var_0, ) = n100_treeensembleregressor(X) (var_1, ) = n101_treeensembleregressor(X) (dpath0, ) = n102_treeensembleregressor(X) (wvar_0, ) = n103_mul(var_0, w0) (wvar_2, ) = n104_mul(var_2, w0) (wvar_1, ) = n105_mul(var_1, w0) (fvar_1, ) = n106_flatten(wvar_1) (fvar_2, ) = n107_flatten(wvar_2) (fvar_0, ) = n108_flatten(wvar_0) (variable, ) = n109_sum(fvar_0, fvar_1, fvar_2) return { 'variable': variable, } .. GENERATED FROM PYTHON SOURCE LINES 115-116 It works almost the same way. .. GENERATED FROM PYTHON SOURCE LINES 116-120 .. code-block:: default pred_pyrt = oinf.run({'X': X_test.astype(numpy.float32)})['variable'] print(diff(pred_skl, pred_pyrt)) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none (4.59469082159103e-05, 2.835917685038965e-07) .. GENERATED FROM PYTHON SOURCE LINES 121-123 Final graph +++++++++++ .. GENERATED FROM PYTHON SOURCE LINES 123-127 .. code-block:: default ax = plot_graphviz(oinf.to_dot(), dpi=100) ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) .. image:: /auto_examples/images/sphx_glr_plot_abegin_convert_pipeline_001.png :alt: plot abegin convert pipeline :class: sphx-glr-single-img .. rst-class:: sphx-glr-timing **Total running time of the script:** ( 0 minutes 49.119 seconds) .. _sphx_glr_download_auto_examples_plot_abegin_convert_pipeline.py: .. only :: html .. container:: sphx-glr-footer :class: sphx-glr-footer-example .. container:: binder-badge .. image:: images/binder_badge_logo.svg :target: https://mybinder.org/v2/gh/sdpython/onnxcustom/master?urlpath=lab/tree/notebooks/auto_examples/plot_abegin_convert_pipeline.ipynb :alt: Launch binder :width: 150 px .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_abegin_convert_pipeline.py ` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_abegin_convert_pipeline.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_