Как эффективно использовать нормализацию партии в 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, называемые нормализацией периодической пакетной обработки. Авторы применяют следующие уравнения

Пакетно-нормированный LSTM

К сожалению, в 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)
      ))
Другие вопросы по тегам