加载训练有素的Keras模型并继续训练

时间:2017-03-08 08:07:58

标签: python tensorflow neural-network keras resuming-training

我想知道是否可以保存部分训练的Keras模型,并在重新加载模型后继续训练。

原因是我将来会有更多的训练数据,我不想重新训练整个模型。

我正在使用的功能是:

#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))

7 个答案:

答案 0 :(得分:19)

实际上 - rs = stmt.executeQuery("SELECT node_name FROM v_catalog.nodes") ; 会保存您重启培训所需的所有信息。唯一可以通过重新加载模型来破坏的是你的优化器状态。要检查 - 尝试model.save并重新加载模型并在训练数据上进行训练。

答案 1 :(得分:9)

以上大多数答案都涵盖了重点。如果您正在使用最新的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

有关更多详细信息,请检查here和另一个示例here

答案 2 :(得分:4)

问题可能是您使用了不同的优化器 - 或优化器的不同参数。我使用

在自定义预训练模型中遇到了同样的问题
reduce_lr = ReduceLROnPlateau(monitor='loss', factor=lr_reduction_factor,
                              patience=patience, min_lr=min_lr, verbose=1)

对于预训练模型,原始学习率从0.0003开始,在预训练期间,它降低到min_learning率,即0.000003

我只是将那条线复制到使用预先训练过的模型的脚本上,并且确实有很差的准确性。直到我注意到预训练模型的最后学习率是最小学习率,即0.000003。如果我从学习速度开始,我会得到与预训练模型的输出完全相同的精度 - 这是有道理的,因为学习速度比预训练中使用的最后学习速率大100倍模型将导致GD的巨大超调,从而严重降低精度。

答案 3 :(得分:2)

请注意,Keras有时会遇到加载模型的问题,例如here。 这可能会解释您没有从相同的训练准确度开始的情况。

答案 4 :(得分:1)

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

请注意,从那里开始的改进无法保证,因为模型可能已达到局部最小值,这可能是全局的。没有必要恢复模型以搜索另一个局部最小值,除非您打算以受控方式提高学习率并将模型推到可能更好的最小值不远处。

答案 5 :(得分:0)

您可能还会遇到“概念漂移”,请参见Should you retrain a model when new observations are available。还有一些学术论文讨论的灾难性遗忘的概念。这是MNIST Empirical investigation of catastrophic forgetting

答案 6 :(得分:0)

如果您使用的是 TF2,请使用新的 saved_model 方法(格式 pb)。更多信息可用 herehere

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