Гайд · TNWS AI

Как сохранить оптимизированный граф ONNX Runtime при создании сессии

4 мин—

Сохранение optimized_model_filepath в ONNX Runtime: исходный и оптимизированный файлы, проверка одинакового output и ограничения переносимости.

Задача и применимость

Актуальный запрос: «как сохранить optimized model ONNX Runtime SessionOptions». Получить отдельный оптимизированный артефакт и проверить эквивалентность на эталонных входах. SessionOptions.optimized_model_filepath просит runtime сохранить граф после применённых оптимизаций при создании сессии. Размер файла не обязан уменьшиться, а переносимость оптимизированного графа зависит от формата, версии и execution provider; исходную модель сохраняют отдельно. Материал сверён 26 сентября 2026 года с официальной документацией ONNX Runtime и фактически проверяется на ONNX Runtime 1.30.0, ONNX 1.19.0 и NumPy 2.3.5. Тестовая модель создаётся локально и не скачивает веса.

Пошаговое выполнение

  1. Задайте путь во временном каталоге до создания сессии.
  2. Создайте SessionOptions и укажите optimized_model_filepath.
  3. Инициализируйте CPU-сессию и убедитесь, что файл появился.
  4. Загрузите оптимизированный файл новой сессией и сравните outputs.

Сначала запускайте пример во временном каталоге. Для реальной модели зафиксируйте 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)
optimized=tmp/"add.optimized.onnx"
options=ort.SessionOptions()
options.optimized_model_filepath=str(optimized)
session=ort.InferenceSession(str(model_path),sess_options=options,providers=["CPUExecutionProvider"])
assert optimized.exists() and optimized.stat().st_size>0
x=np.array([[2,5]],dtype=np.float32)
expected=session.run(None,{"x":x})[0]
session2=ort.InferenceSession(str(optimized),providers=["CPUExecutionProvider"])
actual=session2.run(None,{"x":x})[0]
np.testing.assert_allclose(actual,expected)

Вход и ожидаемые данные

После создания первой сессии существует непустой add.optimized.onnx. Обе сессии на input [2,5] возвращают [3,4]. На маленьком Add-графе размер или скорость могут не улучшиться. Цель примера — правильный lifecycle и тест эквивалентности, а не маркетинговое обещание ускорения.

Проверка результата

Сравните исходную и оптимизированную модель на наборе нормальных и крайних входов с согласованным допуском. Измерьте cold start и прогретую latency отдельно. Храните сведения о версии runtime и provider рядом с артефактом. Если модель должна работать на разных устройствах, проверяйте каждую целевую конфигурацию. Перед рабочим применением повторите проверку на точных входах экспортированной нейросети: универсальный пример не заменяет контракт конкретного артефакта. Сохраните минимальный воспроизводимый вход, чтобы сравнить старую и новую версии без персональных данных.

Как перенести пример на настоящую нейросеть

Заменяйте учебный граф только после того, как базовый пример проходит полностью. Получите имена, типы и формы через API сессии, затем воспроизведите тот же preprocessing, который использовался при обучении или экспорте. Для изображения это включает порядок каналов, resize, нормализацию и цветовое пространство; для текста — конкретный tokenizer, специальные токены, padding и attention mask. Эти параметры не восстанавливаются надёжно по одной форме tensor. Храните конфигурацию рядом с моделью и версионируйте её вместе с ONNX-файлом. Сначала сравните ONNX output с исходным framework на одинаковых входах, а затем отдельно проверяйте предметную метрику: accuracy, F1, Recall@k или другую заранее выбранную величину.

Критерии приёмки

  1. Модель проходит onnx.checker и загружается выбранным provider.
  2. dtype, rank, shape и имена совпадают с метаданными.
  3. Положительный вход совпадает с численным эталоном.
  4. Негативный вход вызывает ожидаемую ошибку, а не случайный результат.
  5. Тест повторяется после смены модели, runtime или provider.

Регрессионный протокол

Сохраните версии пакетов, providers, имена tensor, shape и dtype. Используйте минимум пять входов: стандартный, другой batch, нули, отрицательные значения и граничный допустимый диапазон. Сравнивайте outputs с эталонной реализацией и явно задавайте абсолютный и относительный допуск. Измерение производительности отделяйте от проверки точности: сначала докажите эквивалентность, затем делайте прогрев и много повторов. Не выбирайте лучший прогон вручную — публикуйте p50, p95 и условия машины. Ошибка одного теста должна блокировать замену модели, но не требует останавливать независимые сервисы.

Диагностика расхождений

Если значения отличаются, локализуйте слой по порядку: исходный файл, preprocessing, dtype и shape, выбранный provider, затем численная точность операторов. Сохраните небольшой обезличенный вход и outputs обеих реализаций. Не начинайте с увеличения допуска: так можно скрыть переставленные каналы или неверную токенизацию. Для динамического batch проверяйте каждую строку отдельно и вместе, чтобы обнаружить ошибочную зависимость между элементами. Для stateful preprocessing сбрасывайте состояние между тестами. После исправления повторите весь набор, включая негативные случаи, а не только один пример, который раньше падал.

Типичные ошибки и чего не делать

  • Не удаляйте исходную модель сразу после создания оптимизированной.
  • Не судите об оптимизации только по размеру файла.
  • Не переносите артефакт между providers и версиями без теста.

Не изменяйте модель, dtype или форму случайными преобразованиями, лишь бы исчезло исключение. Не используйте вход из недоверенного источника без ограничений размера: огромный tensor способен исчерпать память. Не выдавайте арифметический мини-граф за оценку качества настоящей нейросети.

FAQ

Когда создаётся файл?

При инициализации сессии с заданным optimized_model_filepath.

Всегда ли он меньше?

Нет, это не критерий корректности или скорости.

Что проверять после сохранения?

Численную эквивалентность и производительность на целевой среде.

Официальные источники

Частые вопросы

Когда создаётся файл?

При инициализации сессии с заданным optimized_model_filepath.

Всегда ли он меньше?

Нет, это не критерий корректности или скорости.

Что проверять после сохранения?

Численную эквивалентность и производительность на целевой среде.

Читайте также

Комментарии

Пока тихо. Скажите первое слово