[机器学习笔记(三)]保存加载模型的几种方式

模型的保存和加载

训练一个相对复杂的模型很有可能需要一段时间,如果是在专门的服务器或计算资源上进行训练那放那里跑就行了。但是如果是在自己的小电脑上跑,就干等着,就可能这段时间电脑都用不了。万一期间要做个其他实验,或者单纯打个游戏放松下就难受了。

好在TensorFlow提供了训练期间和训练后对模型保存的方法。也就是说,你可以随时暂停一下,然后随时恢复继续训练,甚至别人训练了一半,你可以拿它们的权重继续训练,避免耗费长时间在训练上。

保存TensorFlow模型有许多不同的方法,取决于你使用的API。因为tf2.0内置了keras这里基本使用keras的方式来完成模型的保存和加载。


  • windows10
  • python==3.6
  • tensorflow==2.0

准备模型

创建一个简单的MNIST手写数字识别模型

获取数据集

为了训练速度,可以只使用前1000个样本来进行训练和测试

(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data()

train_labels = train_labels[:1000]
test_labels = test_labels[:1000]

train_images = train_images[:1000].reshape(-1, 28 * 28) / 255.0
test_images = test_images[:1000].reshape(-1, 28 * 28) / 255.0

定义模型

这里就直接FC结构不用卷积了

# Define a simple sequential model
def create_model():
  model = tf.keras.models.Sequential([
    keras.layers.Dense(512, activation='relu', input_shape=(784,)),
    keras.layers.Dropout(0.2),
    keras.layers.Dense(10, activation='softmax')
  ])

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

  return model

# Create a basic model instance
model = create_model()

# Display the model's architecture
model.summary()

可以看到如下输出

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 512)               401920    
_________________________________________________________________
dropout (Dropout)            (None, 512)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 10)                5130      
=================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
_________________________________________________________________

使用回调保存模型

tf.keras.callbacks.ModelCheckpoint回调可以让我们在训练期间和训练结束时保存模型

创建回调实例

checkpoint_path = "training_1/cp.ckpt" # your path to save model
# checkpoint_dir = os.path.dirname(checkpoint_path) # training_1

# Create a callback that saves the model's weights
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path,
                                                 save_weights_only=True,
                                                 verbose=1)

# Train the model with the new callback
model.fit(train_images, 
          train_labels,  
          epochs=10,
          validation_data=(test_images,test_labels),
          callbacks=[cp_callback])  # Pass callback to training

这个回调会在每个epoch后保存(会覆盖旧的)checkpoint。

使用保存的模型

因为我们只保存了模型的权值,所以在恢复的时候需要先创建一个同样结构的模型,然后载入我们保存的权值。

# Create a basic model instance
model = create_model()

# Evaluate the model
loss, acc = model.evaluate(test_images,  test_labels, verbose=2)
print("Untrained model, accuracy: {:5.2f}%".format(100*acc))

我们还没有对模型进行训练,所以现在权值是全随机的,Accuracy也不会很好。

1000/1 - 0s - loss: 2.3598 - accuracy: 0.1360
Untrained model, accuracy: 13.60%

接下来从保存的checkpoint中加载权值再测试

# Loads the weights
model.load_weights(checkpoint_path)

# Re-evaluate the model
loss,acc = model.evaluate(test_images,  test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))

之前保存的权值被加载到新创建的模型中,Accuracy变成了之前训练保存的。

1000/1 - 0s - loss: 0.3937 - accuracy: 0.8650
Restored model, accuracy: 86.50%

当然tf.keras.callbacks.ModelCheckpoint有很多参数可以设置,比如保存的间隔,或者你可以让他不覆盖,依次保存为不同名字的模型,这样可以在多个checkpoint中选择没有过拟合的

手动保存模型

手动保存模型的方式很简单,使用tf.keras.Model.save_weights方法即可。当然前提是你的模型是一个tf.keras.Model类型。

# Save the weights
model.save_weights('./checkpoints/my_checkpoint')

# Create a new model instance
model = create_model()

# Restore the weights
model.load_weights('./checkpoints/my_checkpoint')

保存整个模型

之前我们保存的一直都是模型的权值,而没有保存模型的结构,所以我们恢复的时候需要创建一个相同结构的模型,然后使用tf.keras.Model.load_weights来加载权重。

保存整个模型可以让我们使用时不需要手动写模型结构,直接从保存的模型里提取出模型。

安装依赖

如果要使用HDF5格式来保存整个模型需要安装如下依赖

pip install -q pyyaml h5py

HDF5格式

保存为HDF5格式只需要使用tf.keras.Model.save(),且文件名后缀为.h5即可

# Create and train a new model instance.
model = create_model()
model.fit(train_images, train_labels, epochs=5)

# Save the entire model to a HDF5 file.
# The '.h5' extension indicates that the model shuold be saved to HDF5.
model.save('my_model.h5') 
# Or give a save_format arg
# model.save(filepath="", save_format="h5")

SavedModel格式

tf.keras.Model.save()方法也可以用于保存SavedModel格式(这个格式是tf的格式,h5则是一个通用的格式)

# Create and train a new model instance.
model = create_model()
model.fit(train_images, train_labels, epochs=5)

# Save the entire model as a SavedModel.
!mkdir -p saved_model
model.save('saved_model/my_model') 
# Or give a save_format arg
#model.save('saved_model/my_model', save_format='tf')

通过tf.keras.Model.save()的参数save_format可以调整保存的格式,tf2.0以下可能默认保存的是h5格式,tf2.0改为了tf格式。

加载模型

加载的时候就不需要先定义一个相同结构的模型,直接从保存的模型中提取出模型结构和权值

# Recreate the exact same model, including its weights and the optimizer
new_modelh5 = tf.keras.models.load_model('my_model.h5')
new_modeltf = tf.keras.models.load_model('saved_model/my_model')

# Show the model architecture
new_modelh5.summary()
new_modeltf.summary()

tf中tf.keras.models.load_model可以恢复两种格式保存的模型。

保存自定义的模型对象

tf中SavedModelHDF5一大区别是,SavedModel可以自动保存自定义的模型对象(有自定义层的模型),而HDF5需要模型配置来保存自定义模型。

参考

[1] https://tensorflow.google.cn/tutorials/keras/save_and_load

posted @ 2019-11-07 10:29  万有引力丶  阅读(2109)  评论(0编辑  收藏  举报