Взрывающиеся градиенты с LSTM с длинными временными рядами - PullRequest
0 голосов
/ 07 мая 2020

Я пытаюсь обучить модель прогнозирования временных рядов с ретроспективным обзором примерно на 100 шагов. Однако, когда я только начинал его тренировать, потери всегда были нано. Я хотел поближе познакомиться и увидел, что даже первое предсказание (до какого-либо обучения, вероятно, со случайно инициализированными весами), все значения равны NaN. Если я уменьшу количество ретроспективных обзоров, то получится едва ли 1e + 36, что по-прежнему супер и вызывает взрывные градиенты (я думаю, все еще не очень знаком с терминами).

Вот как моя архитектура выглядит в коде:

model = Sequential()
model.add(TimeDistributed(Conv2D(filters=3, kernel_size=5, activation='relu', input_shape=(n_features, n_steps), data_format='channels_first')))
model.add(TimeDistributed(MaxPooling2D(pool_size=5, data_format='channels_first')))
model.add(TimeDistributed(Flatten()))
model.add(LSTM(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(outputs.shape[1]))
model.compile(optimizer='rmsprop', loss='mse')

И формы, которые вы можете видеть из следующего: model

входные данные состоят из некоторых осадков (около 50-150 ), температуры (от -10 до 25) и уровня грунтовых вод (от 100 до 500), а результат состоит из прогноза данных уровня грунтовых вод.

Мне показалось очень странным иметь nans или очень высокий числа даже без какой-либо подготовки, и я не уверен, называется ли это взрывным градиентом, я хотел бы знать, что я здесь делаю неправильно.

Ответы [ 2 ]

0 голосов
/ 09 мая 2020

Я предлагаю вам сначала удалить эти три строки, чтобы увидеть, как работают ваши модели:

model.add(TimeDistributed(Conv2D(filters=3, kernel_size=5, activation='relu', input_shape=(n_features, n_steps), data_format='channels_first')))
model.add(TimeDistributed(MaxPooling2D(pool_size=5, data_format='channels_first')))
model.add(TimeDistributed(Flatten()))
0 голосов
/ 07 мая 2020

Я предлагаю вам нормализовать ваши выходные данные в диапазоне (0., 1.) и использовать сигмоид в последнем слое.

Вы всегда можете использовать обратное преобразование для восстановления исходных выходных данных.

mn = np.min(y_train)
mx = np.max(y_train)
y_train = (y_train - mn)/(mx - mn)

# ... train

# inverse transform
y_train_original = y_train*(mx-mn) + mn

Ваш последний уровень - linear, а предыдущая активация - relu. Вам нужно обрезать вывод с помощью sigmoid.

  1. Нормализовать выходные данные до диапазона 0-1.

  2. Используйте сигмоид в последнем слое. model.add(Dense(outputs.shape[1], activation = 'sigmoid'))

...