Почему перед тестированием модели нужно перевести модель в режим инференса (model.eval())
Что проверяют
Понимаете ли вы, что часть слоёв ведёт себя по-разному при обучении и при предсказании, и различаете ли переключение режима и отключение градиентов. Это две разные вещи, и на собеседовании их смешивают чаще всего.
Как отвечать
model.eval() выставляет всем модулям флаг, что обучение выключено. Влияет это там, где поведение от режима зависит:
- dropout перестаёт зануливать активации, и в предсказании участвует вся сеть;
- батч-нормализация перестаёт считать статистику по текущему батчу и берёт накопленные скользящие среднее и дисперсию, а также перестаёт их обновлять.
Без переключения предсказания становятся случайными от запуска к запуску и начинают зависеть от состава батча: один и тот же объект в разных батчах получит разный ответ. Метрики при этом занижены, а на маленьких батчах ещё и нестабильны, плюс валидационные данные незаметно портят накопленную статистику нормализации.
Отдельно сказать, что память и скорость этот вызов не меняет: граф для обратного прохода всё равно строится. За это отвечают torch.no_grad() или torch.inference_mode(), ими оборачивают цикл валидации. И что перед возвратом к обучению нужен model.train().
Где спотыкаются
Называют переключение режима оптимизацией по скорости и памяти. Это смена поведения слоёв, а не режим экономии: без отключения градиентов валидация продолжит копить граф и упрётся в память на большой выборке.
Считают, что достаточно отключить градиенты. Градиенты действительно не посчитаются, но dropout продолжит выбрасывать нейроны, а нормализация продолжит пересчитывать статистику по батчам валидации.
Забывают вернуть модель в режим обучения после валидации внутри эпохи. Симптом коварный: ошибка на обучении внезапно падает, качество на отложенной выборке не растёт, а причину ищут в данных и в скорости обучения.