{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\nTrain, convert and predict with ONNX Runtime\n============================================\n\nThis example demonstrates an end to end scenario\nstarting with the training of a scikit-learn pipeline\nwhich takes as inputs not a regular vector but a\ndictionary ``{ int: float }`` as its first step is a\n`DictVectorizer `_.\n\nTrain a pipeline\n++++++++++++++++\n\nThe first step consists in retrieving the boston datset.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import pandas\nfrom sklearn.datasets import load_boston\nboston = load_boston()\nX, y = boston.data, boston.target\n\nfrom sklearn.model_selection import train_test_split\nX_train, X_test, y_train, y_test = train_test_split(X, y)\nX_train_dict = pandas.DataFrame(X_train[:,1:]).T.to_dict().values()\nX_test_dict = pandas.DataFrame(X_test[:,1:]).T.to_dict().values()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We create a pipeline.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from sklearn.pipeline import make_pipeline\nfrom sklearn.ensemble import GradientBoostingRegressor\nfrom sklearn.feature_extraction import DictVectorizer\npipe = make_pipeline(\n DictVectorizer(sparse=False),\n GradientBoostingRegressor())\n \npipe.fit(X_train_dict, y_train)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We compute the prediction on the test set\nand we show the confusion matrix.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from sklearn.metrics import r2_score\n\npred = pipe.predict(X_test_dict)\nprint(r2_score(y_test, pred))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Conversion to ONNX format\n+++++++++++++++++++++++++\n\nWe use module \n`sklearn-onnx `_\nto convert the model into ONNX format.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from skl2onnx import convert_sklearn\nfrom skl2onnx.common.data_types import FloatTensorType, Int64TensorType, DictionaryType, SequenceType\n\n# initial_type = [('float_input', DictionaryType(Int64TensorType([1]), FloatTensorType([])))]\ninitial_type = [('float_input', DictionaryType(Int64TensorType([1]), FloatTensorType([])))]\nonx = convert_sklearn(pipe, initial_types=initial_type)\nwith open(\"pipeline_vectorize.onnx\", \"wb\") as f:\n f.write(onx.SerializeToString())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We load the model with ONNX Runtime and look at\nits input and output.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import onnxruntime as rt\nfrom onnxruntime.capi.onnxruntime_pybind11_state import InvalidArgument\n\nsess = rt.InferenceSession(\"pipeline_vectorize.onnx\")\n\nimport numpy\ninp, out = sess.get_inputs()[0], sess.get_outputs()[0]\nprint(\"input name='{}' and shape={} and type={}\".format(inp.name, inp.shape, inp.type))\nprint(\"output name='{}' and shape={} and type={}\".format(out.name, out.shape, out.type))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We compute the predictions.\nWe could do that in one call:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "try:\n pred_onx = sess.run([out.name], {inp.name: X_test_dict})[0]\nexcept (RuntimeError, InvalidArgument) as e:\n print(e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But it fails because, in case of a DictVectorizer,\nONNX Runtime expects one observation at a time.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "pred_onx = [sess.run([out.name], {inp.name: row})[0][0, 0] for row in X_test_dict]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We compare them to the model's ones.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(r2_score(pred, pred_onx))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Very similar. *ONNX Runtime* uses floats instead of doubles,\nthat explains the small discrepencies.\n\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.4" } }, "nbformat": 4, "nbformat_minor": 0 }