Как эффективно использовать нормализацию партии в LSTM?
Я пытаюсь использовать пакетную нормализацию в LSTM с использованием keras в R. В моем наборе данных переменная target/output является Sales
столбец, и каждая строка в наборе данных записывает Sales
за каждый день в году (2008-2017). Набор данных выглядит следующим образом:
Моя цель - построить модель LSTM на основе такого набора данных, который должен быть в состоянии обеспечить прогноз в конце обучения. Я тренирую эту модель на данных за 2008-2016 гг. И использую половину данных за 2017 г. в качестве проверки, а остальные - в качестве тестового набора.
Ранее я пытался создать модель, используя отсев и раннюю остановку. Это выглядит ниже:
mdl1 <- keras_model_sequential()
mdl1 %>%
layer_lstm(units = 512, input_shape = c(1, 3), return_sequences = T ) %>%
layer_dropout(rate = 0.3) %>%
layer_lstm(units = 512, return_sequences = FALSE) %>%
layer_dropout(rate = 0.2) %>%
layer_dense(units = 1, activation = "linear")
mdl1 %>% compile(loss = 'mse', optimizer = 'rmsprop')
Модель выглядит следующим образом
___________________________________________________________
Layer (type) Output Shape Param #
===========================================================
lstm_25 (LSTM) (None, 1, 512) 1056768
___________________________________________________________
dropout_25 (Dropout) (None, 1, 512) 0
___________________________________________________________
lstm_26 (LSTM) (None, 512) 2099200
___________________________________________________________
dropout_26 (Dropout) (None, 512) 0
___________________________________________________________
dense_13 (Dense) (None, 1) 513
===========================================================
Total params: 3,156,481
Trainable params: 3,156,481
Non-trainable params: 0
___________________________________________________________
Для обучения модели ранняя остановка используется с набором проверки.
mdl1.history <- mdl1 %>%
fit(dt.tr, dt.tr.out, epochs=500, shuffle=F,
validation_data = list(dt.val, dt.val.out),
callbacks = list(
callback_early_stopping(min_delta = 0.000001, patience = 10, verbose = 1)
))
Кроме того, я хочу использовать пакетную нормализацию для ускорения обучения. Насколько я понимаю, чтобы использовать пакетную нормализацию, мне нужно разделить данные на пакеты и применить layer_batch_normalization
для ввода каждого скрытого слоя. Слои модели выглядят следующим образом:
batch_size <- 32
mdl2 <- keras_model_sequential()
mdl2 %>%
layer_batch_normalization(input_shape = c(1, 3), batch_size = batch_size) %>%
layer_lstm(units = 512, return_sequences = T) %>%
layer_dropout(rate = 0.3) %>%
layer_batch_normalization(batch_size = batch_size) %>%
layer_lstm(units = 512, return_sequences = F) %>%
layer_dropout(rate = 0.2) %>%
layer_batch_normalization(batch_size = batch_size) %>%
layer_dense(units = 1, activation = "linear")
mdl2 %>% compile(loss = 'mse', optimizer = 'rmsprop')
Эта модель выглядит следующим образом:
______________________________________________________________________________
Layer (type) Output Shape Param #
==============================================================================
batch_normalization_34 (BatchNormalization) (32, 1, 3) 12
______________________________________________________________________________
lstm_27 (LSTM) (32, 1, 512) 1056768
______________________________________________________________________________
dropout_27 (Dropout) (32, 1, 512) 0
______________________________________________________________________________
batch_normalization_35 (BatchNormalization) (32, 1, 512) 2048
______________________________________________________________________________
lstm_28 (LSTM) (32, 1, 512) 2099200
______________________________________________________________________________
dropout_28 (Dropout) (32, 1, 512) 0
______________________________________________________________________________
batch_normalization_36 (BatchNormalization) (32, 1, 512) 2048
______________________________________________________________________________
dense_14 (Dense) (32, 1, 1) 513
==============================================================================
Total params: 3,160,589
Trainable params: 3,158,535
Non-trainable params: 2,054
______________________________________________________________________________
Тренировка модели выглядит как раньше. Единственное отличие заключается в наборе данных для обучения и проверки, который состоит из размеров, кратных batch_size
(32 здесь), путем повторной выборки данных из 2-й последней партии в последнюю партию.
Тем не менее, производительность mdl1
намного лучше, чем у mdl2
, как можно увидеть ниже.
Я не уверен точно, что я делаю неправильно, поскольку я начинаю с керас (и практической нейронной сети в целом). Кроме того, производительность первой модели также не так хороша; Любое предложение о том, как улучшить это также было бы здорово.
1 ответ
Пакетную нормализацию в LSTM не так просто реализовать. В некоторых статьях представлены удивительные результаты https://arxiv.org/pdf/1603.09025.pdf, называемые нормализацией периодической пакетной обработки. Авторы применяют следующие уравнения
К сожалению, в keras эта модель пока не реализована только в tenorflow https://github.com/OlavHN/bnlstm
Однако мне удалось получить хорошие результаты, используя (по умолчанию) пакетную нормализацию после функции активации без центрирования и смещения. Этот подход отличается от описанного выше, применяя BN после c_t и h_t, возможно, стоит попробовать.
model = Sequential()
model.add(LSTM(neurons1,
activation=tf.nn.relu,
return_sequences=True,
input_shape=(timesteps, data_dim)))
model.add(BatchNormalization(momentum=m, scale=False, center=False))
model.add(LSTM(neurons2,
activation=tf.nn.relu))
model.add(BatchNormalization(momentum=m, scale=False, center=False))
model.add(Dense(1))
Я использую Keras с Python, но я могу попробовать R. В fit
Метод документации говорит, что по умолчанию 32, если не указано. Это больше не верно в текущей версии, как это видно из исходного кода. Я думаю, вы должны попробовать это, по крайней мере, так, как это работает в Python:
mdl2 <- keras_model_sequential()
mdl2 %>%
layer_input(input_shape = c(1, 3)) %>%
layer_batch_normalization() %>%
layer_lstm(units = 512, return_sequences = T, dropout=0.3) %>%
layer_batch_normalization() %>%
layer_lstm(units = 512, return_sequences = F, dropout=0.2) %>%
layer_batch_normalization() %>%
layer_dense(units = 1, activation = "linear")
mdl2 %>% compile(loss = 'mse', optimizer = 'rmsprop')
mdl2.history <- mdl2 %>%
fit(dt.tr, dt.tr.out, epochs=500, shuffle=F,
validation_data = list(dt.val, dt.val.out),
batch_size=32,
callbacks = list(
callback_early_stopping(min_delta = 0.000001, patience = 10, verbose = 1)
))