Как стать автором
Обновить

Когда обучение не идет. Loss is NaN. Причины и решения

Уровень сложностиПростой
Время на прочтение2 мин
Количество просмотров978

Привет, это моя первая статья на Хабре. И я хочу рассказать вам о проблеме, на решение которой когда-то давно у меня ушло довольно много времени.

Часто бывает, что при обучении (или тестировании) модели нейронной сети (NN) функция потерь (loss) возвращает значение NaN (Not a Number). Это приводит к тому, что фаза обучения "срывается". Обычно неясно, почему это происходит. Я расскажу вам о возможных причинах и рекомендациях по решению этой проблемы.

Взрыв градиента

Существует две основные проблемы с градиентами на этапе обучения: исчезновение (vanishing) и взрыв (explosion) градиент. Первая описана в этих статьях:[1] [2]. Вторая будет рассмотрена здесь. Напомню, что при обратном распространении ошибки оптимизатор распространяет градиенты от последнего слоя к первому (хорошо описано в книге Тарика Рашида «Создаем нейронную сеть»). С помощью глубокой NN значения градиентов можно значительно увеличить (или уменьшить). Поэтому абсолютные значения становятся inf или NaN. Итак, есть несколько рекомендаций:

  1. Уменьшите начальную скорость обучения или/и используйте планировщик скорости обучения.

  2. Нормирование градиентов (clip)

Нормирование градиента с заданным гипер-параметром С
Нормирование градиента с заданным гипер-параметром С
# loss.backprop()
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm= C)
# optimizer.step()

Этот метод позволяет ограничить градиенты в диапазоне [-C..C].

3. Измените архитектуру текущей модели (количество слоев, голов, нейронов и т.д.) или используйте другую модель.

Конкретный слой в архитектуре

Некоторые слои могут выдавать NaN для определенных входных данных. Например, слой нормализации использует деление на норму вектора x

 

Норма L2 вектора X
Норма L2 вектора X

Но что, если заданный вектор x равен нулю, тогда и его норма. Это приводит к делению на ноль, следовательно, xnormed  =  inf (NaN). Очевидное решение - добавить небольшое ненулевое число (например, 10e-7) в знаменатель.

Норма L2 вектора X с исключением деления на ноль
Норма L2 вектора X с исключением деления на ноль

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

Производная от определенного слоя

Оптимизатор вычисляет производные функций потерь и слоев NN при обратном распространении. Рассмотрим слой standard-deviation-pooling, описанный здесь. Стандартное отклонение некоторого вектора x:

Стандартное отклонение вектора X
Стандартное отклонение вектора X

Давайте продифференцируем эту функцию по х:

Производная от стандартного отклонения
Производная от стандартного отклонения

Поэтому нам нужно нарушить уравнение (*). Самое простое решение - добавить к x_i небольшое число ε.

Функция потерь возвращает NaN

Давайте разберемся с средней абсолютной ошибкой (mean absolute error - MAE).

Производная от MAE
Производная от MAE

Итак, как показано выше, если любое из предсказанных моделью значений y_i равно целевому значению y^, производная функции потерь возвращает NaN. Вы можете заметить, что этот случай довольно редкий, но я думаю, что он все равно заслуживает вашего внимания :-)

Заключение

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

Теги:
Хабы:
+1
Комментарии1

Публикации

Работа

Data Scientist
42 вакансии

Ближайшие события