Гайд · TNWS AI
Как запустить ONNX-модель через InferenceSession в Python
Минимальная нейросетевая операция в ONNX Runtime: создание проверяемой модели Add, InferenceSession, float32-вход и точный ожидаемый массив.
Задача и применимость
Актуальный запрос: «как запустить ONNX модель через ONNX Runtime Python». Создать локальную ONNX-модель с операцией Add и выполнить её без загрузки сторонних весов. InferenceSession — основной Python-класс ONNX Runtime для загрузки и запуска модели. Вход передаётся словарём по имени, а список None в run запрашивает все выходы. Учебный граф прибавляет фиксированный bias [1, -1], поэтому его результат можно проверить арифметически. Материал сверён 26 сентября 2026 года с официальной документацией ONNX Runtime и фактически проверяется на ONNX Runtime 1.30.0, ONNX 1.19.0 и NumPy 2.3.5. Тестовая модель создаётся локально и не скачивает веса.
Пошаговое выполнение
- Создайте граф ONNX с входом и выходом float32 формы
[None,2]. - Проверьте модель через
onnx.checker.check_modelи сохраните во временный файл. - Создайте
InferenceSessionс явным CPUExecutionProvider. - Передайте массив
[[2,5]]и сравните результат с[[3,4]].
Сначала запускайте пример во временном каталоге. Для реальной модели зафиксируйте checksum, opset, версию exporter и preprocessing. ONNX Runtime исполняет граф, но не знает предметного смысла признаков, поэтому одинаковая shape ещё не доказывает правильную подготовку данных.
Готовый проверяемый шаблон
import tempfile
from pathlib import Path
import numpy as np
import onnx
from onnx import TensorProto, helper
import onnxruntime as ort
tmp = Path(tempfile.mkdtemp())
model_path = tmp / "add.onnx"
x_info = helper.make_tensor_value_info("x", TensorProto.FLOAT, [None, 2])
y_info = helper.make_tensor_value_info("y", TensorProto.FLOAT, [None, 2])
bias = helper.make_tensor("bias", TensorProto.FLOAT, [2], [1.0, -1.0])
node = helper.make_node("Add", ["x", "bias"], ["y"])
graph = helper.make_graph([node], "add_graph", [x_info], [y_info], [bias])
model = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 13)])
onnx.checker.check_model(model)
onnx.save(model, model_path)
session = ort.InferenceSession(str(model_path), providers=["CPUExecutionProvider"])
x = np.array([[2.0, 5.0]], dtype=np.float32)
y = session.run(None, {"x": x})[0]
np.testing.assert_allclose(y, [[3.0, 4.0]])
print(y)
Вход и ожидаемые данные
Вход — float32-массив формы (1,2) со значениями 2 и 5. Модель прибавляет [1,-1]; ожидаемый выход — 3 и 4 той же формы. Это арифметический тест runtime, а не полезная обученная нейросеть. Он нужен, чтобы отделить ошибки загрузки и подачи тензора от качества реальной модели.
Проверка результата
Проверяйте численно через np.testing.assert_allclose, а не визуально по print. Затем подайте две строки и ожидайте покомпонентное применение bias. Зафиксируйте providers и версии onnx, onnxruntime, NumPy. Если реальная модель даёт другие имена входа, не переименовывайте словарь наугад: сначала прочитайте метаданные сессии. Перед рабочим применением повторите проверку на точных входах экспортированной нейросети: универсальный пример не заменяет контракт конкретного артефакта. Сохраните минимальный воспроизводимый вход, чтобы сравнить старую и новую версии без персональных данных.
Как перенести пример на настоящую нейросеть
Заменяйте учебный граф только после того, как базовый пример проходит полностью. Получите имена, типы и формы через API сессии, затем воспроизведите тот же preprocessing, который использовался при обучении или экспорте. Для изображения это включает порядок каналов, resize, нормализацию и цветовое пространство; для текста — конкретный tokenizer, специальные токены, padding и attention mask. Эти параметры не восстанавливаются надёжно по одной форме tensor. Храните конфигурацию рядом с моделью и версионируйте её вместе с ONNX-файлом. Сначала сравните ONNX output с исходным framework на одинаковых входах, а затем отдельно проверяйте предметную метрику: accuracy, F1, Recall@k или другую заранее выбранную величину.
Критерии приёмки
- Модель проходит
onnx.checkerи загружается выбранным provider. - dtype, rank, shape и имена совпадают с метаданными.
- Положительный вход совпадает с численным эталоном.
- Негативный вход вызывает ожидаемую ошибку, а не случайный результат.
- Тест повторяется после смены модели, runtime или provider.
Регрессионный протокол
Сохраните версии пакетов, providers, имена tensor, shape и dtype. Используйте минимум пять входов: стандартный, другой batch, нули, отрицательные значения и граничный допустимый диапазон. Сравнивайте outputs с эталонной реализацией и явно задавайте абсолютный и относительный допуск. Измерение производительности отделяйте от проверки точности: сначала докажите эквивалентность, затем делайте прогрев и много повторов. Не выбирайте лучший прогон вручную — публикуйте p50, p95 и условия машины. Ошибка одного теста должна блокировать замену модели, но не требует останавливать независимые сервисы.
Диагностика расхождений
Если значения отличаются, локализуйте слой по порядку: исходный файл, preprocessing, dtype и shape, выбранный provider, затем численная точность операторов. Сохраните небольшой обезличенный вход и outputs обеих реализаций. Не начинайте с увеличения допуска: так можно скрыть переставленные каналы или неверную токенизацию. Для динамического batch проверяйте каждую строку отдельно и вместе, чтобы обнаружить ошибочную зависимость между элементами. Для stateful preprocessing сбрасывайте состояние между тестами. После исправления повторите весь набор, включая негативные случаи, а не только один пример, который раньше падал.
Типичные ошибки и чего не делать
- Не передавайте Python-список вместо массива без проверки dtype.
- Не считайте успешный run доказательством качества обученной модели.
- Не загружайте неизвестный ONNX-файл без контроля происхождения и ресурсов.
Не изменяйте модель, dtype или форму случайными преобразованиями, лишь бы исчезло исключение. Не используйте вход из недоверенного источника без ограничений размера: огромный tensor способен исчерпать память. Не выдавайте арифметический мини-граф за оценку качества настоящей нейросети.
FAQ
Что такое InferenceSession?
Основной класс для загрузки и запуска ONNX-модели.
Почему float32?
Такой тип объявлен у входа тестовой модели.
Что означает None в run?
Запросить все выходы модели.
Официальные источники
Частые вопросы
Что такое InferenceSession?
Основной класс для загрузки и запуска ONNX-модели.
Почему float32?
Такой тип объявлен у входа тестовой модели.
Что означает None в run?
Запросить все выходы модели.
Читайте также
Как использовать I/O Binding ONNX Runtime на CPU
I/O Binding в Python на CPU: OrtValue из NumPy, bind_ortvalue_input, bind_output, run_with_iobinding и точная проверка результата.
Как настроить intra-op потоки ONNX Runtime через SessionOptions
SessionOptions и intra_op_num_threads в ONNX Runtime: два потока, воспроизводимый output, честный benchmark и почему больше потоков не всегда быстрее.
Как проверить Execution Provider ONNX Runtime и не ждать GPU зря
Проверка get_available_providers и session.get_providers: явный CPUExecutionProvider, отличие установленного provider от выбранного и безопасный fallback.
Комментарии
Пока тихо. Скажите первое слово