Модификация Keras - как правильно тренировать несколько моделей в Keras - PullRequest
0 голосов
/ 17 апреля 2020

Это касается Keras в R, но, насколько я понимаю, это относится и к python.

Модели Keras модифицированы на месте . Изначально непонимание того, что это значит, застало меня врасплох, поэтому я подумал, что напишу, что это значит для обучения нескольких моделей за один сеанс, чтобы другие могли избежать ошибок, которые я сделал.

Что это означает, что вы не можете скопировать объект модели, например:

model = keras_model_sequential()
model %>%
   layer_dense(
      units = 50,
      input_shape = 100
   )
model_copy = model

Теперь, если вы попытаетесь изменить либо model, либо model_copy, будет изменен и другой объект. Ответ ниже объясняет почему.

1 Ответ

0 голосов
/ 17 апреля 2020

Введение

R может либо изменять на месте, что означает, что объект изменяется в памяти, либо создавать новую копию объекта при его изменении. Это объясняется здесь . Если вы создаете объект и другой объект, который указывает на этот первый объект, они будут указывать на то же место в памяти. Однако это означает, что изменение одного из них приведет к изменению другого.

Чтобы избежать этого, R отслеживает, если имена 1 или> 1 указывают на одно и то же место в памяти. Если это 1, тогда безопасно изменить значения памяти. Это модификация на месте . Однако, если это> 1, то изменение одного объекта изменит другой. Следовательно, изменяемый объект фактически копируется в новую часть памяти, так что два объекта больше не указывают на одну и ту же часть памяти. Это означает, что изменение одного объекта не влияет на другой.

Это не выполняется в Keras в R, и, насколько я понимаю (хотя я еще не использовал Keras в python), это также не ' т в python. Keras всегда использует модификацию на месте, независимо от того, сколько имен указывают на место в памяти. Таким образом, все, что делается с одной моделью, также делается с другой, потому что в действительности это всего лишь два имени для одной и той же модели - оба «объекта» на самом деле являются только одним объектом.

Пример неработающего кода

Чтобы показать, где это может сбить вас с толку, приведу пример обучения сети классификации mnist со сравнением двух показателей обучения RMSProp. Если кто-то не знал о модификации на месте в Керасе, можно написать код:

library(keras)

# data
mnist = dataset_mnist()
x_train = mnist$train$x
y_train = mnist$train$y
x_train = array_reshape(x_train, c(nrow(x_train), 784))
x_train = x_train / 255
y_train = to_categorical(y_train, 10)

# model
model = keras_model_sequential() 
model %>% 
  layer_dense(units = 256, activation = 'relu', input_shape = c(784)) %>% 
  layer_dropout(rate = 0.4) %>% 
  layer_dense(units = 128, activation = 'relu') %>%
  layer_dropout(rate = 0.3) %>%
  layer_dense(units = 10, activation = 'softmax')

# compile and train a model, given a learning rate
comp_train = function(learning_rate) {
  model_copy = model
  model_copy %>% compile(
    loss = 'categorical_crossentropy',
    optimizer = optimizer_rmsprop(
      lr = learning_rate
    ),
    metrics = c('accuracy')
  )
  training_history = model_copy %>% fit(
    x_train, y_train, 
    epochs = 30, batch_size = 128, 
    validation_split = 0.2
  )
  return(
    as.data.frame(training_history)
  )
}

# test two learning rates
lr_0.001 = comp_train(0.001)
lr_0.0001 = comp_train(0.0001)

Результаты имеют смысл для скорости обучения 0,001:

A standard exponential decay one would expect from training a neural net

Однако при скорости обучения 0,0001 результаты очень неожиданные:

A training history that isn't what one would expect of training a neural net

Эти результаты не Не удивительно, если кто-то понимает, что второе изображение является просто продолжением первого изображения еще 30 эпох. Итак, вместе взятые, два изображения просто показывают обучение одного и того же нейрона net в течение 60 эпох. Это происходит из-за модификации на месте - когда вы тренируете «вторую» сеть, вы фактически просто тренируете первую, даже если она уже обучена.

Пример рабочего кода

* 1037 Так что же делать по-другому? С Keras каждая модель должна быть инициализирована с keras_model_sequential() или keras_model() (какой бы тип вы ни использовали). Поэтому мы отдельно определяем каждую модель:
library(keras)

# data
mnist = dataset_mnist()
x_train = mnist$train$x
y_train = mnist$train$y
x_train = array_reshape(x_train, c(nrow(x_train), 784))
x_train = x_train / 255
y_train = to_categorical(y_train, 10)

# models
model_lr0.001 = keras_model_sequential() 
model_lr0.0001 = keras_model_sequential() 

model_lr0.001 %>% 
  layer_dense(units = 256, activation = 'relu', input_shape = c(784)) %>% 
  layer_dropout(rate = 0.4) %>% 
  layer_dense(units = 128, activation = 'relu') %>%
  layer_dropout(rate = 0.3) %>%
  layer_dense(units = 10, activation = 'softmax')
model_lr0.0001 %>% 
  layer_dense(units = 256, activation = 'relu', input_shape = c(784)) %>% 
  layer_dropout(rate = 0.4) %>% 
  layer_dense(units = 128, activation = 'relu') %>%
  layer_dropout(rate = 0.3) %>%
  layer_dense(units = 10, activation = 'softmax')

# compile and train a given model, also given a learning rate
comp_train = function(model, learning_rate) {
  model %>% compile(
    loss = 'categorical_crossentropy',
    optimizer = optimizer_rmsprop(
      lr = learning_rate
    ),
    metrics = c('accuracy')
  )
  training_history = model %>% fit(
    x_train, y_train, 
    epochs = 30, batch_size = 128, 
    validation_split = 0.2
  )
  return(
    as.data.frame(training_history)
  )
}

# test two learning rates
lr_0.001 = comp_train(model_lr0.001, 0.001)
lr_0.0001 = comp_train(model_lr0.0001, 0.0001)

На этот раз мы получаем ожидаемые результаты:

A standard exponential decay one would expect from training a neural net

A standard exponential decay one would expect from training a neural net

Теперь мы можем успешно сравнить две скорости обучения. «Лучшим» рабочим кодом будет определение модели (с keras_model_sequential()) в функции, которая также дает ожидаемые результаты. Это оставлено как упражнение для читателя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...