notebooks/onnx_model_export.ipynb (233 lines of code) (raw):
{
"cells": [
{
"cell_type": "markdown",
"id": "26947f7e",
"metadata": {},
"source": [
"# ONNX model export\n",
"\n",
"In this notebook we'll cover how to export a setfit model to ONNX format. This is useful for deploying models in production and speeding up inference on CPUs."
]
},
{
"cell_type": "markdown",
"id": "39c7df94",
"metadata": {},
"source": [
"## Setup"
]
},
{
"cell_type": "markdown",
"id": "ca808828",
"metadata": {},
"source": [
"If you're running this Notebook on Colab or some other cloud platform, you will need to install a few libraries namely `setfit`, `onnxruntime`, `onnx`, and `skl2onnx`. Uncomment the following cell and run it:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d5d6c9f2",
"metadata": {},
"outputs": [],
"source": [
"# %pip install setfit[onnx]"
]
},
{
"cell_type": "markdown",
"id": "47c3060f",
"metadata": {},
"source": [
"## Convert model to ONNX\n",
"\n",
"There are two types of heads available for setfit models. Sklearn based estimators and `torch.nn.Module`. We'll convert the example from `text-classification.ipynb` which uses an `sklearn` head and a base model that hasn't been trained which defaults to a `nn.Module` head. We start by loading in the models"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1a4c320d",
"metadata": {},
"outputs": [],
"source": [
"from setfit import SetFitModel\n",
"\n",
"model = SetFitModel.from_pretrained(\"lewtun/my-awesome-setfit-model\")"
]
},
{
"cell_type": "markdown",
"id": "6080ea85",
"metadata": {},
"source": [
"Next we import the onnx_export onnx function from `setfit.onnx` and run the export. The export function takes in the `model_body` and the `model_head` from the setfit model loaded above."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "89d24aad",
"metadata": {},
"outputs": [],
"source": [
"from setfit.exporters.onnx import export_onnx\n",
"\n",
"# Export the sklearn based model\n",
"output_path = \"sklearn_model.onnx\"\n",
"export_onnx(model.model_body,\n",
" model.model_head,\n",
" opset=12,\n",
" output_path=output_path)"
]
},
{
"cell_type": "markdown",
"id": "640ff34a",
"metadata": {},
"source": [
"Excellent! Let's check to see that this worked. If we list our current directory we should see a `model.onnx` file if everything succeeded. If you're interested in looking at the internals of this file check out [netron](https://github.com/lutzroeder/netron). "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a5c62283",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"assert output_path in os.listdir() "
]
},
{
"cell_type": "markdown",
"id": "e2d4707c",
"metadata": {},
"source": [
"With our model successfully converted to `onnx` let's run some initial predictions and make sure we are getting the same results as our earlier model. We'll start by predicting using the original pytorch pipeline."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a9a00c30",
"metadata": {},
"outputs": [],
"source": [
"# Run inference using the original model\n",
"input_text = [\"i loved the spiderman movie!\", \"pineapple on pizza is the worst 🤮\"]\n",
"pytorch_preds = model(input_text)\n",
"pytorch_preds "
]
},
{
"cell_type": "markdown",
"id": "4fb8f677",
"metadata": {},
"source": [
"Now let's make some predictions using the onnx model that we just created!"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a151b3ba",
"metadata": {},
"outputs": [],
"source": [
"import onnxruntime\n",
"from transformers import AutoTokenizer\n",
"tokenizer = AutoTokenizer.from_pretrained(\"lewtun/my-awesome-setfit-model\")\n",
"inputs = tokenizer(\n",
" input_text,\n",
" padding=True,\n",
" truncation=True,\n",
" return_attention_mask=True,\n",
" return_token_type_ids=True,\n",
" return_tensors=\"np\",\n",
")\n",
"\n",
"session = onnxruntime.InferenceSession(output_path)\n",
"\n",
"onnx_preds = session.run(None, dict(inputs))[0]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b1c9c59c",
"metadata": {},
"outputs": [],
"source": [
"onnx_preds"
]
},
{
"cell_type": "markdown",
"id": "c1abc081",
"metadata": {},
"source": [
"The predicted outputs should look the same let's verify using numpy's `array_equal` function."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c552118b",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"assert np.array_equal(onnx_preds, pytorch_preds)"
]
},
{
"cell_type": "markdown",
"id": "41d34da9",
"metadata": {},
"source": [
"Nice! The output from our original pytorch model and our new onnx optimized model is the same!"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "80766b89",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "dcc67aa3",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.8.13"
}
},
"nbformat": 4,
"nbformat_minor": 5
}