Fournisseurs d'exécution ONNX Runtime

Optimisation des performances des modèles de langage étendu avec ONNX sur Simseo MLOps

Dans notre article de blog précédent, nous avons expliqué comment simplifier le déploiement et la surveillance des modèles de base avec Simseo MLOps. Nous avons pris un modèle pré-formé de HuggingFace à l’aide de Tensorflow, et nous avons écrit un script d’inférence simple et téléchargé le script et le modèle enregistré en tant que package de modèle personnalisé sur Simseo MLOps. Nous avons ensuite facilement déployé le modèle de base pré-entraîné sur les serveurs Simseo en quelques minutes seulement.

Dans cet article de blog, nous montrerons comment vous pouvez facilement améliorer considérablement la vitesse d’inférence du même modèle tout en réduisant sa consommation de ressources. Dans notre procédure pas à pas, vous apprendrez que la seule chose nécessaire est de convertir votre modèle de langage au format ONNX. Le support natif pour ONNX Runtime dans Simseo s’occupera du reste.

Pourquoi les grands modèles de langage sont-ils difficiles pour l’inférence ?

Auparavant, nous avons parlé de ce que sont les modèles de langage. L’architecture neuronale des grands modèles de langage peut avoir des milliards de paramètres. Avoir un grand nombre de paramètres signifie que ces modèles seront gourmands en ressources et lents à prédire. Pour cette raison, ils sont difficiles à utiliser pour l’inférence avec des performances élevées. De plus, nous voulons que ces modèles traitent non seulement une entrée à la fois, mais traitent également des lots d’entrées et les consomment plus efficacement. La bonne nouvelle est que nous avons un moyen d’améliorer leurs performances et leur débit en accélérant leur processus d’inférence, grâce aux capacités du runtime ONNX.

Qu’est-ce qu’ONNX et le runtime ONNX ?

ONNX (Open Neural Network Exchange) est un format standard ouvert pour représenter des modèles d’apprentissage automatique (ML) construits sur divers frameworks tels que PyTorch, Tensorflow/Keras, scikit-learn. ONNX Runtime est également un projet open source basé sur la norme ONNX. Il s’agit d’un moteur d’inférence optimisé pour accélérer le processus d’inférence des modèles convertis au format ONNX sur une large gamme de systèmes d’exploitation, de langages et de plates-formes matérielles.

Fournisseurs d’exécution ONNX Runtime. Source : environnement d’exécution ONNX

ONNX et son environnement d’exécution forment ensemble la base de la standardisation et de l’accélération de l’inférence de modèle dans les environnements de production. Grâce à certaines techniques d’optimisation1, ONNX Runtime accélère l’inférence de modèle sur différentes plates-formes, telles que les appareils mobiles, le cloud ou les environnements de périphérie. Il fournit une abstraction en exploitant les capacités de calcul de ces plates-formes via une interface API unique.

De plus, en convertissant des modèles vers ONNX, nous bénéficions de l’avantage de l’interopérabilité du cadre car nous pouvons exporter des modèles formés dans divers cadres ML vers ONNX et vice versa, charger des modèles ONNX précédemment exportés en mémoire et les utiliser dans notre cadre ML de choix.

Accélération de l’inférence de modèle basée sur les transformateurs avec ONNX Runtime

Divers tests de performance exécutés par des équipes d’ingénierie indépendantes du secteur ont démontré que les modèles basés sur des transformateurs peuvent bénéficier de manière significative des optimisations ONNX Runtime pour réduire la latence et augmenter le débit sur les processeurs.

Quelques exemples incluent le travail de Microsoft autour de l’optimisation du modèle BERT à l’aide d’ONNX Runtime2, Résultats de l’analyse comparative Twitter pour l’inférence de processeur de transformateur dans Google Cloud3et l’accélération des transformateurs de phrases avec Hugging Face Optimum4.

image
Source : Microsoft5

