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 }