本文主要记录使用TensorFlow训练模型中与试验管理相关的最佳实践,主要包括模型训练的大致代码框架、模型的保存与恢复、训练过程的监测、随机性的控制等。主要材料来自CS 20SI: Tensorflow for Deep Learning Research。
TensorFlow代码框架
使用TensorFlow构建深度网络模型大致包括数据预处理、图的构建、模型训练、模型推断与评估等部分,大致的代码框架如下:
import tensorflow as tf
import numpy as np
# Data
X = tf.placeholder("float", [None, n_input])
Y = tf.placeholder("float", [None, n_output])
# Parameters
W = tf.Variable(tf.random_normal([n_input, n_output]))
b = tf.Variable(tf.random_normal([n_output]))
# Define model
y = tf.matmul(x, W) + b
y_pred = tf.nn.relu(y)
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_pred, y_true))
optimizer = tf.train.GradientDescentOptimizer(0.05).minimize(cost)
# Training
with tf.Session() as sess:
tf.initialize_all_variables().run()
sess.run(optimizer, feed_dict={X: x_data, Y: y_data})
# Prediction
y_test = tf.nn.relu(tf.matmul(x_test, W) + b))
模型的保存与恢复
一个很深的网络训练成本是比较高的,因而将模型定期保存(写入硬盘)则有必要。这里的模型,实际上是有组织的一批数据,包括图的结构描述、参数当前值等。因而我们要保存的不仅是模型,还有模型当前的运行状态,实际上每一次保存可以作为一个还原点。
tf.train.Saver类
使用tf.train.Saver
类需传入以下参数:tf.train.Saver.save(sess, save_path, global_step=step)
。
首先定义步数变量:self.global_step = tf.Variable(0, dtype=tf.int32, trainable=False,name='global_step')
在模型训练的过程中插入还原点的保存:
self.optimizer = tf.train.GradientDescentOptimizer(self.lr).minimize(self.loss,global_step=self.global_step)
saver = tf.train.Saver()
with tf.Session()as sess:
sess.run(tf.global_variables_initializer())
average_loss =0.0
for index in range(num_train_steps):
batch = batch_gen.next()
loss_batch, _ = sess.run([model.loss, model.optimizer], feed_dict={...})
average_loss += loss_batch
# Save model every 1000 steps
if(index +1)%1000==0:
saver.save(sess,'checkpoints/model', global_step=model.global_step)
在训练过程中,在checkpoints
路径下会存储一系列的还原点文件,要恢复session到某个还原点,可使用如下代码:saver.restore(sess, 'checkpoints/name_of_the_checkpoint')
。
Keras封装:keras.callbacks.ModelCheckpoint()
Keras对TensorFlow进行了高层的封装,使用一系列回调函数keras.callbacks.Callback()
来进行试验管理。
模型保存ModelCheckpoint()
需要传入的参数:keras.callbacks.ModelCheckpoint(filepath, monitor='val_loss', verbose=0, save_best_only=False, save_weights_only=False, mode='auto', period=1)
实际的使用中,将上述回调函数类传入model.fit()
过程即可:
from keras.callbacks import ModelCheckpoint
model = Sequential()
model.add(Dense(10, input_dim=784, kernel_initializer='uniform'))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
checkpointer = ModelCheckpoint(filepath='/checkpoints/weights.hdf5', verbose=1, save_best_only=True)
model.fit(x_train, y_train, batch_size=128, epochs=20, verbose=0, validation_data=(X_test, Y_test), callbacks=[checkpointer])
模型训练过程的监测
训练过程中,我们常常需要提取阶段性的信息来评估模型是否符合预期效果。
tf.summary
首先创建想要观察指标的tf.summary
对象:
with tf.name_scope("summaries"):
tf.summary.scalar("loss", self.loss)
tf.summary.scalar("accuracy", self.accuracy)
tf.summary.histogram("histogram loss", self.loss)
# merge them all
self.summary_op = tf.summary.merge_all()
tf.summary
是一种operation,因而可以随训练过程一同运行:loss_batch, _, summary = sess.run([model.loss, model.optimizer, model.summary_op], feed_dict=feed_dict)
最后,将summary加入writer以写入文件:
with tf.Session() as sess:
writer = tf.summary.FileWriter('./summary', sess.graph)
for index in range(num_train_steps):
writer.add_summary(summary, global_step=step)
writer.close()
这样,就可以用TensorBoard监测我们关心的指标在训练过程中的变化情况。
Keras封装:keras.callbacks.TensorBoard()
Keras同样将TensorBoard封装成回调函数的形式,在模型训练时进行调用即可:
from keras.callbacks import TensorBoard
tensorboard = TensorBoard(log_dir="./logs")
model.fit(x_train, y_train, batch_size=128, epochs=20, verbose=0, validation_data=(X_test, Y_test), callbacks=[tensorboard]
随机性的控制
TensorFlow中随机性的控制分为operation和graph两个层面。
Operation层面
在Operation层面中,建立随机seed之后,新建立的Session每一次调用sess.run()
都会遵循同一随机状态:
c = tf.random_uniform([],-10,10, seed=2)
with tf.Session()as sess:
print sess.run(c) # >> 3.57493
with tf.Session()as sess:
print sess.run(c) # >> 3.57493
而且,不同的operation可以保存自己的seed:
c = tf.random_uniform([],-10,10, seed=1)
d = tf.random_uniform([],-10,10, seed=2)
with tf.Session() as sess:
sess.run(c)
sess.run(d)
Graph层面
在Graph层面,整张图公用一个随机状态,多次运行同一图模型的计算,其随机状态保持一致。
import tensorflow as tf
tf.set_random_seed(2)
c = tf.random_uniform([],-10,10)
d = tf.random_uniform([],-10,10)
with tf.Session() as sess:
sess.run(c)
sess.run(d)