页面树结构

2017-11-09 ApacheCN 开源组织,第二期邀请成员活动,一起走的更远 : http://www.apachecn.org/member/209.html


MachineLearning 优酷地址 : http://i.youku.com/apachecn

转至元数据结尾
转至元数据起始

训练模型时,实时跟踪和评估进度通常很有价值。在本教程中,您将学习如何使用TensorFlow的日志记录功能和MonitorAPI来监督正在用神经网络分类器分类irises的训练情况。本教程基于tf.contrib.learn快速入门中的代码开发,因此如果您尚未完成该教程,您可能需要首先探索它,特别是如果您正在寻找tf.contrib.learn基础的介绍/复习。

 

构建

在本教程中,你将基于以下来自tf.contrib.learn快速入门的代码 :

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os

import numpy as np
import tensorflow as tf

# Data sets
IRIS_TRAINING = os.path.join(os.path.dirname(__file__), "iris_training.csv")
IRIS_TEST = os.path.join(os.path.dirname(__file__), "iris_test.csv")

def main(unused_argv):
    # Load datasets.
    training_set = tf.contrib.learn.datasets.base.load_csv_with_header(
        filename=IRIS_TRAINING, target_dtype=np.int, features_dtype=np.float32)
    test_set = tf.contrib.learn.datasets.base.load_csv_with_header(
        filename=IRIS_TEST, target_dtype=np.int, features_dtype=np.float32)

    # Specify that all features have real-value data
    feature_columns = [tf.contrib.layers.real_valued_column("", dimension=4)]

    # Build 3 layer DNN with 10, 20, 10 units respectively.
    classifier = tf.contrib.learn.DNNClassifier(feature_columns=feature_columns,
                                                hidden_units=[10, 20, 10],
                                                n_classes=3,
                                                model_dir="/tmp/iris_model")

    # Fit model.
    classifier.fit(x=training_set.data,
                   y=training_set.target,
                   steps=2000)

    # Evaluate accuracy.
    accuracy_score = classifier.evaluate(x=test_set.data,
                                         y=test_set.target)["accuracy"]
    print('Accuracy: {0:f}'.format(accuracy_score))

    # Classify two new flower samples.
    new_samples = np.array(
        [[6.4, 3.2, 4.5, 1.5], [5.8, 3.1, 5.0, 1.7]], dtype=float)
    y = list(classifier.predict(new_samples, as_iterable=True))
    print('Predictions: {}'.format(str(y)))

if __name__ == "__main__":
  tf.app.run()
将上述代码复制到文件中,并将相应的训练test数据集下载到相同目录。

在以下部分中,您将逐步更新上述代码以添加日志记录和监视功能。最终更新的完整代码可从这里下载

 

概述

tf.contrib.learn快速入门教程告诉我们如何实现一个神经网络分类器对iris例子分类。

但是当本教程的代码运行时,输出不包含训练模型如何进行记录跟踪 ,只打印以下语句的结果 :

Accuracy: 0.933333
Predictions: [1 2]
没有任何记录,模型训练感觉像一个黑盒子; 您不能看到TensorFlow通过梯度下降算法在每一步中发生了什么,了解模型是否正确收敛,或者监督
early stopping提前结束训练是否合适。

解决这个问题的一种方法是将模型训练分成多个fit,调用更少的步长数,以逐步评估模型准确性。然而,这不是推荐的做法,因为它大大减慢了模型训练速度。幸运的是,tf.contrib.learn提供了另一种解决方案: Monitor API,它旨在帮助您在训练过程中记录指标并评估您的模型。在以下部分中,您将学习如何在TensorFlow中启用日志记录,设置ValidationMonitor进行流评估,并使用TensorBoard可视化您的metrics。

 

使用TensorFlow启用日志记录

TensorFlow使用五个不同级别的日志消息。按问题严重性升序排列,分别是DEBUGINFOWARNERROR,和FATAL。当您在任意这些级别配置日志记录时,TensorFlow将输出与该级别以及问题更严重级别相对应的所有日志消息。例如,如果设置了日志记录级别ERROR,则会收到包含日志输出 ERRORFATAL消息,如果设置了一个级别DEBUG,则会从所有五个级别获取日志消息。

默认情况下,TensorFlow被配置在WARN日志级别,但是当跟踪模型训练时,您需要将级别调整为INFO,这将在fit操作运行时提供更多的反馈。

将下行添加到代码的开头(在import导入之后):

tf.logging.set_verbosity(tf.logging.INFO)
现在运行代码时,会看到如下所示的其他日志输出:
INFO:tensorflow:loss = 1.18812, step = 1
INFO:tensorflow:loss = 0.210323, step = 101
INFO:tensorflow:loss = 0.109025, step = 201
使用INFO级别日志记录,tf.contrib.learn会在每100步之后自动将training-loss metrics输出到stderr。

 

