训练和评价模型


我们已经完成了对MNIST的卷积神经网络的编码,现在我们就来训练和评价它。

加载训练和测试数据

首先让我们加载训练和测试数据。增加一个main方法:


def main(unused_argv):
  # Load training and eval data
  mnist = tf.contrib.learn.datasets.load_dataset("mnist")
  train_data = mnist.train.images # Returns np.array
  train_labels = np.asarray(mnist.train.labels, dtype=np.int32)
  eval_data = mnist.test.images # Returns np.array
  eval_labels = np.asarray(mnist.test.labels, dtype=np.int32)

我们存储了训练数据的feature数据,55000张手写数字图片的灰度值。还有每个图片对应的label,也就是0-9的的数字。都是用numpy数组来表示。对于评价数据也是类似的。

创建一个Estimator

接下来让我们来创建一个Estimator,它是一个执行模型训练,验证测试的高层API。我们增加如下的代码:


# Create the Estimator
mnist_classifier = tf.estimator.Estimator(
    model_fn=cnn_model_fn, model_dir="/tmp/mnist_convnet_model")

model_fn参数指定了用来对模型进行训练,验证,预测的方法。我们用之前创建的额cnn_model_fn作为model_fn的参数。model_dir参数用来指定我们存储模型数据(checkpoints)的路径。

如果想更深一步的了解Estimator的API,可以看这篇文章

设置Logging Hook

因为卷积网络比较费时间,我们来设置一些log这样让我们可以知道训练的进度。我们可以用tensorflow的tf.train.SessionRunHook来创建一个tf.train.LoggingTensorHook。然后用它来输出我们卷积网络中softmax层输出的概率值。


# Set up logging for predictions
  tensors_to_log = {"probabilities": "softmax_tensor"}
  logging_hook = tf.train.LoggingTensorHook(
      tensors=tensors_to_log, every_n_iter=50)

我们把我们想要记录log的tensor放到一个dict里,key是我们自定义的名字,value是想要log的tensor的名字。像上边的代码里,我们需要几率的tensor是softmax_tensor,这个tensor是上边softmax输出的tensor。

如果你没有指定tensor的名字,TensorFlow 可以assign一个默认的名字,你可以通过下边的方法来看到tensorflow默认指定的名字。一个是通过[TensorBoard](https://www.tensorflow.org/programmers_guide/graph_viz)。或者用[TensorFlow Debugger](https://www.tensorflow.org/programmers_guide/debugger)

接下来,我们创建LoggingTensorHook,把tensors_to_log传给tensors这个参数,再设置every_n_iter=50,这样我们就可以每隔50次训练迭代记录一次softmax输出的概率值。

训练模型

现在我们可以训练我们的模型了。我们可以通过创建train_input_fn方法并对mnist_classifier调用train():


# 训练模型
train_input_fn = tf.estimator.inputs.numpy_input_fn(
    x={"x":train_data},
    y=train_labels,
    batch_size=100,
    num_epochs=None,
    shuffle=True)
mnist_classifier.train(
    input_fn=train_input.fn,
    steps=20000,
    hooks=[logging_hook])

在numpy_input_fn调用时,我们给参数x传递训练的feature data构成的一个dict。labels作为y。batch_size=100 表示每次训练选取100个样例作为一个batch。num_epochs=None表明会一直获取数据直到训练的step到达。steps=20000表明一共训练20000次迭代。最后我们把logging_hook传给train方法,这样在到达logginghook指定的迭代后,就会触发logging_hook来记log。

评价模型

训练完成后,我们想评价一下我们的模型精度,我们可以用evaluate方法,这个方法会对我们在model_fn里指定的eval_metric_ops参数进行求值。我们添加如下的代码:


# 评价模型并打印结果
eval_input_fn = tf.estimator.inputs.numpy_input_fn(
    x={"x": eval_data},
    y=eval_labels,
    num_epochs=1,
    shuffle=False)
eval_results=mnist_classifier.evaluate(input_fn=eval_input_fn)
print(eval_results)

在这里我们把num_epochs设置为1,因为只需要过一遍验证数据。并且也没有必要对数据shuffle,所以我们设置shuffle为False。

运行模型

我们已经完成了对我们卷积神经网络的模型方法,Estimator,training/evalution的编码。现在我们运行一下我们的代码看一下结果。

运行速度和你的硬件性能有很大关系,一般在CPU上跑的话需要1个小时,你可以减少训练的迭代次数也就是train()方法的stpes参数。来更快的看到结果。

当模型运行时,你可以看到这样的log:


INFO:tensorflow:loss = 2.36026, step = 1
INFO:tensorflow:probabilities = [[ 0.07722801  0.08618255  0.09256398, ...]]
...
INFO:tensorflow:loss = 2.13119, step = 101
INFO:tensorflow:global_step/sec: 5.44132
...
INFO:tensorflow:Loss for final step: 0.553216.

INFO:tensorflow:Restored model from /tmp/mnist_convnet_model
INFO:tensorflow:Eval steps [0,inf) for training step 20000.
INFO:tensorflow:Input iterator is exhausted.
INFO:tensorflow:Saving evaluation summary for step 20000: accuracy = 0.9733, loss = 0.0902271
{'loss': 0.090227105, 'global_step': 20000, 'accuracy': 0.97329998}

上边的log显示我们的模型有97.3%的准确度。

其他资源

学习更多的关于TensorFlow Estimator和卷积神经网络的知识,你可以看下边的资源:
Createing Estimators in tf.estimator 是一个关于TensorFlow Estimator API的书名,它过了一遍如何配置一个Estimator,写一个model方法,计算loss,和定义一个training op
Convolutional Neural Networks讲了如何不用Estimator,用Tensorflow的底层API进行MNIST分类。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

%d 博主赞过: