装载一个训练有素的克拉斯模型并继续训练

我想知道是否有可能保存一个部分训练的克拉斯模型,并继续训练后再次装载模型。

原因是,我将有更多的训练数据在未来,我不想再次训练整个模型。

我使用的功能是:

#Partly train model
model.fit(first_training, first_classes, batch_size=32, nb_epoch=20)


#Save partly trained model
model.save('partly_trained.h5')


#Load partly trained model
from keras.models import load_model
model = load_model('partly_trained.h5')


#Continue training
model.fit(second_training, second_classes, batch_size=32, nb_epoch=20)

编辑1: 添加完整的工作示例

对于10个纪元后的第一个数据集,最后一个纪元的损失为0.0748,准确度为0.9863。

保存、删除和重新加载模型后,在第二个数据集上训练的模型的丢失率和准确率分别为0.1711和0.9504。

这是由新的训练数据引起的,还是由一个完全重新训练的模型引起的?

"""
Model by: http://machinelearningmastery.com/
"""
# load (downloaded if needed) the MNIST dataset
import numpy
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense
from keras.utils import np_utils
from keras.models import load_model
numpy.random.seed(7)


def baseline_model():
model = Sequential()
model.add(Dense(num_pixels, input_dim=num_pixels, init='normal', activation='relu'))
model.add(Dense(num_classes, init='normal', activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
return model


if __name__ == '__main__':
# load data
(X_train, y_train), (X_test, y_test) = mnist.load_data()


# flatten 28*28 images to a 784 vector for each image
num_pixels = X_train.shape[1] * X_train.shape[2]
X_train = X_train.reshape(X_train.shape[0], num_pixels).astype('float32')
X_test = X_test.reshape(X_test.shape[0], num_pixels).astype('float32')
# normalize inputs from 0-255 to 0-1
X_train = X_train / 255
X_test = X_test / 255
# one hot encode outputs
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
num_classes = y_test.shape[1]


# build the model
model = baseline_model()


#Partly train model
dataset1_x = X_train[:3000]
dataset1_y = y_train[:3000]
model.fit(dataset1_x, dataset1_y, nb_epoch=10, batch_size=200, verbose=2)


# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Baseline Error: %.2f%%" % (100-scores[1]*100))


#Save partly trained model
model.save('partly_trained.h5')
del model


#Reload model
model = load_model('partly_trained.h5')


#Continue training
dataset2_x = X_train[3000:]
dataset2_y = y_train[3000:]
model.fit(dataset2_x, dataset2_y, nb_epoch=10, batch_size=200, verbose=2)
scores = model.evaluate(X_test, y_test, verbose=0)
print("Baseline Error: %.2f%%" % (100-scores[1]*100))

编辑2: tensorflow. keras 备注

对于 tensorflow. keras,在模型拟合中将参数 nb _ epochs 更改为 epochs:

import numpy
from tensorflow.keras.datasets import mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.models import load_model




numpy.random.seed(7)


def baseline_model():
model = Sequential()
model.add(Dense(num_pixels, input_dim=num_pixels, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
118261 次浏览

实际上-model.save保存所有信息需要在您的情况下重新开始培训。唯一可能被重新加载模型破坏的是你的优化器状态。要检查这一点-尝试 save和重新加载模型,并训练它的训练数据。

请注意,Kera 有时在加载模型时会出现问题,如 给你中所示。 这也许可以解释为什么你不从同样训练有素的准确性开始。

问题可能在于您使用了不同的优化器——或优化器的不同参数。我只是有一个同样的问题,一个自定义预训练模型,使用

reduce_lr = ReduceLROnPlateau(monitor='loss', factor=lr_reduction_factor,
patience=patience, min_lr=min_lr, verbose=1)

对于预训练模型,原始学习率从0.0003开始,在预训练过程中降低到最小学习率,即0.000003

我只是把这一行复制到脚本中,脚本使用了预先训练好的模型,结果得到了非常糟糕的准确性。直到我注意到预先训练模型的最后学习率是最小学习率,即0.000003。如果我从这个学习率开始,我会得到与预先训练模型输出完全相同的精度——这是有意义的,因为从一个比预先训练模型中使用的最后学习率大100倍的学习率开始,将导致 GD 的巨大超调,因此精度大大降低。

以上所有的帮助,您恢复 必须的从相同的学习率()作为 LR 时,模型和权重保存。直接在优化器上设置它。

注意,不能保证从那里改进,因为模型可能已经达到了局部最小值,这可能是全局的。为了寻找另一个局部最小值而恢复一个模型是没有意义的,除非你打算以一种可控的方式增加学习率,并且在不远的地方将模型推向一个可能更好的最小值。

您可能还会遇到概念漂移,请参阅 当有新的观察结果时,您是否应该重新训练模型。还有一些学术论文讨论的灾难性遗忘的概念。这是一张 MNIST 灾难性遗忘的实证研究的照片

以上大部分答案都涵盖了重点。如果您正在使用最近的 Tensorflow (TF2.1或以上) ,那么下面的例子将帮助您。代码的模型部分来自 Tensorflow 网站。

import tensorflow as tf
from tensorflow import keras
mnist = tf.keras.datasets.mnist


(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0


def create_model():
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(512, activation=tf.nn.relu),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])


model.compile(optimizer='adam', loss='sparse_categorical_crossentropy',metrics=['accuracy'])
return model


# Create a basic model instance
model=create_model()
model.fit(x_train, y_train, epochs = 10, validation_data = (x_test,y_test),verbose=1)

请将模型保存在 * 中。Tf 格式。根据我的经验,如果定义了任何 custom_ loss,* 。H5格式将不会保存优化器状态,因此如果您想从我们离开的地方重新训练模型,那么它将不能满足您的需要。

# saving the model in tensorflow format
model.save('./MyModel_tf',save_format='tf')




# loading the saved model
loaded_model = tf.keras.models.load_model('./MyModel_tf')


# retraining the model
loaded_model.fit(x_train, y_train, epochs = 10, validation_data = (x_test,y_test),verbose=1)

这种方法将在保存模型之前重新启动我们离开的训练。正如其他人提到的,如果你想保存最佳模型的权重或者你想保存每个时代的模型权重,你需要使用带有选项的 keras 回调函数(ModelCheckpoint) ,如 save_weights_only=Truesave_freq='epoch'save_best_only

有关详细信息,请检查 给你和另一个例子 给你

如果您使用的是 TF2,请使用新的 save _ model 方法(格式为 pb)。

model.fit(x=X_train, y=y_train, epochs=10,callbacks=[model_callback])#your first training
tf.saved_model.save(model, save_to_dir_path) #save the model
del model #to delete the model
model =  tf.keras.models.load_model(save_to_dir_path)
model.fit(x=X_train, y=y_train, epochs=10,callbacks=[model_callback])#your second training

用保存的模型训练模型是完全可以的。我用相同的数据训练了保存的模型,发现它提供了很好的准确性。而且,每个时代所花费的时间都要少得多。

下面是代码看一看:

from keras.models import load_model
model = load_model('/content/drive/MyDrive/CustomResNet/saved_models/model_1.h5')
history=model.fit(train_gen,validation_data=valid_gen,epochs=5)