图片数据的常用训练步骤
由于mnist数据集的别捷性,在讲解原理性的知识时,是首选的数据集。本文整理了一个模型从数据及准备到训练的完整步骤,可以作为模板使用。
一、数据集的加载
这一步是将数据标注工具标注完的数据加载到内存的过程,关于数据标注的具体内容请参考 深度学习,先学会制作自己的数据集
由于是深度学习的起步阶段,我们先简单试用一下mnist数据集。
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
from tensorflow.keras.layers import Dense, Flatten, Conv2D
from tensorflow.keras import Model
(x_train,y_train),(x_test,y_test)=tf.keras.datasets.mnist.load_data()
二、数据预处理
数据集加载到内存后,往往不能直接用于训练。常常为了改变数据集客观存在的问题,比如数据集比较小,数据集的图片太大,数据集的图片大小不统一等等,这些问题会直接影响训练的时模型收敛情况和最终的准确性。因此做好这一步非常重要。在此简单说明一下。
##归一化操作,这是数据集预处理时的常用操作,把像素值转换到0~1之间
x_train, x_test = x_train / 255.0, x_test / 255.0
##给数据集图片增加一个维度 shape由(28,28)=》(28,28,1)
x_train = x_train[..., tf.newaxis]
x_test = x_test[..., tf.newaxis]
对数据集中的图片进行打乱操作
train_ds = tf.data.Dataset.from_tensor_slices(
(x_train, y_train)).shuffle(10000).batch(32)
test_ds = tf.data.Dataset.from_tensor_slices(
(x_test, y_test)).batch(32)
三、自定义模型
模型搭建可以用keras高级API来快速搭建,但实际应用中常常需要自己自定义搭建,因此介绍自定义模型类的方式来实现模型的搭建。
class MyModel(Model):
def __init__(self):##定义网络结构
super(MyModel, self).__init__()
self.conv1 = Conv2D(32, 3, activation='relu')
self.flatten = Flatten()
self.d1 = Dense(128, activation='relu')
self.d2 = Dense(10, activation='softmax')
def call(self, x):##前馈网络,其实就是过一遍初始化中搭建的网络
x = self.conv1(x)
x = self.flatten(x)
x = self.d1(x)
print(x.shape)
return self.d2(x)
# 实例化一个模型
model = MyModel()
四、损失函数和优化器的指定
模型通过最小化损失函数求解和评估模型,和优化器一起为模型训练提供学习准则和优化方向。常见的损失函数为交叉熵随时函数,优化器在这里选择Adam,当然这些可以选择tf提供的方法也可以自定义。
loss_object = tf.keras.losses.SparseCategoricalCrossentropy()
optimizer = tf.keras.optimizers.Adam()
五、训练集和测试集的准确率计算
准确率以及loss值能够直观的反应模型的训练情况,作为模型评估和分析的直接依据。
train_loss = tf.keras.metrics.Mean(name='train_loss')
train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='train_accuracy')
test_loss = tf.keras.metrics.Mean(name='test_loss')
test_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='test_accuracy')
六、单步训练函数的定义
使用tf.GradientTape来训练模型效率更高,其实就是是在函数前面添加@tf.function。
@tf.function
def train_step(images, labels):
with tf.GradientTape() as tape:
predictions = model(images)
loss = loss_object(labels, predictions)
gradients = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(gradients, model.trainable_variables))
train_loss(loss)
train_accuracy(labels, predictions)
@tf.function
def a_test_step(images, labels):
predictions = model(images)
t_loss = loss_object(labels, predictions)
test_loss(t_loss)
test_accuracy(labels, predictions)
七、循环训练开始
为了使模型更准确,一般都会设置多个批次,每个批次加载一定量的图片送入模型进行训练,这里注意每完成一个批次,损失值和准确率的变量要清零。
EPOCHS = 5
for epoch in range(EPOCHS):
for images, labels in train_ds:
train_step(images, labels)
for test_images, test_labels in test_ds:
a_test_step(test_images, test_labels)
template = 'Epoch {}, Loss: {}, Accuracy: {}, Test Loss: {}, Test Accuracy: {}'
print(template.format(epoch+1,
train_loss.result(),
train_accuracy.result()*100,
test_loss.result(),
test_accuracy.result()*100))
# 注意这里要reset一下
train_loss.reset_states()
train_accuracy.reset_states()
test_loss.reset_states()
test_accuracy.reset_states()
八、模型保存
保存模型常用的种方式,save/load weights
只保存了参数,文件较小,加载较快,但是测试/部署时需要重建搭建网络。
##保存
model.save_weights('./checkpoints/my_checkpoint')
##加载
model = model(images) #model必须和之前定义的模型一模一样
model.load_weights('./checkpoints/my_checkpoint') #加载训练好的权重
Save the model
该方法把模型也保存了,文件较大,效率比较低。
#保存模型和参数
model.save('model.h5')
#删除模型和参数
del model
#重新加载模型和参数
newmodel= tf.keras.models.load_model('model.h5')
newmodel.evaluate(x_val, y_val)
注意:常常在保存模型之前还会对模型进行评估,保存完模型后会对模型进行测试,本文只是一个概要流程,具体内容将在后续文章详细讨论。