将训练好的模型参数保存起来,以便验证或测试,这是我们在训练过程中经常做的事情。tf里面提供模型保存的代码是tf.train.Saver()。模型保存,先要创建一个Saver对象:如
saver=tf.train.Saver()
在创建Saver对象时,我们经常会使用 max_to_keep 参数,这个参数的作用是用来设置保存模型的个数,默认为5
max_to_keep=5
既保存最近的5个模型。
如果需要每训练一代(epoch)就保存一次模 型,则可将 max_to_keep设置为None或0,如:
saver=tf.train.Saver(max_to_keep=0)
如果你只想保存最后一代的模型,则只需要将max_to_keep设置为1即可。如:
saver=tf.train.Saver(max_to_keep=1)
创建完saver对象后,就可以保存训练的模型了,如:
saver.save(sess,'----------',global_step=step)
第一个参数sess,就不用说了。第二个参数设定保存的路径和名字,第三个参数将训练的次数作为后缀加入到模型名字中。
mnist实例:
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=False)
x = tf.placeholder(tf.float32, [None, 784])
y_=tf.placeholder(tf.int32,[None,])
dense1 = tf.layers.dense(inputs=x,
units=1024,
activation=tf.nn.relu,
kernel_initializer=tf.truncated_normal_initializer(stddev=0.01),
kernel_regularizer=tf.nn.l2_loss)
dense2= tf.layers.dense(inputs=dense1,
units=512,
activation=tf.nn.relu,
kernel_initializer=tf.truncated_normal_initializer(stddev=0.01),
kernel_regularizer=tf.nn.l2_loss)
logits= tf.layers.dense(inputs=dense2,
units=10,
activation=None,
kernel_initializer=tf.truncated_normal_initializer(stddev=0.01),
kernel_regularizer=tf.nn.l2_loss)
loss=tf.losses.sparse_softmax_cross_entropy(labels=y_,logits=logits)
train_op=tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)
correct_prediction = tf.equal(tf.cast(tf.argmax(logits,1),tf.int32), y_)
acc= tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
sess=tf.InteractiveSession()
sess.run(tf.global_variables_initializer())
saver=tf.train.Saver(max_to_keep=1)
for i in range(100):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_op, feed_dict={x: batch_xs, y_: batch_ys})
val_loss,val_acc=sess.run([loss,acc], feed_dict={x: mnist.test.images, y_: mnist.test.labels})
print('epoch:%d, val_loss:%f, val_acc:%f'%(i,val_loss,val_acc))
saver.save(sess,'/home/pycharmcode/',global_step=i+1)
sess.close()
代码中红色部分就是保存模型的代码,虽然每次训练一次代码的,都进行了保存,但后一次保存的模型会覆盖前一次的,最终只会保存最后一次。因此我们可以节省时间,将保存代码放到循环之外(仅适用max_to_keep=1,否则还是需要放在循环内).
在实验中,最后一代可能并不是验证精度最高的一代,因此我们并不想默认保存最后一代,而是想保存验证精度最高的一代,则加个中间变量和判断语句就可以了。
saver=tf.train.Saver(max_to_keep=1)
max_acc=0
for i in range(100):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_op, feed_dict={x: batch_xs, y_: batch_ys})
val_loss,val_acc=sess.run([loss,acc], feed_dict={x: mnist.test.images, y_: mnist.test.labels})
print('epoch:%d, val_loss:%f, val_acc:%f'%(i,val_loss,val_acc))
if val_acc>max_acc:
max_acc=val_acc
saver.save(sess,'/home/pycharmcode/',global_step=i+1)
sess.close()
如果我们想保存验证精度最高的三代,且把每次的验证精度也随之保存下来,则我们可以生成一个txt文件用于保存。
saver=tf.train.Saver(max_to_keep=3)
max_acc=0
f=open('/home/pycharm.txt','w')
for i in range(100):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_op, feed_dict={x: batch_xs, y_: batch_ys})
val_loss,val_acc=sess.run([loss,acc], feed_dict={x: mnist.test.images, y_: mnist.test.labels})
print('epoch:%d, val_loss:%f, val_acc:%f'%(i,val_loss,val_acc))
f.write(str(i+1)+', val_acc: '+str(val_acc)+'\n')
if val_acc>max_acc:
max_acc=val_acc
saver.save(sess,'/home/pycharmcode/',global_step=i+1)
f.close()
sess.close()
复制代码
模型的恢复用的是restore()函数,它需要两个参数restore(sess, save_path),save_path指的是保存的模型路径。我们可以使用tf.train.latest_checkpoint()来自动获取最后一次保存的模型。如:
model_file=tf.train.latest_checkpoint('home/')
saver.restore(sess,model_file)