Ces benchmarks démontrent que nous pouvons augmenter considérablement le débit et les performances des modèles NLP basés sur des transformateurs, en particulier grâce à la quantification. Par exemple, dans le benchmark de l’équipe Microsoft ci-dessus, le modèle BERT à 12 couches quantifié avec Intel® DL Boost : VNNI et ONNX Runtime peut atteindre jusqu’à 2,9 fois des gains de performances.

Comment Simseo MLOps prend-il nativement en charge ONNX ?

Pour vos workflows de modélisation ou d’inférence, vous pouvez intégrer votre code personnalisé dans Simseo avec ces deux mécanismes :

  1. En tant que tâche personnalisée : Bien que Simseo fournisse des centaines de tâches intégrées, il existe des situations où vous avez besoin de méthodes de prétraitement ou de modélisation qui ne sont pas actuellement prises en charge prêtes à l’emploi. Pour combler cette lacune, vous pouvez apporter une tâche personnalisée qui implémente une méthode manquante, insérer cette tâche dans un blueprint dans Simseo, puis former, évaluer et déployer ce blueprint de la même manière que vous le feriez pour n’importe quel blueprint généré par Simseo. Vous pouvez consulter le fonctionnement du processus ici.
  2. En tant que modèle d’inférence personnalisé : Il peut s’agir d’un modèle pré-formé ou d’un code utilisateur préparé pour l’inférence, ou d’une combinaison des deux. Un modèle d’inférence peut avoir un schéma d’entrée/sortie prédéfini pour la classification/régression/détection d’anomalies ou être complètement non structuré. Vous pouvez lire plus de détails sur le déploiement de vos modèles d’inférence personnalisés ici.

Dans les deux cas, afin d’exécuter vos modèles personnalisés sur la plate-forme Simseo AI avec prise en charge de MLOps, vous devez d’abord sélectionner l’un de nos environnements_dropin_publics tels que Python3 + PyTorch, Python3 + Keras/Tensorflow ou Python3 + ONNX. Ces environnements définissent chacun les bibliothèques disponibles dans l’environnement et fournissent un modèle. Vos propres exigences de dépendance peuvent être appliquées à l’un de ces environnements de base pour créer un environnement d’exécution pour vos tâches personnalisées ou vos modèles d’inférence personnalisés.

L’avantage supplémentaire des environnements d’exécution Simseo est que si vous avez un seul artefact de modèle et que votre modèle est conforme à certaines structures d’entrée/sortie, ce qui signifie que vous n’avez pas besoin d’un script d’inférence personnalisé pour transformer la demande d’entrée ou les prédictions brutes, vous n’avez même pas devez fournir un script personnalisé dans votre package de modèle téléchargé. Dans le cas ONNX, si vous ne souhaitez prédire qu’avec un seul fichier .onnx et que ce fichier de modèle est conforme à la spécification structurée, lorsque vous sélectionnez l’environnement de base Python3 + ONNX pour votre package de modèle personnalisé, Simseo MLOps saura comment charger ce modéliser en mémoire et prédire avec. Pour en savoir plus et mettre la main sur des exemples faciles à reproduire, veuillez visiter la section des modèles de modèles d’inférence personnalisés dans notre référentiel de modèles personnalisés.

Procédure pas à pas

Après avoir lu toutes ces informations sur les avantages en termes de performances et la simplicité relative de la mise en œuvre de modèles via ONNX, je suis sûr que vous êtes plus que ravi de commencer.

Pour illustrer un exemple de bout en bout, nous allons effectuer les étapes suivantes :

  1. Prenez le même modèle de fondation dans notre article de blog précédent et enregistrez-le sur votre disque local.
  2. Exportez le modèle Tensorflow enregistré au format ONNX.
  3. Empaquetez l’artefact de modèle ONNX avec un script d’inférence personnalisé (custom.py).
  4. Téléchargez le package de modèle personnalisé vers Simseo MLOps sur l’environnement de base ONNX.
  5. Créez un déploiement.
  6. Envoyez des requêtes de prédiction au point de terminaison de déploiement.

Par souci de concision, nous ne montrerons que les étapes supplémentaires et modifiées que vous effectuerez en plus de la procédure pas à pas de notre blog précédent, mais la mise en œuvre de bout en bout est disponible sur ce bloc-notes Google Colab sous le référentiel de la communauté Simseo.

Conversion du modèle Foundation en ONNX

Pour ce tutoriel, nous utiliserons le transformer outil de conversion ONNX de la bibliothèque pour convertir notre question répondant à LLM au format ONNX comme ci-dessous.

FOUNDATION_MODEL = "bert-large-uncased-whole-word-masking-finetuned-squad"

!python -m transformers.onnx --model=$FOUNDATION_MODEL --feature=question-answering $BASE_PATH


Modification de votre script d’inférence personnalisé pour utiliser votre modèle ONNX

Pour l’inférence avec ce modèle sur Simseo MLOps, notre script custom.py chargera le modèle ONNX en mémoire dans une session d’exécution ONNX et gérera les demandes de prédiction entrantes comme suit :

%%writefile $BASE_PATH/custom.py

"""

Copyright 2021 Simseo, Inc. and its affiliates.

All rights reserved.

This is proprietary source code of Simseo, Inc. and its affiliates.

Released under the terms of Simseo Tool and Utility Agreement.

"""

import json

import os

import io

from transformers import AutoTokenizer

import onnxruntime as ort

import numpy as np

import pandas as pd

def load_model(input_dir):

    global model_load_duration

    onnx_path = os.path.join(input_dir, "model.onnx")

    tokenizer_path = os.path.join(input_dir)

    tokenizer = AutoTokenizer.from_pretrained(tokenizer_path)

    sess = ort.InferenceSession(onnx_path)

    return sess, tokenizer

def _get_answer_in_text(output, input_ids, idx, tokenizer):

    answer_start = np.argmax(output[0], axis=1)[idx]

    answer_end = (np.argmax(output[1], axis=1) + 1)[idx]

    answer = tokenizer.convert_tokens_to_string(

        tokenizer.convert_ids_to_tokens(input_ids[answer_start:answer_end])

    )

    return answer

def score_unstructured(model, data, query, **kwargs):

    global model_load_duration

    sess, tokenizer = model

    # Assume batch input is sent with mimetype:"text/csv"

    # Treat as single prediction input if no mimetype is set

    is_batch = kwargs["mimetype"] == "text/csv"

    if is_batch:

        input_pd = pd.read_csv(io.StringIO(data), sep="|")

        input_pairs = list(zip(input_pd["context"], input_pd["question"]))

        inputs = tokenizer.batch_encode_plus(

            input_pairs, add_special_tokens=True, padding=True, return_tensors="np"

        )

        input_ids = inputs["input_ids"]

        output = sess.run(["start_logits", "end_logits"], input_feed=dict(inputs))

        responses = []

        for i, row in input_pd.iterrows():

            answer = _get_answer_in_text(output, input_ids[i], i, tokenizer)

            response = {

                "context": row["context"],

                "question": row["question"],

                "answer": answer,

            }

            responses.append(response)

        to_return = json.dumps(

            {

                "predictions": responses

            }

        )

    else:

        data_dict = json.loads(data)

        context, question = data_dict["context"], data_dict["question"]

        inputs = tokenizer(

            question,

            context,

            add_special_tokens=True,

            padding=True,

            return_tensors="np",

        )

        input_ids = inputs["input_ids"][0]

        output = sess.run(["start_logits", "end_logits"], input_feed=dict(inputs))

        answer = _get_answer_in_text(output, input_ids, 0, tokenizer)

        to_return = json.dumps(

            {

                "context": context,

                "question": question,

                "answer": answer

            }

        )

    return to_return

