一、数据集处理、载入、模型构建、模型训练
1.1 Fashion MNIST数据集介绍
Fashion-MNIST数据集包含了10个类别的图像,分别是:t-shirt(T恤),trouser(牛仔裤),pullover(套衫),dress(裙子),coat(外套),sandal(凉鞋),shirt(衬衫),sneaker(运动鞋),bag(包),ankle boot(短靴)。数据集中包含60000张训练图片和10000张测试图片,每张图片是一个28*28
的像素数组,每个像素的值为0~255之间的8位无符号整数(uint8)。每张图片均有1个标签与之对应,下面是对应关系:
1.2 导入相关包,同时查看一下版本。
import tensorflow as tf
import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
print('Tensorflow Version: {}'.format(tf.__version__))
输出结果为:Tensorflow Version: 2.3.0
1.2 载入数据集
(train_image, train_lable), (test_image, test_label) = tf.keras.datasets.fashion_mnist.load_data()
查看训练数据集
train_image.shape
输出结果为:(60000, 28, 28)
查看测试数据集
train_lable.shape
输出结果为:(60000, )
可以显示一下图片
plt.imshow(train_image[3])
显示为:
1.3 由于每张图片像素的取值范围是0-255,需要做归一化处理。
train_image = train_image/255
test_image = test_image/255
1.4 构建模型
model = tf.keras.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=(28,28))) # 28*28
model.add(tf.keras.layers.Dense(128, activation='relu'))
model.add(tf.keras.layers.Dense(10, activation='softmax'))
查看一下模型
model.summary()
输出结果为:
1.5 编译模型
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['acc']
)
1.6 训练模型
model.fit(train_image, train_lable, epochs=3)
输出结果信息为:
1.7 在测试数据集上该评估模型
model.evaluate(test_image, test_label, verbose=0)
输出结果信息为:[0.3675694167613983, 0.8694999814033508]
可见,在测试数据集上的预测准确率为0.8694999814033508,还算可以。
二、保存整个模型
在第一部分,我训练成了模型model,这里我将整个模型可以保存到一个文件中,其中包含权重值、模型配置乃至优化器配置。
2.1 保存整个模型
model.save('less_model.h5')
这样就将整个模型(包括权重值、模型配置乃至优化器配置)保存到了less_model.h5文件中,less_model.h5文件存放的位置在同级目录中。
2.2 保存模型的目的在于后期方便对模型进行载入,下面载入模型,并查看模型。
new_model = tf.keras.models.load_model('less_model.h5')
new_model.summary()
显示结果为
2.3 编译模型
new_model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['acc']
)
2.4 在测试集上评估该模型
new_model.evaluate(test_image, test_label, verbose=0)
结果为:[0.3675694167613983, 0.8694999814033508]。可见,其结果与前面一样。
三、只保存架构
有时我们只对模型的架构感兴趣,而无需保存权重值或优化器。在这种情况下,可以仅保存模型的“配置” 。
3.1 只获取模型的架构,json_config中存放的便只是架构。
json_config = model.to_json()
json_config
输出为
3.2 从json_config中恢复模型架构
reinitialized_model = tf.keras.models.model_from_json(json_config)
reinitialized_model.summary()
输出为
3.3 编译
reinitialized_model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['acc']
)
3.4 在测试集上评估该模型
reinitialized_model.evaluate(test_image, test_label, verbose=0)
结果为:[2.3960182666778564, 0.07109999656677246]。可见,准确率很低,和胡乱猜测的一样,这就是由于我们只是保存了模型的架构,而没保存权重。
四、在训练期间保存检查点
前面介绍的方法均是训练完毕之后再进行保存,如果训练期间断电的话,那么断电前训练的成果就丢失了。本部分介绍的是在训练的同时进行保存的方法。
1、定义检查点路径及名称,为当前目录下的training_cp/cp.ckpt中。
checkpoint_path = 'training_cp/cp.ckpt'
2、设置回调函数,即在训练过程中调用该函数,实现对模型的实时保存。save_weights_only=True表示只保存权重。
cp_callback = tf.keras.callbacks.ModelCheckpoint(checkpoint_path,
save_weights_only=True)
3、构建模型
model = tf.keras.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=(28,28))) # 28*28
model.add(tf.keras.layers.Dense(128, activation='relu'))
model.add(tf.keras.layers.Dense(10, activation='softmax'))
4、编译模型
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['acc']
)
5、训练模型,同时调用回调函数。
model.fit(train_image, train_lable, epochs=3, callbacks=[cp_callback])
输出结果为:
6、在测试数据集上评估模型
model.evaluate(test_image, test_label, verbose=0)
输出结果为:[0.3619687557220459, 0.8698999881744385]
7、再构建1个相同的模型
model_test = tf.keras.Sequential()
model_test.add(tf.keras.layers.Flatten(input_shape=(28,28))) # 28*28
model_test.add(tf.keras.layers.Dense(128, activation='relu'))
model_test.add(tf.keras.layers.Dense(10, activation='softmax'))
8、编译模型
model_test.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['acc']
)
9、载入权重
model_test.load_weights(checkpoint_path)
10、训练模型。在载入的权重的基础上训练。观察该步的训练结果,同时与第5步的训练结果进行对比,可以看出,该步是在第5步训练出的模型的基础上训练的。
model_test.fit(train_image, train_lable, epochs=3, callbacks=[cp_callback])
输出的训练结果:
11、在测试数据集上评估该模型
model_test.evaluate(test_image, test_label, verbose=0)
输出:[0.3371407389640808, 0.8802000284194946]