<jupyter_start><jupyter_text>Keras to ONNX conversionThis notebook shows how to convert your trained Keras model to ONNX, the generic format supported by DIANNA.The keras2onnx Python package suports both the SavedModel format and the older HDF5 (.h5 or .keras) format. It can convert multi-backend keras as well as tf.keras models.  Note: tf.keras is also supported by the tensorflow to onnx converter, see [this notebook](./tensorflow.ipynb).<jupyter_code>import os

import numpy as np
import keras
import keras2onnx

import onnx
import onnxruntime as ort<jupyter_output><empty_output><jupyter_text>Download and initialize built-in model<jupyter_code># Note: a ~100MB file will be downloaded
model = keras.applications.resnet50.ResNet50(include_top=True, weights='imagenet')<jupyter_output><empty_output><jupyter_text>Evaluate model on some random input<jupyter_code>input_shape = [1] + model.inputs[0].shape[1:]  # input shape without a 1 for batch size, instead of None
input_data = np.random.normal(size=input_shape).astype(np.float32)
pred = model.predict(input_data)<jupyter_output><empty_output><jupyter_text>Convert to ONNX<jupyter_code># Convert the model to ONNX
fname = 'resnet.onnx'

# Note: convert to ONNX and storing to disk is not working with tensorflow 2.3 nor 2.4 as backend
# Workaround (only working with TF 2.3, not 2.4): convert model to ONNX protobuf, then save to disk with ONNX

# keras2onnx.save_model(model, fname)  # this is not working
onnx_protobuf = keras2onnx.convert_keras(model, model.name)
onnx.save(onnx_protobuf, fname)<jupyter_output>tf executing eager_mode: True
tf.keras model eager_mode: False
The ONNX operator number change on the optimization: 458 -> 127<jupyter_text>Evaluate ONNX models and compare to tensorflow output<jupyter_code># verify the ONNX model is valid
onnx_model = onnx.load(fname)
onnx.checker.check_model(onnx_model)

# get ONNX predictions
sess = ort.InferenceSession(fname)
input_name = sess.get_inputs()[0].name
output_name = sess.get_outputs()[0].name

onnx_input = {input_name: input_data}
pred_onnx = sess.run([output_name], onnx_input)[0]

print(np.allclose(pred_onnx, pred, atol=1e-5))<jupyter_output>True
{'fraction_non_alphanumeric': 0.08731617647058823, 'fraction_numerical': 0.017463235294117647, 'mean_word_length': 6.379661016949153, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '542818', 'license': 'Apache-2.0', 'n_tokens_mistral': 774, 'n_tokens_neox': 744, 'n_words': 220, 'path': 'onnx_conversion_scripts/keras.ipynb', 'repo_name': 'dianna-ai/dianna-exploration', 'size': '2176'}