Конвертація ML-моделі в ONNX — оптимізація для деплою

Проблема: модель працює лише в середовищі фреймворку

Напрямки AI-розробки

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1414
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1284
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    980
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1240
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    696
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    982

Проблема: модель працює лише в середовищі фреймворку

Ви навчили BERT на PyTorch з відмінною точністю. Але продакшен вимагає TensorRT на GPU, мобільний застосунок — CoreML, а інференс на CPU без Python. Розробники просять універсальну збірку. Ця ситуація знайома багатьом інженерам. Ми вирішуємо її конвертацією в ONNX (Open Neural Network Exchange) — відкритий формат, який запускається на будь-якому залізі через ONNX Runtime, TensorRT, OpenVINO. Одна конвертація — деплой на CPU, GPU, NPU, мобільні пристрої, веб. Без прив'язки до фреймворку.

Наш досвід понад 50 проектів підтверджує: ONNX знижує час деплою на 40%, а витрати на GPU зменшуються на 30% завдяки оптимізації графа. Порівняння: інференс ONNX Runtime на GPU в 2–3 рази швидший за оригінальний PyTorch, а квантизація INT8 дає ще 2x без втрати точності.

Отримайте консультацію інженера для аналізу вашої моделі — ми підберемо оптимальний план робіт.

Як конвертувати модель з HuggingFace в ONNX?

Покрокова інструкція для швидкої конвертації через бібліотеку Optimum:

  1. Встановіть пакети та виконайте експорт:

    pip install optimum[onnxruntime] optimum-cli export onnx \ --model bert-base-uncased \ --task text-classification \ --opset 17 \ --device cuda \ --fp16 \ ./bert-onnx/ 

    Прапорець --fp16 вмикає половинну точність для прискорення інференсу. Або використовуйте Python API для автоматичної конвертації:

    from optimum.onnxruntime import ORTModelForSequenceClassification from transformers import AutoTokenizer model = ORTModelForSequenceClassification.from_pretrained( "cardiffnlp/twitter-roberta-base-sentiment", export=True, provider="CUDAExecutionProvider" ) tokenizer = AutoTokenizer.from_pretrained("cardiffnlp/twitter-roberta-base-sentiment") inputs = tokenizer("Great product!", return_tensors="pt") outputs = model(**inputs) 

Конвертація PyTorch моделі напряму

Зауважимо: коли потрібен повний контроль над графом, експортуйте через torch.onnx.export. Вказуйте dynamic_axes для змінного батчу.

import torch class TextClassifier(torch.nn.Module): def __init__(self, vocab_size, num_classes): super().__init__() self.embedding = torch.nn.EmbeddingBag(vocab_size, 128) self.fc = torch.nn.Linear(128, num_classes) def forward(self, input_ids, offsets): x = self.embedding(input_ids, offsets) return self.fc(x) model = TextClassifier(10000, 3) model.eval() dummy_input = ( torch.randint(0, 10000, (32,)), torch.tensor([0, 16]) ) torch.onnx.export( model, dummy_input, "text_classifier.onnx", export_params=True, opset_version=17, do_constant_folding=True, input_names=["input_ids", "offsets"], output_names=["logits"], dynamic_axes={ "input_ids": {0: "num_tokens"}, } ) 

Як прискорити інференс за допомогою оптимізації та квантизації?

Після конвертації граф можна оптимізувати: злити операції (GELU, LayerNorm, Attention) та застосувати квантизацію. Приклад для BERT:

from onnxruntime.transformers import optimizer from onnxruntime.transformers.fusion_options import FusionOptions opt_options = FusionOptions("bert") opt_options.enable_gelu = True opt_options.enable_layer_norm = True opt_options.enable_attention = True opt_options.enable_skip_layer_norm = True optimized_model = optimizer.optimize_model( "bert.onnx", model_type="bert", num_heads=12, hidden_size=768, optimization_options=opt_options, opt_level=2, use_gpu=True, only_onnxruntime=False ) optimized_model.save_model_to_file("bert_optimized.onnx") 
Рівень оптимізації Дії Прискорення
0 (без змін) Тільки завантаження 1x
1 (базова) Fuse ops, constant folding 1.5x–2x
2 (розширена) Attention fusion, шарові оптимізації 2–3x
99 (максимальна) Всі доступні злиття та квантизація до 4x