Création de votre déploiement de modèle d’inférence personnalisé sur l’environnement de base ONNX de Simseo

Comme dernière modification, nous allons créer le déploiement de ce modèle personnalisé sur l’environnement de base ONNX de Simseo MLOps comme ci-dessous :

deployment = deploy_to_datarobot(BASE_PATH,

                                "ONNX",

                                "bert-onnx-questionAnswering",

                                "Pretrained BERT model, fine-tuned on SQUAD for question answering")

Lorsque le déploiement est prêt, nous testons notre modèle personnalisé avec notre entrée de test et nous nous assurons que nous obtenons des réponses à nos questions par notre LLM pré-formé :

datarobot_predict(test_input, deployment.id)

Comparaison des performances

Maintenant que tout est prêt, il est temps de comparer notre précédent déploiement Tensorflow avec l’alternative ONNX.

À des fins d’analyse comparative, nous avons contraint notre déploiement de modèle personnalisé à n’avoir que 4 Go de mémoire à partir de nos paramètres MLOps afin que nous puissions comparer les alternatives Tensorflow et ONNX sous des contraintes de ressources.

Comme le montrent les résultats ci-dessous, notre modèle dans ONNX prédit 1,5 fois plus rapidement que son homologue Tensorflow. Et ce résultat peut être vu à travers une simple exportation ONNX de base supplémentaire, (c’est-à-dire sans autres configurations d’optimisation, telles que la quantification).

Durée de la prédiction

En ce qui concerne la consommation de ressources, quelque part après ~ 100 lignes, notre déploiement de modèle Tensorflow commence à renvoyer des erreurs de mémoire insuffisante (OOM), ce qui signifie que ce modèle nécessiterait plus de 4 Go de mémoire pour traiter et prédire environ 100 lignes d’entrée. D’autre part, notre déploiement de modèle ONNX peut calculer des prédictions jusqu’à ~ 450 lignes sans générer d’erreur OOM. En conclusion de notre cas d’utilisation, le fait que le modèle Tensorflow gère jusqu’à 100 lignes, alors que son équivalent ONNX gère jusqu’à 450 lignes montre que le modèle ONNX est plus économe en ressources, car il utilise beaucoup moins de mémoire.

Commencez à tirer parti d’ONNX pour vos modèles personnalisés

En tirant parti de la norme open source ONNX et du runtime ONNX, les constructeurs d’IA peuvent tirer parti de l’interopérabilité du framework et des performances d’inférence accélérées, en particulier pour les grands modèles de langage basés sur des transformateurs sur leur environnement d’exécution préféré. Grâce à sa prise en charge native d’ONNX, Simseo MLOps permet aux organisations de tirer facilement parti de leurs déploiements d’apprentissage automatique avec une vitesse et un débit d’inférence optimisés.

Dans cet article de blog, nous avons montré à quel point il est facile d’utiliser un grand modèle de langage pour répondre aux questions dans ONNX en tant que modèle personnalisé Simseo et combien de performances d’inférence et d’efficacité des ressources vous pouvez gagner avec une simple étape de conversion. Pour répliquer ce flux de travail, vous pouvez trouver le bloc-notes de bout en bout sous le dépôt de la communauté Simseo, ainsi que de nombreux autres didacticiels pour donner aux constructeurs d’IA les capacités de Simseo.

1 ONNX Runtime, optimisations de modèles

2 Microsoft, Optimisation du modèle BERT pour les cœurs de processeur Intel à l’aide du fournisseur d’exécution par défaut du runtime ONNX

3 Blog Twitter, Accélérer l’inférence CPU Transformer dans Google Cloud

4 Philipp Schmid, accélère les transformateurs de phrases avec Hugging Face Optimum

5 Microsoft, Optimisation du modèle BERT pour les cœurs de processeur Intel à l’aide du fournisseur d’exécution par défaut du runtime ONNX