配置验证监视器进行流评估

记录训练损失有助于了解您的模型是否收敛,但如果您想进一步了解训练中发生的情况怎么办?tf.contrib.learn提供了几个高级别Monitor,您可以附加到您的fit操作,以进一步跟踪metrics/调试模型训练期间的更低级别TensorFlow操作,包括:

监控描述
CaptureVariable在训练的每n步中将指定的变量的值保存到集合中
PrintTensor在训练的每n步记录指定的张量值
SummarySaver在训练的每n步中使用tf.summary.FileWriter保存tf.Summary protocol buffers 成给定张量 
ValidationMonitor在训练的每n步记录一组指定的评估指标,如果需要,在一定条件下实现提前停止

隔N步评估

对于iris神经网络分类器,在记录训练损失时,您可能还需要同时对测试数据进行评估,以了解该模型的泛化程度。您可以通过配置测试数据的ValidationMonitortest_set.datatest_set.target)并通过设置every_n_steps评估的频率来实现此目的。every_n_steps的默认值是 100; 本例设定every_n_steps50,即模型训练后每50步进行评估:

validation_monitor = tf.contrib.learn.monitors.ValidationMonitor(
    test_set.data,
    test_set.target,
    every_n_steps=50)
将此代码放在实例化classifier那行之前。

ValidationMonitor依靠保存的checkpoints执行评估操作,因此您需要添加包含save_checkpoints_secstf.contrib.learn.RunConfig去修改classifier的实例化,该参数指定在训练期间经过多少秒保存checkpoint。由于iris数据集相当小,因此训练速度很快,设置save_checkpoints_secs为1(每1秒保存checkpoint)以确保足够数量的checkpoint:

classifier = tf.contrib.learn.DNNClassifier(
    feature_columns=feature_columns,
    hidden_units=[10, 20, 10],
    n_classes=3,
    model_dir="/tmp/iris_model",
    config=tf.contrib.learn.RunConfig(save_checkpoints_secs=1))
注意:model_dir参数指定/tmp/iris_model目录存储模型数据; 比起自动生成的目录,这个目录路径在后面操作中更容易被引用。每次运行代码时,任
存在于/tmp/iris_model中的数据将被加载,并且模型训练将在上一次运行中停止的地方继续运行(例如,在训练期间成功运行两次脚本去执行4000步
即每次fit操作执行2000步)。为了从scratch开始整个模型的训练,在运行代码之前删除/tmp/iris_model 。

最后,附加您的validation_monitor,更新包快调用monitors参数的fit,该参数在模型训练期间生成包含所有monitors的list:

classifier.fit(x=training_set.data,
               y=training_set.target,
               steps=2000,
               monitors=[validation_monitor])
现在,当您重新运行代码时,您应该在日志输出中看到验证metrics,例如:
INFO:tensorflow:Validation (step 50): loss = 1.71139, global_step = 0, accuracy = 0.266667
...
INFO:tensorflow:Validation (step 300): loss = 0.0714158, global_step = 268, accuracy = 0.966667
...
INFO:tensorflow:Validation (step 1750): loss = 0.0574449, global_step = 1729, accuracy = 0.966667

使用MetricSpec定义Evaluation Metrics

默认情况下,如果未指定evaluation metrics,ValidationMonitor则会记录 loss 和accuracy,但可以自定义每50步运行的metrics列表。为了指定你在每次evaluation时的精确metrics,可以向ValidationMonitor构造函数中添加一个 metrics参数。metrics采用key/value对的字典,其中每个key是您要记录metric的名称,对应的value是一个 MetricSpec 对象。

MetricSpec构造函数接受四个参数:

  • metric_fn。计算和返回metric值的函数。这可以是在tf.contrib.metrics模块中得到的预定义函数 ,例如tf.contrib.metrics.streaming_precision或 tf.contrib.metrics.streaming_recall

    或者,您可以自定义metric函数,它们必须采用predictionslabels张量作为参数(weights也可以成为可选参数)。该函数必须以两种格式之一返回metric值:

    • 单一张量
    • 一对(value_op, update_op)操作,value_op返回metric值,update_op执行相应的操作来更新模型内部状态。
  • prediction_key。包含返回模型预测的张量的key。如果模型返回单个张量或具有单个entry的字典,则可以省略此参数。对于DNNClassifier模型,通过key为 tf.contrib.learn.PredictionKey.CLASSES,类预测将被返回成一个张量

  • label_key。包含模型返回标签的张量的key,由模型input_fn 指定。与prediction_key相同,如果input_fn 返回单个张量或具有单个entry的字典,则可以省略此参数。在本教程的iris示例中,DNNClassifier没有input_fn (xy数据直接传递给fit),因此没有必要提供label_key

  • weights_key可选。包含权重输入给 metric_fn张量的key(通过input_fn返回)。

