Sequential 模型和 Functional 模型保存方法相同,用Functional 模型演示:
from tensorflow import keras
from tensorflow.keras import layers
#定义模型
inputs = keras.Input(shape=(784,), name='digits')
x = layers.Dense(64, activation='relu', name='dense_1')(inputs)
x = layers.Dense(64, activation='relu', name='dense_2')(x)
outputs = layers.Dense(10, name='predictions')(x)
model = keras.Model(inputs=inputs, outputs=outputs, name='3_layer_mlp')
model.summary()
#训练模型
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784).astype('float32') / 255
x_test = x_test.reshape(10000, 784).astype('float32') / 255
model.compile(loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
optimizer=keras.optimizers.RMSprop())
history = model.fit(x_train, y_train,
batch_size=64,
epochs=1)
Model: "3_layer_mlp"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
digits (InputLayer) [(None, 784)] 0
_________________________________________________________________
dense_1 (Dense) (None, 64) 50240
_________________________________________________________________
dense_2 (Dense) (None, 64) 4160
_________________________________________________________________
predictions (Dense) (None, 10) 650
=================================================================
Total params: 55,050
Trainable params: 55,050
Non-trainable params: 0
_________________________________________________________________
Train on 60000 samples
60000/60000 [==============================] - 3s 42us/sample - loss: 0.3146
#保存模型
model.save('path_to_my_model.h5')
#恢复模型
new_model = keras.models.load_model('path_to_my_model.h5')
new_model.summary()
Model: "3_layer_mlp"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
digits (InputLayer) [(None, 784)] 0
_________________________________________________________________
dense_1 (Dense) (None, 64) 50240
_________________________________________________________________
dense_2 (Dense) (None, 64) 4160
_________________________________________________________________
predictions (Dense) (None, 10) 650
=================================================================
Total params: 55,050
Trainable params: 55,050
Non-trainable params: 0
_________________________________________________________________
当调用model.save
方法时:
默认情况下都会被保存,save
方法定义如下
save(
filepath, overwrite=True, include_optimizer=True, save_format=None,
signatures=None, options=None
)
filepath
:字符串类型,保存路径overwrite
: 是静默覆盖目标位置的任何现有文件,还是向用户提供手动提示。include_optimizer
: 是否把优化器内参数也一并保存save_format
: 选填’tf’ 和’h5’其中一个, Tensorflow SavedModel 和 HDF5两种类型. 默认是TFsignatures
: 使用SavedModel保存的签名。只适用于“tf”格式,详情查看 tf.saved_model.save
options
:可选参数, tf.saved_model.SaveOptions
对象,该对象指定保存到SavedModel的选项。tf.keras.models.load_model()
方法:
tf.keras.models.load_model(
filepath, custom_objects=None, compile=True
)
filepath
:加载路径custom_objects
: 可选的字典将名称(字符串)映射到在反序列化期间要考虑的自定义类或函数。compile
: 是否在加载模型后编译模型model.save()
与new_model = keras.models.load_model()
同样可将模型导出为SavedModel格式
# Export the model to a SavedModel
model.save('path_to_saved_model', save_format='tf')
# Recreate the exact same model
new_model = keras.models.load_model('path_to_saved_model')
SavedModel是TensorFlow对象的独立序列化格式,由TensorFlow支持和实现。
如果只想保存模型结构,而不想保存模型参数,可以通过model.get_config()
方法获取模型的配置信息 , 模型的配置信息是Python dict
类型 , 对于模型的恢复可以使用keras.Model.from_config(config)
config = model.get_config()
reinitialized_model = keras.Model.from_config(config)
模型的config
信息也可以被保存为json字符串 , 此时应该使用model.to_json()
与keras.models.model_from_json()
, 对模型进行提取和恢复
json_config = model.to_json()
reinitialized_model = keras.models.model_from_json(json_config)
将模型的结构(配置信息)取到内存以后 , 可以通过python方法将模型保存到硬盘:
json_config = model.to_json()
with open('model_config.json', 'w') as json_file:
json_file.write(json_config)
如果只想保存权重信息可以使用get_weights()
/set_weights()
方法 , 对模型的权重进行提取和恢复
weights = model.get_weights()
model.set_weights(weights)
如果想将其保存在硬盘上,应该用save_weights(fpath)
和 load_weights(fpath)
,代替 get_weights()
和 set_weights(weights)
model.save_weights
方法 :
save_weights(
filepath, overwrite=True, save_format=None
)
filepath
: 字符串,文件路径, .h5
后缀将会使文件保存为HDF5格式overwrite
: 是静默覆盖目标位置的任何现有文件,还是向用户提供手动提示。save_format
: 可选 tf 或者 h5 默认不填的话 , 根据文件路径后缀判断 , 否则默认 tf无论是单独保存参数还是单独保存模型,无论哪种方式,都不会保存训练数据和优化器参数,所以新模型需要重新编译。
子类模型的保存和上述类似但是要注意
model.save_weights
保存参数,恢复时,需要保证用子类创建一个相同类型的模型,并编译(compile
)相同的配置,且在 load_weights
之前一定要先训练一些数据(为了自动创建层的大小与类型等操作)可以使用训练好的模型而无需从头开始重新训练,或在您打断的地方开始训练,以防止训练过程没有保存。 tf.keras.callbacks.ModelCheckpoint
允许在训练的过程中和结束时回调保存的模型。
tf.keras.callbacks.ModelCheckpoint
对象是回调对象,该回调对象可以在每一个周期保存模型
实例化方法:
tf.keras.callbacks.ModelCheckpoint(
filepath, monitor='val_loss', verbose=0, save_best_only=False,
save_weights_only=False, mode='auto', save_freq='epoch', **kwargs
)
Arguments:
filepath
:字符串类型,储存模型的路径monitor
: 监视指标val_acc
或者val_loss
verbose
: 日志模型, 0 或者 1.save_best_only
: 布尔型,如果为true,根据监视指标,最后一个最好的模型将不会被覆盖,如果filepath
没有包含格式化选项{epoch}
,保存的模型文件将会被新周期里更好的模型覆盖。mode
: 可选填{'auto', 'min', 'max'}
中的一个,如果save_best_only
被设置为true,那么覆盖操作的执行,将根据监视指标和这个参数来决定,比如max
val_acc
和min
val_loss
,如果被天填auto
则会跟俊监视指标指定选择max
还是min
save_weights_only
: 如果参数为真,则只保存模型的权值,而非整个模型,这个参数只要影响该回调对象是调用(model.save_weights(filepath)
方法还是调用model.save(filepath)
.save_freq
: 填写epoch
或者一个数字,如果是epoch
时,回调会在每个epoch之后保存模型。当使用integer时,回调将在处理n个样本后保存模型,默认是'epoch'
例如:
checkpoint_path = "training_1/cp.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path,
save_weights_only=True,
verbose=1)
history = model.fit(x_train, y_train,
batch_size=64,
epochs=10, callbacks=[cp_callback])
Train on 60000 samples
Epoch 1/10
58304/60000 [============================>.] - ETA: 0s - loss: 0.3180
Epoch 00001: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 9s 150us/sample - loss: 0.3145
Epoch 2/10
58432/60000 [============================>.] - ETA: 0s - loss: 0.1484
Epoch 00002: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 32us/sample - loss: 0.1476
Epoch 3/10
58624/60000 [============================>.] - ETA: 0s - loss: 0.1077
Epoch 00003: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 31us/sample - loss: 0.1077
Epoch 4/10
58688/60000 [============================>.] - ETA: 0s - loss: 0.0861
Epoch 00004: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 32us/sample - loss: 0.0860
Epoch 5/10
58624/60000 [============================>.] - ETA: 0s - loss: 0.0745
Epoch 00005: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 31us/sample - loss: 0.0742
Epoch 6/10
58624/60000 [============================>.] - ETA: 0s - loss: 0.0630
Epoch 00006: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 31us/sample - loss: 0.0627
Epoch 7/10
58944/60000 [============================>.] - ETA: 0s - loss: 0.0559
Epoch 00007: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 33us/sample - loss: 0.0563
Epoch 8/10
59648/60000 [============================>.] - ETA: 0s - loss: 0.0493
Epoch 00008: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 34us/sample - loss: 0.0493
Epoch 9/10
58816/60000 [============================>.] - ETA: 0s - loss: 0.0431
Epoch 00009: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 34us/sample - loss: 0.0429
Epoch 10/10
58688/60000 [============================>.] - ETA: 0s - loss: 0.0398
Epoch 00010: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 34us/sample - loss: 0.0397
使用tf.train.Checkpoint
, 需要首先声明一个 Checkpoint对象:
checkpoint = tf.train.Checkpoint(model=model)
这里 tf.train.Checkpoint()
接受的初始化参数比较特殊,是一个 **kwargs
。具体而言,是一系列的键值对,键名可以随意取,值为需要保存的对象。例如,如果我们希望保存一个继承 tf.keras.Model
的模型实例 model
和一个继承 tf.train.Optimizer
的优化器 optimizer
,我们可以这样写:
checkpoint = tf.train.Checkpoint(myAwesomeModel=model, myAwesomeOptimizer=optimizer)
接下来,当模型训练完成需要保存的时候,使用:
checkpoint.save(save_path_with_prefix)
就可以。 save_path_with_prefix
是保存文件的目录 + 前缀。
当在其他地方需要为模型重新载入之前保存的参数时,需要再次实例化一个 checkpoint,同时保持键名的一致。再调用 checkpoint 的 restore 方法。就像下面这样:
model = MyModel() # 待恢复参数的同一模型
checkpoint = tf.train.Checkpoint(myAwesomeModel=model) # 键名保持为“myAwesomeModel”
checkpoint.restore(save_path_with_prefix_and_index)
即可恢复模型变量。 save_path_with_prefix_and_index
是之前保存的文件的目录 + 前缀 + 编号。例如,调用 checkpoint.restore('./save/model.ckpt-1')
就可以载入前缀为 model.ckpt
,序号为 1 的文件来恢复模型。
当保存了多个文件时,我们往往想载入最近的一个。可以使用 tf.train.latest_checkpoint(save_path)
这个辅助函数返回目录下最近一次 checkpoint 的文件名。例如如果 save 目录下有 model.ckpt-1.index
到 model.ckpt-10.index
的 10 个保存文件, tf.train.latest_checkpoint('./save')
即返回 ./save/model.ckpt-10
。
在定义 Checkpoint 后接着定义一个 CheckpointManager:
checkpoint = tf.train.Checkpoint(model=model)
manager = tf.train.CheckpointManager(checkpoint, directory='./save', checkpoint_name='model.ckpt', max_to_keep=k)
此处, directory
参数为文件保存的路径, checkpoint_name
为文件名前缀(不提供则默认为 ckpt
), max_to_keep
为保留的 Checkpoint 数目。
在需要保存模型的时候,我们直接使用 manager.save()
即可。如果我们希望自行指定保存的 Checkpoint 的编号,则可以在保存时加入 checkpoint_number
参数。例如 manager.save(checkpoint_number=100)
。
Keras中文文档
https://keras.io/zh/
TensorFlow官方
https://tensorflow.google.cn/
最全Tensorflow2.0 入门教程持续更新
https://zhuanlan.zhihu.com/p/59507137
简单粗暴TensorFlow2
https://tf.wiki/zh/preface.html