Tensorflow最佳实践:试验管理

本文主要记录使用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)

@ddlee

[源码笔记]keras源码分析之Layer、Tensor和Node [论文笔记]Accurate, Large Minibatch SGD: Training ImageNet in One Hour
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×