Salut tout le monde, Nina ici, de retour sur agntbox.com ! Aujourd’hui, je veux parler de quelque chose qui fait beaucoup de bruit dans mes canaux Slack et qui hante mes sessions de codage tard dans la nuit : les frameworks d’IA. Plus précisément, je souhaite explorer un coin particulier qui est souvent négligé alors que tout le monde s’affaire à poursuivre le dernier LLM : les outils autour du fine-tuning et du déploiement pour des modèles plus petits et plus spécialisés.
Nous connaissons tous les grands noms – TensorFlow, PyTorch. Ce sont les géants, les acteurs établis. Et à juste titre ! Ils sont incroyablement puissants et polyvalents. Mais soyons réalistes, parfois vous n’avez pas besoin d’un porte-avions pour traverser un étang. Parfois, vous avez besoin d’un hors-bord agile, surtout lorsque vous travaillez avec un délai serré, sur un ensemble de données spécifique et un objectif clair en tête. C’est là que je veux parler de quelque chose avec lequel je me sens assez à l’aise ces derniers temps : Hugging Face Optimum pour ONNX Runtime.
Maintenant, avant que vos yeux ne se perdent dans les acronymes, laissez-moi m’expliquer. Hugging Face, bien sûr, est le chouchou du monde du NLP, rendant les modèles pré-entraînés accessibles à tous. ONNX (Open Neural Network Exchange) est un standard ouvert pour représenter les modèles d’apprentissage automatique, ce qui signifie essentiellement que vous pouvez convertir des modèles entraînés dans un cadre (comme PyTorch) et les exécuter dans un autre (comme TensorFlow, ou dans notre cas, ONNX Runtime). Et ONNX Runtime ? C’est le moteur d’inférence haute performance de Microsoft.
Alors, que fait Hugging Face Optimum pour ONNX Runtime ? C’est essentiellement un pont, un optimiseur et un assistant de déploiement réunis en un. Il vous aide à prendre vos modèles Hugging Face, à les optimiser pour l’inférence ONNX Runtime, et souvent, à obtenir un gain de vitesse significatif sans sacrifier beaucoup (ou aucune) précision. Et ça, mes amis, ça vaut de l’or.
Pourquoi je suis obsédée par Optimum ONNX Runtime en ce moment
Mon parcours avec Optimum ONNX Runtime a commencé, comme la plupart de mes obsessions technologiques, avec un problème. Je travaillais sur un projet pour un client qui impliquait le déploiement d’un modèle BERT relativement petit pour la classification de texte sur des tickets de support client. Le modèle avait été entraîné sur un ensemble de données personnalisé, et bien qu’il fonctionnât très bien, le temps d’inférence était juste un peu trop lent pour une interaction client en temps réel. Nous parlions d’environ 150-200ms par inférence sur un GPU puissant, ce qui n’est pas terrible, mais pour des applications à fort volume et en temps réel, chaque milliseconde compte.
J’ai essayé tous les suspects habituels : le batching, l’optimisation des pipelines d’entrée, même quelques quantifications de base. Nous avons obtenu quelques améliorations, mais rien de dramatique. Puis, un collègue a mentionné Optimum, et spécifiquement, son intégration avec ONNX. J’étais sceptique au début. Une autre couche d’abstraction ? Plus de dépendances ? Mais j’étais désespérée, alors je me suis lancée.
Ce que j’ai découvert était un flux de travail étonnamment simple qui produisait des résultats. Nous avons réussi à réduire notre temps d’inférence à environ 50-70ms par inférence sur le même GPU, et nous avons même vu des performances décentes sur un CPU pour des tâches moins critiques. C’est un gain de 2 à 3 fois, ce qui dans le monde de l’IA en temps réel est une énorme victoire. Cela signifiait que nous pouvions évoluer notre service beaucoup plus efficacement et fournir des réponses plus rapides aux clients, impactant directement leur expérience.
Le problème qu’il résout : Performance et Portabilité
Soyons honnêtes, déployer des modèles d’IA peut être un vrai casse-tête. Vous entraînez un beau modèle dans PyTorch, puis vous devez figurez comment le faire fonctionner efficacement en production. Parfois, vous êtes coincé avec une configuration matérielle spécifique, ou vous devez déployer sur un appareil de périphérie avec des ressources limitées. C’est ici que l’ONNX entre en jeu. Il fournit un format commun, découplant votre modèle du cadre d’entraînement.
Optimum va encore plus loin. Il ne s’agit pas seulement de convertir en ONNX ; il s’agit d’optimiser ce modèle ONNX. Il peut appliquer des techniques comme l’optimisation de graphes, la fusion d’opérateurs, et même quantifier votre modèle pour réduire sa taille et accélérer l’inférence, souvent avec un impact minimal sur la précision. Cela est particulièrement utile pour les modèles plus petits ou lorsque vous êtes limité par la mémoire ou le calcul sur votre cible de déploiement.
Le cas d’utilisation de mon client était un parfait exemple. Nous avions un modèle PyTorch, mais nous voulions le déployer sur une instance cloud avec des GPU NVIDIA, et nous avions besoin d’un débit maximal. Optimum ONNX Runtime nous a permis d’exporter le modèle, d’appliquer des optimisations spécifiques pour notre matériel cible, et de le faire fonctionner comme un rêve.
Commencer avec Optimum ONNX Runtime : Un Exemples Pratique
Passons en revue un exemple de base de la manière dont vous pourriez utiliser Optimum pour exporter et optimiser un modèle Hugging Face pour ONNX Runtime. Pour cela, nous utiliserons un modèle simple d’analyse de sentiment.
Tout d’abord, vous aurez besoin d’installer les bibliothèques nécessaires :
pip install transformers optimum[onnxruntime] onnx
Maintenant, écrivons un peu de code Python pour exporter un modèle pré-entraîné d’analyse de sentiment.
Exemple 1 : Exportation d’un Modèle d’Analyse de Sentiment
Ici, nous prenons un modèle standard `distilbert-base-uncased-finetuned-sst-2-english` et l’exportons au format ONNX en utilisant Optimum.
from transformers import pipeline
from optimum.onnxruntime import ORTModelForSequenceClassification
from transformers import AutoTokenizer
model_id = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(model_id)
# Exporter le modèle au format ONNX
# Le `save_directory` est où votre modèle ONNX et votre tokenizer seront sauvegardés.
# `opset` spécifie la version de l'ensemble d'opérateurs ONNX.
# `input_names` sont importants pour définir les entrées de votre graphe ONNX.
onnx_path = "./onnx_sentiment_model/"
ort_model = ORTModelForSequenceClassification.from_pretrained(model_id, from_transformers=True)
ort_model.save_pretrained(onnx_path)
tokenizer.save_pretrained(onnx_path)
print(f"Modèle et tokenizer exportés vers {onnx_path}")
Après avoir exécuté cela, vous aurez un répertoire nommé `onnx_sentiment_model` contenant votre fichier `model.onnx` et les fichiers tokenizer. Ce fichier `model.onnx` est la version optimisée prête pour ONNX Runtime.
Exemple 2 : Exécution d’Inférences avec le Modèle ONNX
Maintenant, chargeons ce modèle exporté et exécutons quelques inférences avec. Remarquez comment nous chargeons `ORTModelForSequenceClassification` directement depuis le `onnx_path` où nous avons sauvegardé.
from optimum.onnxruntime import ORTModelForSequenceClassification
from transformers import AutoTokenizer, pipeline
import time
onnx_path = "./onnx_sentiment_model/"
# Charger le modèle ONNX et le tokenizer
ort_model = ORTModelForSequenceClassification.from_pretrained(onnx_path)
tokenizer = AutoTokenizer.from_pretrained(onnx_path)
# Créer un pipeline pour une inférence facile
onnx_pipeline = pipeline(
"sentiment-analysis",
model=ort_model,
tokenizer=tokenizer,
accelerator="ort" # Cela indique au pipeline d'utiliser ONNX Runtime
)
text_samples = [
"J'adore ce produit, c'est incroyable !",
"Ce film était juste correct, un peu ennuyeux.",
"Je déteste absolument attendre dans de longues files.",
"Le service était incroyablement rapide et efficace."
]
print("\n--- Exécution d'Inference avec le Modèle ONNX ---")
start_time = time.time()
results = onnx_pipeline(text_samples)
end_time = time.time()
for i, res in enumerate(results):
print(f"Texte : '{text_samples[i]}' -> Étiquette : {res['label']}, Score : {res['score']:.4f}")
print(f"Temps d'inférence pour {len(text_samples)} échantillons : {(end_time - start_time):.4f} secondes")
Lorsque vous exécutez cela, vous verrez les prédictions de sentiment. Plus important encore, si vous deviez comparer le temps d’inférence avec le modèle PyTorch original sur le même matériel, vous obtiendriez probablement un gain de vitesse notable, surtout pour des lots plus importants ou des modèles plus complexes. Le paramètre `accelerator=”ort”` dans le pipeline est un petit mais puissant indicateur qui dit à Hugging Face d’utiliser ONNX Runtime pour l’inférence, c’est là que la magie opère.
Exemple 3 : Contrôler les Fonctionnalités d’Optimisation (Optionnel mais Puissant)
Optimum permet un contrôle fin sur le processus d’optimisation. Par exemple, vous pouvez spécifier le niveau d’optimisation ou même choisir des optimisations graphiques spécifiques. Cela peut être crucial lorsque vous essayez de tirer chaque dernier goutte de performance de votre modèle ou lorsque vous devez faire des compromis entre vitesse et précision (par exemple, avec la quantification).
from optimum.onnxruntime import ORTModelForSequenceClassification, ORTConfig
from transformers import AutoTokenizer
from optimum.exporters.tasks import TasksManager
from optimum.onnxruntime.configuration import AutoOptimizationConfig
model_id = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(model_id)
# Définir la configuration d'optimisation
# Ici, nous utilisons l'optimisation par défaut mais vous pouvez personnaliser davantage
# Par exemple, pour appliquer la quantification : `optimization_config = AutoOptimizationConfig.O2()`
optimization_config = AutoOptimizationConfig.O1() # O1 pour l'optimisation de base, O2 pour plus d'agressivité, O3 pour complet
# Exporter le modèle avec la configuration d'optimisation explicite
onnx_path_optimized = "./onnx_sentiment_model_optimized/"
task = TasksManager.get_task_from_model_or_model_name(model_id)
# Vous devrez peut-être ajuster le paramètre `feature` en fonction de la tâche de votre modèle
# Pour la classification de séquences, c'est souvent 'sequence-classification'
ORTModelForSequenceClassification.from_pretrained(
model_id,
from_transformers=True,
export_feature=task.feature,
optimization_config=optimization_config,
).save_pretrained(onnx_path_optimized)
tokenizer.save_pretrained(onnx_path_optimized)
print(f"Modèle optimisé et tokenizer exportés vers {onnx_path_optimized}")
Le `AutoOptimizationConfig` est votre ami ici. `O1` fournit des optimisations graphiques de base, `O2` ajoute une fusion plus agressive et des éliminations de nœuds, et `O3` inclut toutes les optimisations disponibles, y compris la quantification si applicable. Choisir le bon niveau dépend de vos besoins spécifiques et du matériel que vous ciblez. Pour mon client, nous avons expérimenté entre `O1` et `O2` pour trouver le meilleur compromis, en nous dirigeant vers `O2` pour le meilleur équilibre entre vitesse et précision.
Mes Retours et Ce Qui Suivant
Mon expérience avec Hugging Face Optimum pour ONNX Runtime a été extrêmement positive. Ce n’est pas une solution miracle pour chaque déploiement d’IA, mais elle répond à un besoin très courant et critique : faire fonctionner vos modèles plus vite et plus efficacement en production, surtout lorsque vous travaillez avec des modèles Hugging Face.
- Amélioration des performances : Le principal avantage est la réduction significative du temps d’inférence. Pour les applications en temps réel, cela peut entraîner un changement significatif, améliorant l’expérience utilisateur et réduisant les coûts d’infrastructure.
- Portabilité : En convertissant en ONNX, vos modèles deviennent plus portables, exécutables sur différents matériels et systèmes d’exploitation sans être liés à un cadre d’apprentissage profond spécifique.
- Facilité d’utilisation : L’intégration avec la bibliothèque `transformers` de Hugging Face est remarquablement fluide. Si vous êtes déjà familier avec Hugging Face, la courbe d’apprentissage pour Optimum est assez douce.
- Efficacité des ressources : Les modèles optimisés nécessitent souvent moins de mémoire et de cycles CPU/GPU, ce qui est crucial pour les déploiements sur le terrain ou dans des environnements cloud sensibles aux coûts.
Une chose que j’ai apprise est qu’il vaut la peine d’expérimenter avec différents niveaux et configurations d’optimisation. Ne vous contentez pas des paramètres par défaut. Essayez `O1`, `O2`, et même `O3` (avec quantification si votre cas d’utilisation le permet) et évaluez les résultats sur votre matériel cible réel. Les gains peuvent être surprenants !
En regardant vers l’avenir, je crois que des outils comme Hugging Face Optimum vont devenir encore plus essentiels. Alors que les modèles d’IA prolifèrent et s’intègrent à des environnements de déploiement plus diversifiés, la capacité d’optimiser et de rationaliser leur inférence sera primordiale. Je suis particulièrement impatient de voir comment Optimum évoluera avec de nouveaux accélérateurs matériels et des techniques de quantification plus avancées.
Conseils pratiques pour votre prochain projet d’IA :
- Évaluez vos besoins en inférence : Avant d’explorer l’optimisation, définissez clairement vos exigences de performance. Quelle est une latence acceptable ? Quel est votre objectif de débit ?
- Considérez ONNX tôt : Si vous utilisez des modèles Hugging Face et que la performance est une préoccupation, commencez à penser à l’exportation et à l’optimisation ONNX pendant votre cycle de développement, pas seulement au déploiement.
- Évaluez, Évaluez, Évaluez : Mesurez toujours l’amélioration (ou la dégradation) réelle des performances après avoir appliqué des optimisations. Ne vous fiez pas aux gains théoriques. Utilisez des données réelles et du matériel réel.
- Expérimentez avec les niveaux d’optimisation : Ne vous contentez pas des paramètres par défaut. Jouez avec `AutoOptimizationConfig.O1()`, `O2()`, et `O3()` pour trouver le meilleur équilibre pour votre modèle et votre cas d’utilisation.
- Restez informé : La bibliothèque Hugging Face Optimum est en développement actif. Gardez un œil sur leurs publications et leur documentation pour de nouvelles fonctionnalités et améliorations de performances.
C’est tout pour moi cette semaine ! Si vous avez des difficultés avec la performance de déploiement de modèles, essayez Hugging Face Optimum pour ONNX Runtime. Cela pourrait être le speedboat dont vous avez besoin. Faites-moi savoir dans les commentaires si vous l’avez utilisé ou si vous avez d’autres outils préférés pour l’optimisation des modèles. Bon inférence !
🕒 Published: