Keras修改到位-如何在Keras中正确培训多个模型

Keras修改到位-如何在Keras中正确培训多个模型,r,tensorflow,keras,R,Tensorflow,Keras,这是关于R中的Keras,但据我所知,它也适用于python Keras模型是。在过去,我一开始不理解这意味着什么,所以我想我会写下这对在同一课程中训练多个模型意味着什么,这样其他人就可以避免犯我犯的错误 这意味着不能复制模型对象,例如: model = keras_model_sequential() model %>% layer_dense( units = 50, input_shape = 100 ) model_copy = model 现

这是关于R中的Keras,但据我所知,它也适用于python

Keras模型是。在过去,我一开始不理解这意味着什么,所以我想我会写下这对在同一课程中训练多个模型意味着什么,这样其他人就可以避免犯我犯的错误

这意味着不能复制模型对象,例如:

model = keras_model_sequential()
model %>%
   layer_dense(
      units = 50,
      input_shape = 100
   )
model_copy = model
现在,如果您尝试修改
模型
模型_copy
,则另一个模型也将被修改。下面的答案解释了原因。

引言 R可以就地修改,这意味着在内存中修改对象,也可以在修改对象时创建对象的新副本。这是可以解释的。如果创建一个对象,以及指向第一个对象的另一个对象,它们将指向内存中的同一位置。但是,这意味着修改一个将修改另一个

为了避免这种情况,如果1个或>1个名称指向内存中的同一位置,则R跟踪。如果为1,则修改内存值是安全的。这是适当的修改。但是,如果大于1,则修改一个对象将修改另一个对象。因此,被修改的对象实际上被复制到内存的一个新部分,这样两个对象就不再指向内存的同一部分。这意味着修改一个对象不会影响另一个对象

这不是在R中的Keras中实现的,据我所知(尽管我还没有在python中使用Keras),它也不是在python中实现的。Keras总是就地使用修改,不管有多少名称指向内存中的点。因此,对一个模型所做的任何事情也会对另一个模型所做,因为实际上,它们只是同一个模型的两个名称——两个“对象”实际上只是一个对象

示例断开的代码 为了说明这会使您陷入困境,下面是一个示例,通过比较两个RMSProp学习率来训练mnist分类网络。如果不知道Keras中的修改,可以编写代码:

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的学习率,结果是有意义的:

但是,对于0.0001的学习率,结果非常出乎意料:

如果人们意识到第二幅图像只是第一幅图像的延续,并且延续了30个时代,那么这些结果也就不足为奇了。所以,把这两幅图像放在一起,只显示了同一个神经网络在60个时期内的训练。这是因为修改到位——当你训练“第二个”网络时,你实际上只是训练第一个,即使它已经训练过了

示例工作代码 那么,应该采取哪些不同的做法呢?对于Keras,不同的模型必须分别使用
Keras\u model\u sequential()
Keras\u 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)
这一次,我们得到了预期的结果:

我们现在可以成功地比较这两种学习率。“更好”的工作代码是在函数中定义模型(使用
keras\u model\u sequential()
),这也会给出预期的结果。这是留给读者的练习