Конвертація моделі у ONNX-формат

Проектуємо та впроваджуємо системи штучного інтелекту: від прототипу до production-ready рішення. Наша команда поєднує експертизу в машинному навчанні, дата-інжинірингу та MLOps, щоб AI працював не в лабораторії, а в реальному бізнесі.
Показано 1 з 1Усі 1566 послуг
Конвертація моделі у ONNX-формат
Середній
від 1 дня до 3 днів
Часті запитання

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

Етапи розробки AI-рішення

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

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

Конвертація моделей у формат ONNX

ONNX (Open Neural Network Exchange) - відкритий формат представлення ML-моделей, не прив'язаний до конкретного фреймворку. Конвертовану модель запускають ONNX Runtime, TensorRT, OpenVINO, CoreML – на CPU, GPU, NPU, мобільних пристроях.

Конвертація HuggingFace моделі через Optimum

# Установка
pip install optimum[onnxruntime]

# Экспорт через CLI
optimum-cli export onnx \
  --model bert-base-uncased \
  --task text-classification \
  --opset 17 \
  --device cuda \
  --fp16 \
  ./bert-onnx/
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")

# Использование идентично обычной HF модели
inputs = tokenizer("Great product!", return_tensors="pt")
outputs = model(**inputs)

Конвертація моделі PyTorch безпосередньо

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,)),    # input_ids
    torch.tensor([0, 16])               # offsets
)

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"},
    }
)

Оптимізація ONNX графа

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,            # 0=нет, 1=базовая, 2=расширенная, 99=все
    use_gpu=True,
    only_onnxruntime=False
)
optimized_model.save_model_to_file("bert_optimized.onnx")

Верифікація коректності конвертації

import onnx
import onnxruntime as ort
import numpy as np

# Проверка валидности модели
model = onnx.load("bert_optimized.onnx")
onnx.checker.check_model(model)

# Сравнение вывода с оригинальной PyTorch моделью
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 - ONNX не підтримує динамічний control flow. Рішення: уніфікація через masking чи конвертація через TorchScript.

Custom operators: оператори без ONNX еквівалента. Рішення: реєстрація custom op або рефакторинг із використанням стандартних операцій.

Dynamic shapes: деякі операції потребують статичних розмірностей. Рішення: правильна вказівка dynamic_axes або використання фіксованих розмірів із padding.

Numerical precision: накопичення помилок у довгих ланцюжках операцій при FP16. Рішення: конвертація у FP32, потім квантизація окремо.