Потеря NaN при тренировке регрессионной сети
У меня есть матрица данных в "однократной кодировке" (все единицы и нули) с 260 000 строк и 35 столбцов. Я использую Keras для обучения простой нейронной сети для прогнозирования непрерывной переменной. Код для создания сети следующий:
model = Sequential()
model.add(Dense(1024, input_shape=(n_train,)))
model.add(Activation('relu'))
model.add(Dropout(0.1))
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.1))
model.add(Dense(256))
model.add(Activation('relu'))
model.add(Dropout(0.1))
model.add(Dense(1))
sgd = SGD(lr=0.01, nesterov=True);
#rms = RMSprop()
#model.compile(loss='categorical_crossentropy', optimizer=rms, metrics=['accuracy'])
model.compile(loss='mean_absolute_error', optimizer=sgd)
model.fit(X_train, Y_train, batch_size=32, nb_epoch=3, verbose=1, validation_data=(X_test,Y_test), callbacks=[EarlyStopping(monitor='val_loss', patience=4)] )
Однако в процессе обучения я вижу, что потеря уменьшается красиво, но в середине второй эпохи она идет на nan:
Train on 260000 samples, validate on 64905 samples
Epoch 1/3
260000/260000 [==============================] - 254s - loss: 16.2775 - val_loss:
13.4925
Epoch 2/3
88448/260000 [=========>....................] - ETA: 161s - loss: nan
Я попытался использовать RMSProp
вместо SGD
, я попробовал tanh
вместо relu
, я пробовал с и без выпада, все безрезультатно. Я попытался использовать меньшую модель, т.е. Только с одним скрытым слоем и с той же проблемой (она становится нан в другой точке). Однако он работает с меньшими возможностями, т.е. Если имеется только 5 столбцов и дает неплохие прогнозы. Кажется, что есть что-то переполнение, но я не могу себе представить, почему - потеря не является неоправданно большой.
Python версия 2.7.11, работающая на Linux-машине, только CPU. Я тестировал его с последней версией Theano, и я также получаю Nans, поэтому я попытался перейти к Theano 0.8.2 и иметь такую же проблему. С последней версией Keras такая же проблема, а также с версией 0.3.2.
Ответы
Ответ 1
Регрессия с нейронными сетями трудно получить, потому что вывод неограничен, поэтому вы особенно склонны к проблеме взрывающихся градиентов (вероятная причина nans),
Исторически одним из ключевых решений для взрывающихся градиентов было снижение скорости обучения, но с появлением алгоритмов адаптивной скорости обучения для каждого параметра, таких как Адам, вам больше не нужно устанавливать скорость обучения, чтобы получить хорошую производительность. Существует очень мало оснований использовать SGD с импульсом больше, если вы не являетесь нервным сетью и не знаете, как настроить график обучения.
Вот некоторые вещи, которые вы могли бы попробовать:
-
Нормализовать ваши результаты с помощью квантильной нормализации или z скоринга. Чтобы быть строгим, вычислите это преобразование на данных обучения, а не на весь набор данных. Например, при нормализации квантилей, если пример находится в 60-м процентиле обучающего набора, он получает значение 0,6. (Вы можете также сдвинуть нормированные значения квантиля на 0,5, чтобы 0-й процентиль составлял -0,5, а 100-й процентиль - +0,5).
-
Добавьте регуляризацию, либо увеличив скорость отсева, либо добавив штрафы L1 и L2 к весам. Регуляция L1 аналогична выбору элементов, и поскольку вы сказали, что уменьшение числа функций до 5 дает хорошую производительность, L1 также может быть.
-
Если это все еще не помогает, уменьшите размер вашей сети. Это не всегда лучшая идея, так как это может нанести вред производительности, но в вашем случае у вас есть большое количество нейронов первого уровня (1024) по сравнению с функциями ввода (35), поэтому это может помочь.
-
Увеличьте размер партии от 32 до 128. 128 довольно стандартный и потенциально может повысить стабильность оптимизации.
Ответ 2
Ответ на 1 "неплох. Однако все исправления, по-видимому, устраняют проблему косвенно, а не напрямую. Я бы рекомендовал использовать градиентную обрезку, которая будет просто скопировать любые градиенты, которые превышают определенное значение.
В Keras вы можете использовать clipnorm=1
(см. https://keras.io/optimizers/), чтобы просто скопировать все градиенты с нормой выше 1.
Ответ 3
Я сталкивался с той же проблемой раньше. Я ищу и нахожу этот вопрос и ответы. Все упомянутые выше уловки важны для обучения глубокой нейронной сети. Я перепробовал их все, но все равно получил NAN.
Я также нахожу этот вопрос здесь. https://github.com/fchollet/keras/issues/2134.
Я процитировал резюме автора следующим образом:
"Я хотел бы указать на это, чтобы он был заархивирован для тех, кто может испытать эту проблему в будущем. Я столкнулся с моей функцией потери неожиданно возвращая нянь после того, как он зашел так далеко в тренировочный процесс. Я проверил реус, оптимизатор, функцию потерь, мой отсев в в соответствии с реусом, размером моей сети и формой сеть. Я все еще получал потери, которые в конечном итоге превратились в нан и я очень расстроился.
Затем меня осенило. У меня может быть плохой вклад. Оказывается, один из изображения, которые я передавал на мой CNN (и делал нормальную нормализацию на) было только 0. Я не проверял этот случай, когда я вычел среднее и нормализовал по стандартному отклонению и, таким образом, я в конечном итоге с образцом матрицы, которая была ничем иным, как нан. Однажды я исправил мою функцию нормализации, теперь моя сеть работает отлично.
Я согласен с приведенной выше точкой зрения: вход чувствителен для вашей сети. В моем случае, я использую лог-значение оценки плотности в качестве входных данных. Абсолютное значение может быть очень большим, что может привести к NaN после нескольких шагов градиента. Я думаю, что проверка ввода необходима. Во-первых, вы должны убедиться, что входные данные не содержат include -inf или inf, а также некоторые чрезвычайно большие числа в абсолютном значении.
Ответ 4
Я столкнулся с очень похожей проблемой, и вот как я ее запустил.
Первое, что вы можете попробовать, это изменить активацию на LeakyReLU вместо использования Relu или Tanh. Причина в том, что часто многие узлы в ваших слоях имеют активацию нуля, и обратное распространение не обновляет веса для этих узлов, потому что их градиент также равен нулю. Это также называется проблемой "умирающего ReLU" (вы можете прочитать об этом здесь: https://datascience.stackexchange.com/questions/5706/what-is-the-dying-relu-problem-in-neural-networks).
Для этого вы можете импортировать активацию LeakyReLU, используя:
from keras.layers.advanced_activations import LeakyReLU
и включите его в свои слои следующим образом:
model.add(Dense(800,input_shape=(num_inputs,)))
model.add(LeakyReLU(alpha=0.1))
Кроме того, возможно, что выходная функция (непрерывная переменная, которую вы пытаетесь предсказать) является несбалансированным набором данных и имеет слишком много нулей. Одним из способов решения этой проблемы является использование сглаживания. Вы можете сделать это, добавив 1 к числителю всех ваших значений в этом столбце и разделив каждое из значений в этом столбце на 1/(среднее всех значений в этом столбце)
Это существенно сдвигает все значения от 0 до значения больше 0 (которое может быть очень маленьким). Это препятствует тому, чтобы кривая предсказывала 0 с и минимизировала потери (в конечном счете делая это NaN). Меньшие значения влияют сильнее, чем большие значения, но в целом среднее значение набора данных остается тем же.
Ответ 5
Я столкнулся с той же проблемой при использовании LSTM, проблема в том, что мои данные после стандартизации имеют некоторое значение nan, поэтому мы должны проверить входные данные модели после стандартизации, если вы видите, что у вас будет значение nan:
print(np.any(np.isnan(X_test)))
print(np.any(np.isnan(y_test)))
Вы можете решить эту проблему, добавив небольшое значение (0,000001) к Std следующим образом:
def standardize(train, test):
mean = np.mean(train, axis=0)
std = np.std(train, axis=0)+0.000001
X_train = (train - mean) / std
X_test = (test - mean) /std
return X_train, X_test
Ответ 6
Я получил убыток как нан в первой же эпохе, как только началось обучение. Решение, столь же простое, как удаление nas из входных данных, сработало для меня (df.dropna())
Я надеюсь, что это помогает кому-то, сталкивающемуся с подобной проблемой
Ответ 7
Я попробовал каждое предложение на этой странице и многие другие безрезультатно. Мы импортировали CSV файлы с пандами, а затем использовали keras Tokenizer
с вводом текста для создания словарей и матриц векторов слов. После того, как заметил, некоторые файлы CSV привели к нан в то время как другие работали, вдруг мы смотрели на кодировании файлов и понял, что файлы в формате ASCII не работали с keras, что приводит к nan
потери и точности 0.0000e+00
; однако файлы utf-8 и utf-16 работали ! Прорвать.
Если вы выполняете текстовый анализ и получаете nan
после file -i {input}
использования этих предложений, используйте file -i {input}
(linux) или file -i {input}
(osx), чтобы определить тип вашего файла. Если у вас ISO-8859-1
или us-ascii
, попробуйте конвертировать в utf-8
или utf-16le
. Не пробовал последнее, но я думаю, что это сработает. Надеюсь, это поможет кому-то очень и очень разочарованному!
Ответ 8
У меня была похожая проблема с моим logloss, MAE и другие были все NA. Я посмотрел на данные и обнаружил, что у меня мало особенностей с NA. Я вменял NA с приблизительными значениями и смог решить проблему.
Ответ 9
У меня была та же проблема, я использовал Keras для решения проблемы многомерной регрессии. Позже я понял, что некоторые значения в моем наборе данных были наночастицами, и это привело к потерям наночастиц. Я использовал команду:
df=df.dropna()
И это решило мою проблему.