Вопрос или проблема
Вот мой модельный код для бинарной классификации временного ряда:
def make_model(feature_columns):
feature_layer = tf.keras.layers.DenseFeatures(feature_columns)
feature_layer_outputs = feature_layer(feature_layer_inputs)
feature_layer_outputs = tf.expand_dims(feature_layer_outputs, 1)
conv = keras.layers.Conv1D(filters=64, kernel_size=3, padding="same",kernel_regularizer=keras.regularizers.l1_l2(l1=0.01, l2=0.01))(feature_layer_outputs)
conv = keras.layers.BatchNormalization()(conv)
conv = keras.layers.ReLU()(conv)
conv = keras.layers.Conv1D(filters=64, kernel_size=3, padding="same",kernel_regularizer=keras.regularizers.l1_l2(l1=0.01, l2=0.01))(conv)
conv = keras.layers.BatchNormalization()(conv)
conv = keras.layers.ReLU()(conv)
conv = keras.layers.Conv1D(filters=64, kernel_size=3, padding="same",kernel_regularizer=keras.regularizers.l1_l2(l1=0.01, l2=0.01))(conv)
conv = keras.layers.BatchNormalization()(conv)
conv = keras.layers.ReLU()(conv)
conv = keras.layers.Dropout(0.25)(conv)
gap = keras.layers.GlobalAveragePooling1D()(conv)
output_layer = keras.layers.Dense(1, activation="Softmax")(gap)
return keras.models.Model(inputs=[v for v in feature_layer_inputs.values()], outputs=output_layer)`
Я попробовал следующее. Сначала у меня с самого начала было NaN в качестве потерь. Я исправил это, используя RobustScaler для числовых значений.
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, RobustScaler,MinMaxScaler
dataframe = df
ct = ColumnTransformer([
('numeric', RobustScaler(), numerical_features[1:])
], remainder="passthrough")
dataframe = ct.fit_transform(dataframe)
numerical_features[0] — это моя метка. Я также попробовал добавить keras.regularizers.l1_l2 для решения проблемы с NaN в потерях и добавить дропаут после каждого слоя ReLU (сейчас он только на последнем). Я также пробовал использовать разные функции потерь, такие как MSE и бинарная кросс-энтропия, также я пытался использовать сигмоиду/softmax в выходном слое. В данный момент я практически в полном замешательстве и у меня такое ощущение, что я пропускаю что-то довольно основное. Есть ли у кого-нибудь идеи?
На моем опыте самой распространенной причиной NaN в потерях является ситуация, когда в контрольной выборке 0 экземпляров. Возможно, у вас есть какое-то вычисление, основанное, например, на усреднении потерь по нескольким временным меткам, но одна из временных меток имеет 0 экземпляров, что вызывает каскад значений NaN.
Тщательно проверьте ваш валидационный набор и то, как рассчитываются потери на нем.
Ответ или решение
Наиболее распространенная причина появления NaN (Not a Number) в функции потерь заключается в перерасходе памяти, неправильном нормировании данных или ошибках в самой архитектуре нейронной сети. Рассмотрим основные аспекты этой проблемы, основываясь на вашем коде для бинарной классификации временных рядов.
1. Нормализация данных
Вы упомянули использование RobustScaler
, что является хорошим шагом, поскольку он менее чувствителен к выбросам по сравнению с StandardScaler
. Однако стоит удостовериться, что нормализация применена ко всему набору данных (как к обучающему, так и к валидационному набору). Любая ошибка в нормализации может привести к NaN в расчетах потерь.
Также имейте в виду, что NaN могут произойти из-за деления на ноль или неправильно обработанных значений (например, бесконечностей) в данных. Перед обучением модели полезно выполнить проверку данных на наличие таких значений.
2. Архитектура модели
Ваш код создает модель с несколькими сверточными слоями. Давайте рассмотрим несколько моментов:
-
Активация выхода: Ваша выходная слой определен с активацией
Softmax
, но для бинарной классификации корректнее использоватьsigmoid
. ИспользованиеSoftmax
приводит к ошибочному распределению вероятностей для задач, где нужно просто выставить порог (обычно 0.5).Корректировка:
output_layer = keras.layers.Dense(1, activation="sigmoid")(gap)
-
Функция потерь: Если вы используете
sigmoid
, вам следует применятьbinary_crossentropy
. Если вы используетеsoftmax
, то целесообразно использоватьcategorical_crossentropy
, но это менее распространенный подход при бинарной классификации. -
Регуляризация и дропаут: Использование L1 и L2 регуляризации может помочь предотвратить переобучение, однако стоит убедиться, что коэффициенты регуляризации не слишком высоки, что может затруднить обучение модели и вызвать NaN. Проверьте значения вашей регуляризации и дропаут-уровня, уменьшая их, чтобы оценить влияние на обучение.
3. Проверка на пустые батчи
Как уже упоминалось, NaN в функциях потерь могут также происходить из-за пустых батчей. Убедитесь в том, что ваш валидационный набор данных не содержит нулевых экземпляров для каждого временного окна. Если у вас есть временные ряды с заранее определенными окнами для валидации, убедитесь, что они корректны.
4. Отладка
Предлагаю следующие шаги для отладки:
- Вставьте печать промежуточных значений, таких как выходные данные после каждого слоя, чтобы увидеть, где могут возникнуть NaN.
- Проверьте данные на наличие NaN и бесконечностей после обработки и перед подачей в модель.
- Попробуйте уменьшить размер модели (например, количество фильтров или слоев) и проверьте, есть ли изменения в потере.
- Экспериментируйте с гиперпараметрами, постепенно меняя их, чтобы увидеть влияние на более стабильное обучение.
Общая практика, как и структурирование подхода к задаче, являются важными для успешного решения проблемы. ينبغي عليك أن تدرس جميع الجوانب للتحقق من أن كل شيء يعمل بشكل صحيح وخالي من الأخطاء. Проведение тщательной проверки данных и настройки модели, безусловно, поможет вам справиться с проблемой NaN в функциях потерь.