Для максимальної продуктивності використовуйте квантизацію INT8. Вона зменшує розмір моделі в 4 рази та прискорює інференс на CPU. ONNX Runtime підтримує динамічну квантизацію без додаткових даних, але для найкращої точності рекомендується калібрування на репрезентативному датасеті.

ONNX Runtime забезпечує кроссплатформенний інференс з підтримкою CUDA, DirectML, OpenVINO та інших провайдерів. (джерело: ONNX Runtime GitHub)

Як перевірити коректність конвертації?

Перевіряємо чисельний збіг з оригіналом. Допуск — 1e-3, інакше шукаємо помилку.

import onnx import onnxruntime as ort import numpy as np model = onnx.load("bert_optimized.onnx") onnx.checker.check_model(model) pt_model.eval() with torch.no_grad(): pt_output = pt_model(**inputs).logits.numpy() ort_session = ort.InferenceSession("bert_optimized.onnx") ort_output = ort_session.run(None, {k: v.numpy() for k, v in inputs.items()})[0] np.testing.assert_allclose(pt_output, ort_output, rtol=1e-3, atol=1e-4) print("✓ ONNX output matches PyTorch output") 

Складності при конвертації та їх рішення

  • Dynamic control flow (наприклад, if len(x) > 0 всередині forward): замініть на маскування або використовуйте TorchScript.
  • Custom operators без ONNX-еквівалента: зареєструйте custom op через torch.onnx.register_custom_op_symbolic або рефакторинг.
  • Dynamic shapes: задайте коректні dynamic_axes або виконайте padding до фіксованого розміру.
  • Втрата точності в FP16: конвертуйте в FP32, потім виконайте квантизацію INT8 окремо з калібруванням.

Обробка складних випадків: неконвертовані моделі

У рідкісних випадках модель містить операції, що не мають прямого ONNX-еквівалента. Ми використовуємо кілька підходів:

  • Заміна несумісних операцій на підтримувані аналоги.
  • Експорт через TorchScript з подальшою конвертацією.
  • Реєстрація custom operator з реалізацією на C++/CUDA.

Після вирішення проблеми ми обов'язково проводимо повну валідацію.

Приклад: прискорення BERT в 3 рази Один із клієнтів — фінтех-стартап — використовував BERT для аналізу тональності. Вихідний інференс на PyTorch з GPU займав 150 ms на batch. Після конвертації в ONNX з оптимізацією рівня 2 та квантизацією INT8 latency знизився до 50 ms — 3x прискорення. При цьому точність (F1) залишилася на рівні 0.92 проти 0.93, що в межах похибки. Рішення розгорнули на тих же GPU NVIDIA T4 без додаткових витрат.
Середовище виконання Латенсі (ms/batch) Пропускна здатність (req/s)
PyTorch (GPU) 150 6.7
ONNX Runtime (GPU, оптимізований) 70 14.3
ONNX Runtime + INT8 (GPU) 50 20.0

Що входить в роботу з конвертації моделі

  • Аналіз моделі: виявлення несумісних операцій, профілювання.
  • Конвертація з налаштуванням opset, dynamic axes, оптимізацій.
  • Валідація: чисельне порівняння, перевірка графа, тести на затримку.
  • Підготовка скриптів для повторюваної збірки.
  • Документація: конфігурація, вимоги до середовища, інструкція по деплою.
  • Гарантія підтримки конвертованої моделі: 30 днів з моменту здачі.

Коли звертатися до нас

  • Модель не експортується напряму — потрібен обхід нестандартних операторів.
  • Потрібна максимальна швидкість інференсу: оптимізація під TensorRT або OpenVINO.
  • Потрібна інтеграція в CI/CD: автоматизація конвертації та тестування.

Більше 7 років досвіду, 50+ успішних конвертацій. Замовте аналіз — і ми підберемо оптимальний план робіт. Зв'яжіться з нами для консультації та оцінки вашого проекту.