diff --git a/Cargo.toml b/Cargo.toml index 5a4a796450..7995235c6c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ members = [ "examples/tensorflow-mobilenet-v2", "examples/tflite-mobilenet-v3", "examples/jupyter-keras-tract-tf1", - "examples/jupyter-keras-tract-tf2", + "examples/keras-tract-tf2", "examples/nnef-dump-mobilenet-v2", "examples/nnef-mobilenet-v2", "examples/onnx-mobilenet-v2", diff --git a/examples/jupyter-keras-tract-tf2/README.md b/examples/jupyter-keras-tract-tf2/README.md deleted file mode 100644 index 8b36e963b1..0000000000 --- a/examples/jupyter-keras-tract-tf2/README.md +++ /dev/null @@ -1,26 +0,0 @@ -A simple example of training a Tensorflow model with Python in a [Jupyter notebook](simple_model.ipynb), then [loading it into `tract`](src/main.rs) to make predictions. - -# To Use -`conda env create -f environment.yml` - -Run the Jupyter notebook, which will create the model artifacts (1 onnx for `tract`, and one tensorflow artifact for benchmarking) - -Python - -``` -time python make_predictions.py -real 0m1.667s -user 0m2.575s -sys 0m1.301s -``` - -tract, even in debug mode, is significantly faster: - -``` -time cargo run -real 0m0.111s -user 0m0.080s -sys 0m0.040s -``` - -In a real-life server settings, the model would be loaded and optimized only once and used repeastedly to make predictions on different inputs. Compiled in release mode, the call to `run()` is clocked at 6 microseconds (0m0.000006s !) on one single core. diff --git a/examples/jupyter-keras-tract-tf2/ci.sh b/examples/jupyter-keras-tract-tf2/ci.sh deleted file mode 100755 index 64e948c97a..0000000000 --- a/examples/jupyter-keras-tract-tf2/ci.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh - -set -e - -sudo apt-get update -sudo apt-get install -y libgl1-mesa-glx libegl1-mesa libxrandr2 libxrandr2 libxss1 libxcursor1 libxcomposite1 libasound2 libxi6 libxtst6 - -if [ ! -d $HOME/anaconda3 ] -then - ANACONDA_SETUP=Anaconda3-2022.10-Linux-x86_64.sh - [ -e $ANACONDA_SETUP ] || wget -q https://repo.anaconda.com/archive/$ANACONDA_SETUP - bash $ANACONDA_SETUP -b -fi - -. $HOME/anaconda3/bin/activate -echo $CONDA_EXE -if [ ! -d $HOME/anaconda3/envs/tf_37 ] -then - conda env create -q -f environment.yml -fi -conda activate tf_37 - -cd `dirname $0` -jupyter nbconvert --to notebook --inplace --execute simple_model.ipynb -cargo run -cargo clean - -if [ -n "$CI" ] -then - conda deactivate - conda env remove -n tf_37 -fi diff --git a/examples/jupyter-keras-tract-tf2/environment.yml b/examples/jupyter-keras-tract-tf2/environment.yml deleted file mode 100644 index cf5d384631..0000000000 --- a/examples/jupyter-keras-tract-tf2/environment.yml +++ /dev/null @@ -1,141 +0,0 @@ -name: tf_37 -channels: - - defaults -dependencies: - - _libgcc_mutex=0.1=main - - _tflow_select=2.3.0=mkl - - absl-py=0.10.0=py37_0 - - argon2-cffi=20.1.0=py37h7b6447c_1 - - astunparse=1.6.3=py_0 - - attrs=20.2.0=py_0 - - backcall=0.2.0=py_0 - - blas=1.0=mkl - - bleach=3.2.0=py_0 - - blinker=1.4=py37_0 - - brotlipy=0.7.0=py37h7b6447c_1000 - - c-ares=1.15.0=h7b6447c_1001 - - ca-certificates=2020.7.22=0 - - cachetools=4.1.1=py_0 - - certifi=2020.6.20=py37_0 - - cffi=1.14.2=py37he30daa8_0 - - chardet=3.0.4=py37_1003 - - click=7.1.2=py_0 - - cryptography=3.1=py37h1ba5d50_0 - - decorator=4.4.2=py_0 - - defusedxml=0.6.0=py_0 - - entrypoints=0.3=py37_0 - - gast=0.3.3=py_0 - - google-auth=1.21.2=py_0 - - google-auth-oauthlib=0.4.1=py_2 - - google-pasta=0.2.0=py_0 - - grpcio=1.31.0=py37hf8bcb03_0 - - h5py=2.10.0=py37hd6299e0_1 - - hdf5=1.10.6=hb1b8bf9_0 - - idna=2.10=py_0 - - importlib-metadata=1.7.0=py37_0 - - importlib_metadata=1.7.0=0 - - intel-openmp=2020.2=254 - - ipykernel=5.3.4=py37h5ca1d4c_0 - - ipython=7.18.1=py37h5ca1d4c_0 - - ipython_genutils=0.2.0=py37_0 - - jedi=0.17.2=py37_0 - - jinja2=2.11.2=py_0 - - jsonschema=3.2.0=py37_1 - - jupyter_client=6.1.6=py_0 - - jupyter_core=4.6.3=py37_0 - - keras-preprocessing=1.1.0=py_1 - - ld_impl_linux-64=2.33.1=h53a641e_7 - - libedit=3.1.20191231=h14c3975_1 - - libffi=3.3=he6710b0_2 - - libgcc-ng=9.1.0=hdf63c60_0 - - libgfortran-ng=7.3.0=hdf63c60_0 - - libprotobuf=3.13.0=hd408876_0 - - libsodium=1.0.18=h7b6447c_0 - - libstdcxx-ng=9.1.0=hdf63c60_0 - - markdown=3.2.2=py37_0 - - markupsafe=1.1.1=py37h14c3975_1 - - mistune=0.8.4=py37h14c3975_1001 - - mkl=2020.2=256 - - mkl-service=2.3.0=py37he904b0f_0 - - mkl_fft=1.1.0=py37h23d657b_0 - - mkl_random=1.1.1=py37h0573a6f_0 - - nb_conda=2.2.1=py37_0 - - nb_conda_kernels=2.2.4=py37_0 - - nbconvert=5.6.1=py37_1 - - nbformat=5.0.7=py_0 - - ncurses=6.2=he6710b0_1 - - notebook=6.1.1=py37_0 - - numpy=1.19.1=py37hbc911f0_0 - - numpy-base=1.19.1=py37hfa32c7d_0 - - oauthlib=3.1.0=py_0 - - openssl=1.1.1g=h7b6447c_0 - - opt_einsum=3.1.0=py_0 - - packaging=20.4=py_0 - - pandoc=2.10.1=0 - - pandocfilters=1.4.2=py37_1 - - parso=0.7.0=py_0 - - pexpect=4.8.0=py37_1 - - pickleshare=0.7.5=py37_1001 - - pip=20.2.2=py37_0 - - prometheus_client=0.8.0=py_0 - - prompt-toolkit=3.0.7=py_0 - - protobuf=3.13.0=py37hf484d3e_0 - - ptyprocess=0.6.0=py37_0 - - pyasn1=0.4.8=py_0 - - pyasn1-modules=0.2.7=py_0 - - pycparser=2.20=py_2 - - pygments=2.7.0=py_0 - - pyjwt=1.7.1=py37_0 - - pyopenssl=19.1.0=py_1 - - pyparsing=2.4.7=py_0 - - pyrsistent=0.17.3=py37h7b6447c_0 - - pysocks=1.7.1=py37_1 - - python=3.7.9=h7579374_0 - - python-dateutil=2.8.1=py_0 - - pyzmq=19.0.1=py37he6710b0_1 - - readline=8.0=h7b6447c_0 - - requests=2.24.0=py_0 - - requests-oauthlib=1.3.0=py_0 - - rsa=4.6=py_0 - - scipy=1.5.2=py37h0b6359f_0 - - send2trash=1.5.0=py37_0 - - setuptools=49.6.0=py37_0 - - six=1.15.0=py_0 - - sqlite=3.33.0=h62c20be_0 - - tensorboard=2.2.1=pyh532a8cf_0 - - tensorboard-plugin-wit=1.6.0=py_0 - - tensorflow=2.2.0=mkl_py37h6e9ce2d_0 - - tensorflow-base=2.2.0=mkl_py37hd506778_0 - - tensorflow-estimator=2.2.0=pyh208ff02_0 - - termcolor=1.1.0=py37_1 - - terminado=0.8.3=py37_0 - - testpath=0.4.4=py_0 - - tk=8.6.10=hbc83047_0 - - tornado=6.0.4=py37h7b6447c_1 - - traitlets=4.3.3=py37_0 - - urllib3=1.25.10=py_0 - - wcwidth=0.2.5=py_0 - - webencodings=0.5.1=py37_1 - - werkzeug=1.0.1=py_0 - - wheel=0.35.1=py_0 - - wrapt=1.12.1=py37h7b6447c_1 - - xz=5.2.5=h7b6447c_0 - - zeromq=4.3.2=he6710b0_3 - - zipp=3.1.0=py_0 - - zlib=1.2.11=h7b6447c_3 - - pip: - - fire==0.3.1 - - joblib==0.16.0 - - keras2onnx==1.7.0 - - onnx==1.7.0 - - onnxconverter-common==1.7.0 - - onnxmltools==1.7.0 - - pyyaml==5.3.1 - - scikit-learn==0.23.2 - - skl2onnx==1.7.0 - - tensorflow-addons==0.11.2 - - threadpoolctl==2.1.0 - - tract==0.20.18 - - typeguard==2.9.1 - - typing-extensions==3.7.4.3 -prefix: /home/kali/anaconda3/envs/tf_37 diff --git a/examples/jupyter-keras-tract-tf2/example.onnx b/examples/jupyter-keras-tract-tf2/example.onnx deleted file mode 100644 index 71be7a4be1..0000000000 Binary files a/examples/jupyter-keras-tract-tf2/example.onnx and /dev/null differ diff --git a/examples/jupyter-keras-tract-tf2/io.npz b/examples/jupyter-keras-tract-tf2/io.npz deleted file mode 100644 index 1b5026dabc..0000000000 Binary files a/examples/jupyter-keras-tract-tf2/io.npz and /dev/null differ diff --git a/examples/jupyter-keras-tract-tf2/make_predictions.py b/examples/jupyter-keras-tract-tf2/make_predictions.py deleted file mode 100644 index cb747cf725..0000000000 --- a/examples/jupyter-keras-tract-tf2/make_predictions.py +++ /dev/null @@ -1,12 +0,0 @@ -import tensorflow as tf -import numpy as np -import warnings - -warnings.filterwarnings("ignore") -X = np.random.random((10, 100)) -new_model = tf.keras.models.load_model('my_model') - - -predictions = new_model.predict(X) - -print(f"result: {predictions}") \ No newline at end of file diff --git a/examples/jupyter-keras-tract-tf2/my_model/saved_model.pb b/examples/jupyter-keras-tract-tf2/my_model/saved_model.pb deleted file mode 100644 index db3a71e687..0000000000 Binary files a/examples/jupyter-keras-tract-tf2/my_model/saved_model.pb and /dev/null differ diff --git a/examples/jupyter-keras-tract-tf2/my_model/variables/variables.data-00000-of-00001 b/examples/jupyter-keras-tract-tf2/my_model/variables/variables.data-00000-of-00001 deleted file mode 100644 index 3645b84a0d..0000000000 Binary files a/examples/jupyter-keras-tract-tf2/my_model/variables/variables.data-00000-of-00001 and /dev/null differ diff --git a/examples/jupyter-keras-tract-tf2/my_model/variables/variables.index b/examples/jupyter-keras-tract-tf2/my_model/variables/variables.index deleted file mode 100644 index 2c97170ac0..0000000000 Binary files a/examples/jupyter-keras-tract-tf2/my_model/variables/variables.index and /dev/null differ diff --git a/examples/jupyter-keras-tract-tf2/simple_model.ipynb b/examples/jupyter-keras-tract-tf2/simple_model.ipynb deleted file mode 100644 index 1c200ba630..0000000000 --- a/examples/jupyter-keras-tract-tf2/simple_model.ipynb +++ /dev/null @@ -1,201 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import tensorflow as tf\n", - "from tensorflow.keras.models import Sequential\n", - "from tensorflow.keras.layers import Dense, Activation\n", - "import onnxmltools\n", - "import tract" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "model = Sequential([\n", - " Dense(32, activation='relu', input_dim=100, name='main_input'),\n", - " Dense(1, activation='sigmoid', name=\"dense_1\"),\n", - "])" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "model.compile(optimizer='rmsprop',\n", - " loss='binary_crossentropy',\n", - " metrics=['accuracy'])" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Epoch 1/10\n", - "32/32 [==============================] - 0s 834us/step - loss: 0.7036 - accuracy: 0.4800\n", - "Epoch 2/10\n", - "32/32 [==============================] - 0s 802us/step - loss: 0.6949 - accuracy: 0.5210\n", - "Epoch 3/10\n", - "32/32 [==============================] - 0s 853us/step - loss: 0.6934 - accuracy: 0.5070\n", - "Epoch 4/10\n", - "32/32 [==============================] - 0s 910us/step - loss: 0.6885 - accuracy: 0.5380\n", - "Epoch 5/10\n", - "32/32 [==============================] - 0s 1ms/step - loss: 0.6819 - accuracy: 0.5600\n", - "Epoch 6/10\n", - "32/32 [==============================] - 0s 988us/step - loss: 0.6853 - accuracy: 0.5610\n", - "Epoch 7/10\n", - "32/32 [==============================] - 0s 820us/step - loss: 0.6797 - accuracy: 0.5800\n", - "Epoch 8/10\n", - "32/32 [==============================] - 0s 913us/step - loss: 0.6763 - accuracy: 0.5730\n", - "Epoch 9/10\n", - "32/32 [==============================] - 0s 904us/step - loss: 0.6713 - accuracy: 0.5980\n", - "Epoch 10/10\n", - "32/32 [==============================] - 0s 743us/step - loss: 0.6714 - accuracy: 0.5800\n" - ] - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "data = np.random.random((1000, 100))\n", - "labels = np.random.randint(2, size=(1000, 1))\n", - "\n", - "# Train the model, iterating on the data in batches of 32 samples\n", - "model.fit(data, labels, epochs=10, batch_size=32)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING:tensorflow:From /home/kali/anaconda3/envs/tf_37/lib/python3.7/site-packages/tensorflow/python/ops/resource_variable_ops.py:1817: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.\n", - "Instructions for updating:\n", - "If using Keras pass *_constraint arguments to layers.\n", - "INFO:tensorflow:Assets written to: my_model/assets\n" - ] - } - ], - "source": [ - "# Save in tf's format, for benchmarking\n", - "model.save('my_model')" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "tf executing eager_mode: True\n", - "tf.keras model eager_mode: False\n", - "The ONNX operator number change on the optimization: 10 -> 6\n", - "The maximum opset needed by this model is only 9.\n" - ] - } - ], - "source": [ - "# Save the model in ONNX format to pass to tract\n", - "onnx_model = onnxmltools.convert_keras(model)\n", - "onnxmltools.utils.save_model(onnx_model, 'example.onnx')" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "input = np.random.random((1,100)).astype(np.float32)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "tf_output = model.predict(input)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "# Run the model in tract and check output against TensorFlow\n", - "tract_output = tract.onnx().model_for_path(\"example.onnx\").into_optimized().into_runnable().run([input])[0].to_numpy()\n", - "assert(np.allclose(tf_output, tract_output))" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "# Save input and reference output for Rust demo\n", - "np.savez(\"io.npz\", input=input, output=tf_output)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.7.9" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/jupyter-keras-tract-tf2/.gitignore b/examples/keras-tract-tf2/.gitignore similarity index 100% rename from examples/jupyter-keras-tract-tf2/.gitignore rename to examples/keras-tract-tf2/.gitignore diff --git a/examples/jupyter-keras-tract-tf2/Cargo.toml b/examples/keras-tract-tf2/Cargo.toml similarity index 92% rename from examples/jupyter-keras-tract-tf2/Cargo.toml rename to examples/keras-tract-tf2/Cargo.toml index 39d9a866b5..d06e2c1b4c 100644 --- a/examples/jupyter-keras-tract-tf2/Cargo.toml +++ b/examples/keras-tract-tf2/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "jupyter-keras-tract-tf2" +name = "keras-tract-tf2" version = "0.20.7-pre" authors = ["Matthew Alhonte "] license = "MIT OR Apache-2.0" diff --git a/examples/keras-tract-tf2/README.md b/examples/keras-tract-tf2/README.md new file mode 100644 index 0000000000..386aa7ceea --- /dev/null +++ b/examples/keras-tract-tf2/README.md @@ -0,0 +1,21 @@ +A simple example of training a Tensorflow model with Python, check the model with tract python API, then [loading it into `tract`](src/main.rs) and compare predictions. + +# Python side training + +``` +pip install -r requirements.txt +``` + +Train a model, export it to ONNX along with a input and output example. + +``` +python example.py +``` + +(Outputs are commited to git, you don't need to run the python step at all.) + +# Rust side inference + +``` +cargo run +``` diff --git a/examples/keras-tract-tf2/ci.sh b/examples/keras-tract-tf2/ci.sh new file mode 100755 index 0000000000..02b4dbb172 --- /dev/null +++ b/examples/keras-tract-tf2/ci.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +set -e + +sudo apt-get update +sudo apt-get install -y libgl1-mesa-glx libegl1-mesa libxrandr2 libxrandr2 libxss1 libxcursor1 libxcomposite1 libasound2 libxi6 libxtst6 + +virtualenv venv +. venv/bin/activate + +pip install -r requirements.txt +python example.py +cargo run diff --git a/examples/keras-tract-tf2/example.onnx b/examples/keras-tract-tf2/example.onnx new file mode 100644 index 0000000000..ff3f019160 Binary files /dev/null and b/examples/keras-tract-tf2/example.onnx differ diff --git a/examples/keras-tract-tf2/io.npz b/examples/keras-tract-tf2/io.npz new file mode 100644 index 0000000000..9ead17dfc9 Binary files /dev/null and b/examples/keras-tract-tf2/io.npz differ diff --git a/examples/jupyter-keras-tract-tf2/src/main.rs b/examples/keras-tract-tf2/src/main.rs similarity index 91% rename from examples/jupyter-keras-tract-tf2/src/main.rs rename to examples/keras-tract-tf2/src/main.rs index 057bca97e5..81945a2db0 100644 --- a/examples/jupyter-keras-tract-tf2/src/main.rs +++ b/examples/keras-tract-tf2/src/main.rs @@ -6,6 +6,8 @@ fn main() -> TractResult<()> { let model = tract_onnx::onnx() // load the model .model_for_path("example.onnx")? + // kill over-spcified output fact in ONNX + .with_output_fact(0, Default::default())? // optimize graph .into_optimized()? // make the model runnable and fix its inputs and outputs