以下代码创建一个validation_metrics在模型评估期间定义要记录的三个metric的dict:

validation_metrics = {
    "accuracy":
        tf.contrib.learn.MetricSpec(
            metric_fn=tf.contrib.metrics.streaming_accuracy,
            prediction_key=tf.contrib.learn.prediction_key.PredictionKey.
            CLASSES),
    "precision":
        tf.contrib.learn.MetricSpec(
            metric_fn=tf.contrib.metrics.streaming_precision,
            prediction_key=tf.contrib.learn.prediction_key.PredictionKey.
            CLASSES),
    "recall":
        tf.contrib.learn.MetricSpec(
            metric_fn=tf.contrib.metrics.streaming_recall,
            prediction_key=tf.contrib.learn.prediction_key.PredictionKey.
            CLASSES)
}
ValidationMonitor构造函数之前添加上面的代码。然后ValidationMonitor按照以下方式修改构造函数,添加一个metrics参数以记录指定的正确度
与精度,并指定validation_metrics回调metrics (损失始终记录,不需要明确指定):
validation_monitor = tf.contrib.learn.monitors.ValidationMonitor(
    test_set.data,
    test_set.target,
    every_n_steps=50,
    metrics=validation_metrics) 
重新运行代码,您应该看到日志输出中包含的精度和回调,例如:
INFO:tensorflow:Validation (step 50): recall = 0.0, loss = 1.20626, global_step = 1, precision = 0.0, accuracy = 0.266667
...
INFO:tensorflow:Validation (step 600): recall = 1.0, loss = 0.0530696, global_step = 571, precision = 1.0, accuracy = 0.966667
...
INFO:tensorflow:Validation (step 1500): recall = 1.0, loss = 0.0617403, global_step = 1452, precision = 1.0, accuracy = 0.966667 

通过ValidationMonitor提前停止训练

注意,在上述日志输出中,在600步是,该模型已经实现了1.0的精度和回调率。这产生了模型训练是否可以从提前停止中受益的问题 。

除了记录eval metrics之外,ValidationMonitor满足指定条件时通过三个参数来轻松实现提前停止:

参数描述
early_stopping_metricearly_stopping_roundsearly_stopping_metric_minimize这两个指定条件下,metric触发提前停止(例如,loss或accuary)。默认是"loss"
early_stopping_metric_minimizeTrue:模型最小化early_stopping_metric值; False:模型最大化early_stopping_metric值。默认是True
early_stopping_rounds设置了步数大小,在此期间,如果early_stopping_metric不减少(如果early_stopping_metric_minimize是 True)或增加(如果early_stopping_metric_minimize是 False),训练将被停止。默认是None,这意味着提前停止将永远不会默认发生。

ValidationMonitor构造函数进行以下修订,指定如果在200步(early_stopping_rounds=200)后loss(early_stopping_metric="loss")不减少(early_stopping_metric_minimize=True),模型训练将在该点立即停止,并且不能完成规定的完整的2000步fit

validation_monitor = tf.contrib.learn.monitors.ValidationMonitor(
    test_set.data,
    test_set.target,
    every_n_steps=50,
    metrics=validation_metrics,
    early_stopping_metric="loss",
    early_stopping_metric_minimize=True,
    early_stopping_rounds=200) 
重新运行代码,看看模型训练是否早点停止:
...
INFO:tensorflow:Validation (step 1150): recall = 1.0, loss = 0.056436, global_step = 1119, precision = 1.0, accuracy = 0.966667
INFO:tensorflow:Stopping. Best step: 800 with loss = 0.048313818872.
实际上,这里的训练在1150步停止,表明在过去的200个步骤中,loss没有减少,而总的来说,800步相对于测试数据集产生最小的损失值。这表明通过
减少步数可以进一步改进模型,进一步校准超参数。


用TensorBoard可视化日志数据

读取通过ValidationMonitor在训练期间产生大量关于模型性能的原始数据的日志,此数据的可视化,对进一步了解趋势可能会有帮助,例如准确性如何随着步数而变化。您可以使用TensorBoard(TensorFlow的独立包)通过将logdir命令行参数设置为保存模型训练数据的目录(这里设为/tmp/iris_model)来绘制图形。在命令行上运行以下命令:

$ tensorboard --logdir=/tmp/iris_model/
Starting TensorBoard 39 on port 6006 

然后在浏览器中导航到 http://0.0.0.0:<port_number>,这里的<port_number>是指定命令行输出的端口(这里为6006)。

如果您点击准确性属性,您将看到如下图像,其中显示了相对于步数计算的精度:

有关使用TensorBoard的更多信息,请参阅TensorBoard:可视化学习TensorBoard:图形可视化

 

  • 无标签