Введение
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:
Однако при скорости обучения 0,0001 результаты очень неожиданные:
Эти результаты не Не удивительно, если кто-то понимает, что второе изображение является просто продолжением первого изображения еще 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)
На этот раз мы получаем ожидаемые результаты:
Теперь мы можем успешно сравнить две скорости обучения. «Лучшим» рабочим кодом будет определение модели (с keras_model_sequential()
) в функции, которая также дает ожидаемые результаты. Это оставлено как упражнение для читателя.