Зачем model.eval() важнее для инференса, чем вы думали
Вызов model.eval() в PyTorch делает две вещи: отключает dropout-слои и замораживает накопление статистики BatchNorm, переходя на постоянные среднее значение и дисперсию, вычисленные во время обучения. Пропуск этого вызова ведёт к недетерминированным предсказаниям даже для одного и того же входа.
На практике это означает, что модель, запущенная без eval(), будет давать разные выходы при каждом запуске, если в архитектуре есть BatchNorm или dropout. Проблема особенно заметна в production-системах, где ожидается стабильный результат.
Зачем это критично
Для открытых моделей, которые обучались с BatchNorm, пропуск eval() нарушает калибровку весов: модель работает с неправильной нормализацией, что может привести к смещению выходов или деградации точности на 5–15 процентов в зависимости от архитектуры.
Это особенно опасно при сравнении результатов инференса на разных машинах или при кэшировании предсказаний: без eval() каждый запуск может дать другой результат, что усложняет отладку и воспроизведение ошибок.
Хорошая практика — явно вызывать model.eval() перед инференсом и документировать это в коде, даже если выглядит очевидным. Для моделей без этапа обучения в пайпе хотя бы один раз убедиться, что eval() не меняет поведение модели.