
Откуда в обучении берётся nan: численная нестабильность в ML и почему всё считают в логарифмах
badcasedaily1 11 минут назад Откуда в обучении берётся nan: численная нестабильность в ML и почему всё считают в логарифмах Средний 9 мин 477 Блог компании OTUS Машинное обучение * Python * Программирование *...
Anthropic — What company has the best second artificial intelligence model at the end of June?
В сфере искусственного интеллекта произошло заметное событие. badcasedaily1 11 минут назад Откуда в обучении берётся nan: численная нестабильность в ML и почему всё считают в логарифмах Средний 9 мин 477 Блог компании OTUS Машинное обучение * Python * Программирование * Искусственный интеллект Туториал Модель обучается, loss падает, метрики растут. На какой‑то эпохе loss внезапно становится nan и больше не восстанавливается, как бы вы ни понижали learning rate. Или инференс на проде иногда возвращает вероятность ровно 1.
0 для класса, которого в обучающей выборке почти не было, а в логах при этом тихо мелькает RuntimeWarning: overflow encountered in exp. Код не менялся, данные те же, гиперпараметры те же. Просто в какой‑то момент промежуточное число вышло за границу того, что тип float умеет хранить, и дальше вся арифметика поехала.
Технические детали
Это не баг в данных и не плохо подобранный оптимизатор, а столкновение с тем, что число с плавающей точкой имеет конечный диапазон и конечную точность, а математика машинного обучения — экспоненты, произведения тысяч вероятностей, разности близких величин — упирается в эти границы постоянно. Разберём, где именно арифметика тут ломается, почему сквозное лекарство — переход в логарифмы, и какими готовыми примитивами это закрывается. Где у float заканчиваются числаFloat хранит число в фиксированном количестве бит, и отсюда следуют две независимые границы, которые часто путают.
Первая — диапазон: float32 представляет величины примерно до 3. 4·10³⁸, дальше inf, а снизу наименьшее нормальное число около 1. 18·10⁻³⁸, ещё ниже денормализация и ноль.
Вторая — точность: float32 хранит порядка семи значащих десятичных цифр, float64 — около пятнадцати‑шестнадцати, остальное отбрасывается. import numpy as np np. 4028235e+38 — дальше inf np.
Отраслевые последствия
1754944e-38 — наименьшее нормальное np. 1920929e-07 — машинный эпсилон np. 0Машинный эпсилон — наименьшее число, ещё отличимое от единицы при сложении, и для float32 он около 1.
Всё, что меньше, при сложении с единицей теряется бесследно:np. 0) # True — слагаемое исчезлоПоловинная точность, в которой сегодня по умолчанию идёт значительная часть обучения, ужимает обе границы радикально: float16 переполняется уже на 65504, а его наименьшее нормальное число около 6·10⁻⁵. bfloat16 устроен иначе, он сохраняет широкий диапазон экспоненты float32, жертвуя мантиссой, поэтому почти не переполняется, но хранит всего два‑три значащих знака.
Дальше станет понятно, почему именно переход на половинную точность вытаскивает наружу ошибки, незаметные в float64-ноутбуке.
Этот прогресс даёт важные сигналы о будущем отрасли, и технологический мир внимательно наблюдает.





