Перед переносом модели: как сравнить прогнозы двух сред исполнения

Перед заменой среды исполнения сравните прогнозы на одинаковых входах. Проверим численные допуски и отдельно найдём случаи, где небольшая разница меняет итоговое решение.

Экспорт меняет способ вычисления

Модель перенесли в другую среду исполнения, чтобы ускорить API. На первых запросах прогнозы почти совпадают, но точного побитового равенства нет. Это может быть нормальным следствием численной арифметики, порядка операций или пониженной точности. Одного взгляда на несколько округлённых чисел недостаточно, чтобы принять перенос.

Сначала подготовьте фиксированный набор входных тензоров и выходов эталонной версии. Сравнивайте одинаковые объекты, формы массивов, типы данных и порядок классов. Препроцессинг на этом этапе уже должен выдавать одинаковый вход: иначе вы смешаете ошибку подготовки данных с различием вычислительных сред. В набор включите обычные запросы, крайние значения и объекты около операционного порога.

Дальше задайте допустимое расхождение до просмотра результата. Абсолютный допуск помогает рядом с нулём, относительный — на больших значениях. Для вероятностей и денежных прогнозов разумные пределы будут разными. Выбирайте их по проверенной точности вычислений и влиянию на задачу, а не по желанию пропустить конкретный экспорт.

Два отчёта: близость чисел и совпадение решения

NumPy isclose проверяет условие abs(candidate−reference) ≤ atol + rtol·abs(reference). Эталон передаём вторым аргументом: относительный допуск считается именно от него. До сравнения явно проверяем формы, чтобы broadcasting не превратил ошибочную пару массивов в большую таблицу сравнений.

В примере все три значения укладываются в допуск, но один объект меняет бинарное решение при пороге 0,5. Выходы записаны как небольшой сохранённый результат двух прогонов. Код проверяет приёмочный отчёт, сам экспорт и runtime в нём не запускаются.

import numpy as np
reference = np.array([0.10, 0.4999, 0.90])
candidate = np.array([0.10001, 0.5001, 0.89999])
assert reference.shape == candidate.shape
assert np.isfinite(reference).all() and np.isfinite(candidate).all()
close = np.isclose(candidate, reference, rtol=1e-3, atol=1e-4)
changed = (candidate >= .5) != (reference >= .5)
print("max absolute delta:", float(np.max(np.abs(candidate-reference))))
print("within tolerance:", close.tolist())
print("changed decisions:", np.flatnonzero(changed).tolist())
assert close.all() and changed.sum() == 1

Все элементы окажутся близкими, а индекс 1 изменит решение с отрицательного на положительное. Это не повод автоматически отвергать перенос: нужно проверить частоту и стоимость таких переходов на представительном наборе. Если новая среда используется для ранжирования, дополнительно оцените состав выбранной очереди, потому что малые изменения около границы top-k тоже могут переставить объекты.

При расхождении двигайтесь от входа к выходу. Сравните сохранённый входной массив, затем доступные промежуточные результаты или отдельные подграфы. Не округляйте всё заранее до двух знаков: так пропадают полезные сведения о причине. Для NaN и бесконечностей задайте отдельное правило отказа, а не включайте их в нормальную близость.

После численного паритета пересчитайте целевую метрику на том же размеченном тесте. Особенно это важно при квантовании: допуск одного значения не описывает весь эффект на качество модели. Отдельно измерьте задержку и потребление памяти на целевом устройстве, включая размер батча и прогрев.

Приёмочный артефакт включает версии обеих сред, модель, типы входов, параметры допуска и список крупнейших расхождений с id. Сохраните его для следующего обновления зависимостей. Тогда перенос становится повторяемой инженерной проверкой, а новая версия runtime получает такое же понятное основание для внедрения, как сама модель.

Для следующего шага пригодится проверка RGB/BGR и нормализации входа.

В платном курсе «ML Engineer / Data Scientist: табличные модели в продакшн» вы соберёте воспроизводимый inference pipeline и доведёте его до пакетного расчёта и API. Сохранённые входы, модель и результаты помогают проверять работу пайплайна после переноса. Откройте программу курса.

Продолжить на практике

  • ML Engineer / Data Scientist: табличные модели в продакшн ↗

    Практический курс для тех, кто хочет получить навыки ML Engineer / Data Scientist на реальных табличных задачах. В курсе Вы не просто обучите CatBoost/LightGBM, а соберёте полноценный production-style пайплайн: подготовка данных, feature engineering (генерация признаков), корректная валидация, защита от leakage (утечек), тюнинг через Optuna, интерпретация через SHAP, batch-инференс и REST API для предсказаний.