页面树结构

版本比较

标识

  • 该行被添加。
  • 该行被删除。
  • 格式已经改变。
评论: 修正翻译文档

目录

 

面板
borderColor#00FFFF
borderStyledashed

原文链接 : https://www.tensorflow.org/tutorials/layers

译文链接 : http://www.apache.wiki/pages/viewpage.action?pageId=10029443

贡献者 : 片刻 ApacheCN Apache中文网

校对:Ngxin

TensorFlow layers模块提供了一个高级API,可以轻松构建神经网络。它提供了更好的创建密集(全连接)层和卷积层,添加激活函数以及应用dropout正则化的方法。在本教程中,您将学习使用layers构建卷积神经网络模型来识别MNIST数据集中的手写数字。

所述MNIST数据集包括60000个训练样例和10000个测试样例的0-9的手写数字,格式为28x28像素的灰度图像。

 

入门

我们设计TensorFlow程序的架构。创建一个叫 cnn_mnist.py的文件,并添加以下代码:

代码块
languagepy
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

# Imports
import numpy as np
import tensorflow as tf

from tensorflow.contrib import learn
from tensorflow.contrib.learn.python.learn.estimators import model_fn as model_fn_lib

tf.logging.set_verbosity(tf.logging.INFO)

# Our application logic will be added here

if __name__ == "__main__":
  tf.app.run() 
在您完成本教程时,您将添加代码去构建,训练和评估卷积神经网络。完整的最终代码可以在 这里找到

卷积神经网络简介

卷积神经网络(CNN)是用于图像分类任务的当前最先进的模型架构。CNN将一系列过滤器应用于图像的原始像素数据,以提取和学习更高级别的特征,模型可用于分类。CNN包含三个组成部分:

  • 卷积层,指定用于图片的卷积滤波器数量。对于每个子区域,卷积层执行一系列数学运算,以在输出特征图中产生单个值。卷积层通常将 ReLU激活函能应用于输出,以将非线性引入到模型中。

  • 池化层,为了降低特征图的维度,以减少计算时间,池化层对卷积层进行下采样。通常使用的池化算法是最大池,其提取特征图的子区域(例如,2×2像素块),选择其最大值,并丢弃所有其他值。

  • 密集(全连接)层,该层对卷积层以及池层进行下采样提取的特征进行分类。在密集层中,层中的每个节点连接到上一层中的每个节点。

通常,CNN由许多执行特征提取的卷积模块组成。每个模块由一个卷积层接一个池层组成。最后一个卷积模块后是一个或多个执行分类的密集层。CNN中的最终密集层包含模型中每个目标类的单个节点(模型预测的所有可能的类),其中 softmax激活函数为每个节点生成0-1之间的值(所有这些softmax值加起来等于1)。我们可以这样解释softmax值:该值为给定图片属于每个目标类的可能性的相对度量。

注意:对于CNN架构的更全面的理解,请参阅斯坦福大学的 用于视觉识别的卷积神经网络课程

 

构建基于CNN的MNIST分类器

我们使用以下CNN架构构建一个模型来对MNIST数据集中的图像进行分类:

  1. 卷积层#1:应用32个5x5滤波器(也叫卷积核)(提取5x5像素的子区域),该层同时带有ReLU激活函数
  2. 池化层#1:使用步长为2的2x2滤波器执行最大池化(指定的被池化的区域不重叠)
  3. 卷积层#2:应用64个5x5滤波器,该层同时带有ReLU激活函数
  4. 全连接层#2:再次使用2x2滤波器执行最大池,并且步长同样为2
  5. 全连接层#1:1024个神经元,舍弃掉的神经元比例为0.4(在训练期间任何给定元素被舍弃的概率为0.4)
  6. 全连接层#2(Logit Layer):10个神经元,每个神经元对应一个数字目标类(0-9)。

tf.layers模块包含创建上述三种层类型中的每一种的方法:

  • conv2d()。构造二维卷积层。参数包含卷积核数量,卷积核大小,padding和激活函数。
  • max_pooling2d()。使用最大池化算法构建二维池化层。池化的滤波器大小和步长作为参数。
  • dense()。构造一个全连接层。神经元数量和激活函数作为参数。

这些方法中的每一个都接受张量作为输入,并将转换的张量作为输出返回。这样可以轻松地将一层连接到另一层:只需从已经创建的层获取输出,并将其作为输入提供给另一层。

打开cnn_mnist.py并添加cnn_model_fn函数,它符合TensorFlow的Estimator API预期的接口(更多介绍在后面的创建估计器中)。cnn_mnist.py将MNIST特征数据,标签和 模型模式TRAINEVAL, INFER)作为参数; 配置CNN; 并返回预测,损失和训练操作:

代码块
languagepy
def cnn_model_fn(features, labels, mode):
  """Model function for CNN."""
  # Input Layer
  input_layer = tf.reshape(features, [-1, 28, 28, 1])

  # Convolutional Layer #1
  conv1 = tf.layers.conv2d(
      inputs=input_layer,
      filters=32,
      kernel_size=[5, 5],
      padding="same",
      activation=tf.nn.relu)

  # Pooling Layer #1
  pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)

  # Convolutional Layer #2 and Pooling Layer #2
  conv2 = tf.layers.conv2d(
      inputs=pool1,
      filters=64,
      kernel_size=[5, 5],
      padding="same",
      activation=tf.nn.relu)
  pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)

  # Dense Layer
  pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 64])
  dense = tf.layers.dense(inputs=pool2_flat, units=1024, activation=tf.nn.relu)
  dropout = tf.layers.dropout(
      inputs=dense, rate=0.4, training=mode == learn.ModeKeys.TRAIN)

  # Logits Layer
  logits = tf.layers.dense(inputs=dropout, units=10)

  loss = None
  train_op = None

  # Calculate Loss (for both TRAIN and EVAL modes)
  if mode != learn.ModeKeys.INFER:
    onehot_labels = tf.one_hot(indices=tf.cast(labels, tf.int32), depth=10)
    loss = tf.losses.softmax_cross_entropy(
        onehot_labels=onehot_labels, logits=logits)

  # Configure the Training Op (for TRAIN mode)
  if mode == learn.ModeKeys.TRAIN:
    train_op = tf.contrib.layers.optimize_loss(
        loss=loss,
        global_step=tf.contrib.framework.get_global_step(),
        learning_rate=0.001,
        optimizer="SGD")

  # Generate Predictions
  predictions = {
      "classes": tf.argmax(
          input=logits, axis=1),
      "probabilities": tf.nn.softmax(
          logits, name="softmax_tensor")
  }

  # Return a ModelFnOps object
  return model_fn_lib.ModelFnOps(
      mode=mode, predictions=predictions, loss=loss, train_op=train_op)
以下部分(标题对应上面的每个代码块)深入了解用于创建每个图层的tf.layers 代码,以及如何计算损失,配置训练操作和生成预测。
如果您已经有CNN和
TensorFlow Estimators的经验,并且对上述代码一目了然,您可以略过这部分,或者跳到“训练和评估CNN MNIST分类器”

输入层

图层模块中用于创建二维数据的卷积层与池化层的输入张量期待的形式为:[batch_size,image_widthimage_heightchannels] ,各参数定义如下

  • batch_size。在训练期间执行梯度下降时使用的样本子集大小。
  • image_width。样本图片的宽度。
  • image_height。样本图片的高度。
  • channels。样本图片中的颜色通道数。对于彩色图像,通道数为3(红,绿,蓝)。对于灰度图像,只有1个通道(黑色)。

在这里,我们的MNIST数据集由单色的28x28像素图像组成,因此我们的输入层所需的形状是。[batch_size, 28, 28, 1] 

要将我们输入的features map(features)转换为此形状,我们可以执行以下reshape操作:

代码块
languagepy
input_layer = tf.reshape(features, [-1, 28, 28, 1]) 
请注意,我们已经指出批量大小为-1,规定了此维度应根据features 输入值的数量进行动态计算,并保持所有其他维度的大小不变。这允许我们将其视
batch_size可调的超参数。例如,如果我们以5的batch向我们的模型中提供样本,features将包含3920个值(每张图片中每个像素的值),
并且
input_layer将具有的形状为 [5, 28, 28, 1]。同样地,如果我们以100个批次的方式提供示例,features 将包含78,400个值,
并且
input_layer将具有的形状[100, 28, 28, 1]

卷积层#1

在我们的第一个卷积层中,我们要对输入层应用32个5x5的滤波器,并具有一个ReLU激活函数。我们可以使用layers模块中的conv2d()方法 来创建这个层,如下所示:

代码块
languagepy
conv1 = tf.layers.conv2d(
    inputs=input_layer,
    filters=32,
    kernel_size=[5, 5],
    padding="same",
    activation=tf.nn.relu)
inputs参数指定了输入张量,该参数必须有这样一个shape:[batch_sizeimage_widthimage_heightchannels] 。在这里,我们将我们的
第一个卷积层连接到input_layer,它具有形状
[batch_size, 28, 28, 1] 
注意:当传入data_format=channels_first 这个参数时, conv2d()接受的形状将变为[channelsbatch_sizeimage_width,image_height]

filters参数指定滤波器数量,(本例为32),并且 kernel_size指定了滤波器的尺寸[widthheight](此处为 [5, 5]

提示:如果滤波器宽度和高度具有相同的值,则可以指定kernel_size为一个整型量,如:kernel_size=5

padding参数指定两个枚举值中的一个(不区分大小写):valid(默认值)或same。要指定输出张量应该与输入张量具有相同的宽度和高度值,我们设置padding=same,它指示TensorFlow向输出张量的边缘添加0个值,以保持宽度和高度28.(无填充,28x28的张量进行5x5卷积将产生一个24x24的张量,因为从28x28网格中有24x24个位置能提取一个5x5块。)

activation参数指定应用于卷积输出的激活函数。在这里,我们用 tf.nn.relu指定ReLU激活

conv2d()产生一个具有[batch_size, 28, 28, 32] 形状的输出张量,输入的宽度和高度维度相等 ,但现在有32个通道维持每个滤波器的输出。

池化层#1

接下来,我们将我们的第一个池化层连接到刚创建的卷积层。我们可以使用layers中的max_pooling2d()方法来构建一个使用2x2滤波器执行最大池的层,并且步长为2:

代码块
languagepy
pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)
再次说明,inputs指定 输入张量的形状为[batch_size,image_widthimage_heightchannels] 。这里,我们的输入张量是来自第一卷积层的
输出,其具有  [batch_size, 28, 28, 32]的形状。
  
注意:当传入data_format=channels_first 这个参数时, conv2d() max_pooling2d()接受的形状将变为[channelsbatch_sizeimage_width,image_height]

pool_size参数指定了最大池化中滤波器的尺寸[widthheight] (这里为[2,2] )。如果两个维度的值都相同,则可以指定一个整数,例如pool_size=2

strides参数指定步幅的大小。在这里,我们设置步长2,这表明由滤波器提取的子区域为宽和高维度上的2个像素(对于2x2滤波器,这意味着所提取的区域都不会重叠)。如果要为宽度和高度设置不同的步幅值,可以指定一个tuple或list(例如,stride=[3,6])。

我们的max_pooling2d()pool1)产生的输出张量具有以下形状 :[batch_size, 14, 14, 1] ,2x2滤波器将宽度和高度降低了50%。

卷积层#2和池化层#2

我们可以使用conv2d()max_pooling2d()之前一样将第二个卷积和汇集层连接到我们的CNN 。对于卷积层#2,我们使用ReLU激活配置64个5x5滤波器,对于池#2,我们使用与池化层1相同的规格(2 2×2最大池过滤器,步幅为2):像之前一样将第二个卷积层和池化层连接到我们的CNN 。对于卷积层#2,我们使用ReLU激活配置64个5x5滤波器,对于池化层#2,我们使用与池化层1相同的规格(步幅为2的2×2最大滤波器,):

代码块
languagepy
conv2 = tf.layers.conv2d(
    inputs=pool1,
    filters=64,
    kernel_size=[5, 5],
    padding="same",
    activation=tf.nn.relu)

pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2) 
注意,卷积层#2将第一个合并层(pool1注意,卷积层#2将第一个池化层(pool 1)的输出张量作为输入,并产生张量h_conv2作为输出。conv2 具有与(由于)相同的宽度和高度的形状,并且应用64个滤波器的64个通道。 具有与第一个池化层相同的宽度和高度的形状(由于padding="same"),
都为 [batch_size, 14, 14, 64] 
pool1 padding="same" 
汇集层#2 conv2作为输出,产生
,并且64个滤波器具有64个通道。 

池化层#2 将conv2的输出作为输入,产生pool2输出。pool2 具有形状(宽度和高度减少50%)。 具有形状[batch_size, 7, 7, 64] (与 conv2  相比,宽度和高度减少50%)。

密集层

接下来,我们要为我们的CNN添加一个密集层(有1接下来,我们要为我们的CNN添加一个密集层(具有1,024个神经元和ReLU激活),以对卷积024个神经元和ReLU激活函数),以对卷积/池层提取的特征进行分类。然而,在连接图层之前,我们将对我们的特征图(池化层提取的特征进行分类。然而,在连接图层之前,我们将对我们的特征图(pool2)进行平坦化,使其张量只有两个维度:)进行扁平化,使其张量只有两个维度:

代码块
languagepy
[batch_size,features] 
pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 64])

reshape()上述操作中,-1该表示batch_size 尺寸将被动态地计算根据在我们的输入数据样本的数目。每个例子都有7( 尺寸将根据我们的输入数据样本的数目动态地计算。每个样本都有7(pool2宽)* 7(pool2高)* 64(pool2通道)功能,所以我们希望通道)特征,所以我们希望features维度的值为7 * 7 * 64(总共3136)。输出张量pool2_flat具有形状 。具有[batch_size, 3136]  的形状 。

现在我们可以使用这种现在我们可以使用layers模块中的dense()方法layers连接我们的密集层,如下所示:方法连接我们的密集层,如下所示:

代码块
languagepy
dense = tf.layers.dense(inputs=pool2_flat, units=1024, activation=tf.nn.relu) 
inputs参数指定输入张:我们的扁平化特征图, 参数指定输入张量:我们的扁平化的特征图-pool2_flat。该units参数指定在致密层(1024)神经元的数目。该参数指定在密集层中神经元的数目(1024)。该activation参数可使用的激活函数参数传入激活函数; 再次,我们将 
我们再次将
tf.nn.relu用来添加ReLU激活。

为了帮助改进我们的模型的结果,我们也应用了缺陷正则化到我们的密集层,使用下面的dropout方法layers为了帮助改进我们的模型的结果,我们也应用了dropout正则化到我们的密集层,使用layersdropout方法:

代码块
languagepy
dropout = tf.layers.dropout(
    inputs=dense, rate=0.4, training=mode == learn.ModeKeys.TRAIN)
再次,inputs指定输入张量,它是我们的密层(指定输入张量,它是我们的密集层(dense)的输出张量。

rate参数指定辍学率参数指定丢弃率;  在这里,我们使用本例使用0.4,这意味着40%的元素将在训练期间随机退出。,这意味着40%的元素将在训练期间随机丢弃。

training参数使用一个布尔值,指定模型当前是否正在训练模式下运行参数传入一个布尔值,指定当前模型是否正在训练模式下运行;  如果将只执行差 dropout将只在 trainingTrueTrue的情况下执行。在这里,我们检查mode传递给我们的模型函数 cnn_model_fn是否是TRAIN模式。

我们的输出张量dropout具有形状。具有[batch_size, 1024]  的形状。

逻辑层

Logits层

神经网络中的最后一层是逻辑层,它将返回我们预测的原始值。我们创建一个具有10个神经元的密集层(每个目标类别为0神经网络中的最后一层是logits层,它将返回我们预测的原始值。我们创建一个具有具有线性激活(默认)的10个神经元的密集层(每个神经元对应目标类别0-9的一个),具有线性激活(默认):9中的一个):

代码块
languagepy
logits = tf.layers.dense(inputs=dropout, units=10)
CNN的最终输出张量logits有所变化 。 [batch_size, 10] 的shape 。 

计算损失

对于训练和评估,我们需要定义一个 损失函数 来衡量模型的预测与目标类的匹配程度。对于像MNIST这样的多类分类问题,通常将  来衡量模型的预测与目标类的匹配程度。对于像MNIST这样的多分类问题,通常将 交叉熵用作损失度量。以下代码在模型以任一模式运行用作损失度量。以下代码在模型以任一TRAINEVAL模式运行时计算交叉熵:

代码块
languagepy
loss = None
train_op = None

# Calculate loss for both TRAIN and EVAL modes
if mode != learn.ModeKeys.INFER:
  onehot_labels = tf.one_hot(indices=tf.cast(labels, tf.int32), depth=10)
  loss = tf.losses.softmax_cross_entropy(
      onehot_labels=onehot_labels, logits=logits)
我们来仔细看看上面发生了什么。

我们的labels张量包含了我们的例子的预测列表,例如张量包含了我们的样例的预测列表,例如[1, 9, ...]。为了计算交叉熵,首先我们需要转换labels 为相应的 单热编码 为相应的 one-hot编码

代码块
languagepy
[[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
 ...]
我们使用该tf.one_hot功能来执行此转换。tf.one_hot()有两个必需的参数:
  • indices。在一个热张力中将具有“on值”的位置,即1上述张量中的值的位置。。one-hot张量中有“值”的位置,即上述张量中的1值的位置。
  • depth。一个热张量的深度,即目标类的数量。在这里,深度是。one-hot张量的深度,即目标类的数量。在这里,深度是10

以下代码为我们的标签创建单张热张量onehot_labels

代码块
languagepy
onehot_labels = tf.one_hot(indices=tf.cast(labels, tf.int32), depth=10) 
因为labels包含从0-9的一系列值,indices只是我们的 labels张量,值被转换为整数。这张量,值被转换为整型。depth10因为我们有10个可能的目标类,每个数字一个。

接下来,我们接下来,我们从logits层计算onehot_labels从我们的逻辑层计算预测的交叉熵和softmax。的交叉熵和预测softmax。tf.losses.softmax_cross_entropy()采取 onehot_labelslogits作为参数,执行softmax激活 logits,计算交叉熵,并将我们,计算交叉熵,返回标量Tensor形式的loss作为标量返回Tensor

代码块
languagepy
loss = tf.losses.softmax_cross_entropy(
        onehot_labels=onehot_labels, logits=logits) 

配置训练操作

在上一节中,我们将CNN的损失定义为逻辑层和我们的标签的softmax交叉熵。让我们配置我们的模型,以便在训练过程中使用在上一节中,我们将CNN的损失定义为逻辑层和标签的softmax交叉熵。让我们配置我们的模型,以便在训练过程中使用 tf.contrib.layers.optimize_loss 方法来优化这个损失值 中的tf.contrib.layers。我们将使用0.optimize_loss 方法来优化这个损失值。我们将使用0.001的学习率和 随机梯度下降 作为优化算法:

代码块
languagepy
# Configure the Training Op (for TRAIN mode)
if mode == learn.ModeKeys.TRAIN:
    train_op = tf.contrib.layers.optimize_loss(
        loss=loss,
        global_step=tf.contrib.framework.get_global_step(),
        learning_rate=0.001,
        optimizer="SGD") 
注意:有关对Estimator模型函数配置训练操作的更深入的了解,请参阅tf.contrib.learn中创建估计”learn中创建Estimator”教程中的“ 定义模型的训练操作
产生预测

生成预测

我们的模型的逻辑层将我们的预测作为原始值在一 维张量中返回。让我们将这些原始值转换成我们的模型函数可以返回的两种不同格式:模型的逻辑层将我们的预测作为原始值在[batch_size, 10]  维张量中返回。让我们将这些原始值转换成我们的模型函数可以返回的两种不同格式:

  • 每个例子的每个样本的预测类:从0-9的数字。
  • 概率为每个实施例的每个可能的目标类:该示例是0的概率,是1,是2等
对于一个给定的例子,我们预测的类是具有最高原始值的对数张量的相应行中的元素。我们可以使用以下
  • 每个样本属于每个可能的目标类的可能性:该可能性可能是0,是1,是2等等

对于一个给定的例子,我们预测的类是具有最高原始值的logits张量中相应行中的元素。我们可以使用以下tf.argmax 函数找到该元素的索引:

代码块
languagepy
tf.argmax(input=logits, axis=1)

input参数指定提取最大值的张量 - 这里logits为logits。该axis参数指定的轴参数指定最大值input 张量沿找到最大的价值。在这里,我们想要找到索引为1的维度上的最大值,这对应于我们的预测(回想我们的对数张量具有形状)。 张量的轴。在这里,我们想要找到索引为1的维度上的最大值,这对应于我们的预测(回想我们的logits张量具有[batch_size, 10]  的形状)。

我们可以通过使用softmax激活从我们的对数层导出概率我们可以通过使用tf.nn.softmax应用softmax激活从我们的logits层导出概率:

代码块
languagepy
tf.nn.softmax(logits, name="softmax_tensor")
注意:我们使用name参数来明确地命名此操作 参数来明确地命名此操作为 softmax_tensor,所以我们稍后可以引用它。(我们将在“设置日志钩” "Set Up a Logging Hook"中为softmax值设置日志记录

我们在一个dict中编译我们的预测如下:我们在一个dict中编译我们的预测:

代码块
languagepy
predictions = {
    "classes": tf.argmax(
        input=logits, axis=1),
    "probabilities": tf.nn.softmax(
        logits, name="softmax_tensor")
}
最后,现在我们已经得到了我们predictions的predictionslosstrain_op我们能回报他们,与我们一起,我们能通过过mode的说法,在一个的参数,返回一个tf.contrib.learn.ModelFnOps对象:
代码块
languagepy
# Return a ModelFnOps object
return model_fn_lib.ModelFnOps(
    mode=mode, predictions=predictions, loss=loss, train_op=train_op) 

训练和评估CNN MNIST分类器

我们编码了我们的MNIST CNN模型函数; 现在我们准备好训练和评估了。

负载训练和测试数据

首先,我们加载我们的培训和测试数据。使用以下代码添加一个main()函数 

加载训练和测试数据

首先,我们加载我们的训练和测试数据。使用以下代码在cnn_mnist.py中添加一个main()函数

代码块
languagepy
def main(unused_argv):
  # Load training and eval data
  mnist = 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) 
我们存储和训练标记(从0-9的相应值对每个图像)作为训练特征数据(的手绘数字55000个图像的原始像素值)numpy的阵列 中train我们在train_datatrain_labels分别。同样,我们的evalulation特征数据(10,000张)和评价的标签存储eval_data 和eval_labels分别。

创建估算器

接下来,我们Estimator为我们的模型创建一个(TensorFlow类来执行高级模型训练,评估和推断)。将以下代码添加到
labels中存储训练数据(55000个手写数字图像的原始像素值)和训练标签(每个图片相对应的0-9中的值)作为numpy arrays 。同样,
我们在eval_dataeval_labels 中存储分析数据(10,000张)和分析标签
 

创建Estimator

接下来,为我们的模型创建一个Estimator(执行高级模型训练,评估和推断的TensorFlow类)。将以下代码添加到main()

代码块
languagepy
# Create the Estimator
mnist_classifier = learn.Estimator(
      model_fn=cnn_model_fn, model_dir="/tmp/mnist_convnet_model") 
 model_fn参数指定用于训练,评估和推断的模型函数; 我们通过cnn  我们把在 “构建CNN MNIST分类器” 中创建的cnn_model_fn我们在 “建立CNN MNIST分类器”中创建的。该 传给它
model_dir参数指定将保存模型数据(检查点)的目录(这里,我们指定临时目录参数指定将保存模型数据(checkpoints)的目录(这里,我们指定临时目录/tmp/mnist_convnet_model,但随意更改为您选择的另一个目录)。,但可随意更改为您选择的另一个目录)。
注意:有关TensorFlow EstimatorAPI 的深入了解,请参阅“在tf"Creating Estimators in tf.contrib.learn中创建估计器”learn."教程
设置日志钩

设置Logging Hook

由于CNN可能需要一段时间才能进行培训,我们设置一些日志记录,以便跟踪培训过程中的进度。我们可以使用TensorFlow 由于CNN可能需要一段时间才能进行培训,我们设置一些日志记录,以便跟踪培训过程中的进度。我们可以使用TensorFlow的 tf.train.SessionRunHook来创建一个 tf.train.LoggingTensorHook 将记录CNN的softmax层的概率值。将以下内容添加到 ,记录CNN的softmax层的概率值。将以下内容添加到main()

代码块
languagepy
# Set up logging for predictions
  tensors_to_log = {"probabilities": "softmax_tensor"}
  logging_hook = tf.train.LoggingTensorHook(
      tensors=tensors_to_log, every_n_iter=50) 
我们存储我们要登录的张量的字母tensors在tensors_to_log。每个键是我们选择的标签,将打印在日志输出中,相应的标签是TensorTensorFlow图中的a的名称。在这里,我们 probabilities可以找到中,我们 存储想要记录的值为张量字典。每个key是我们选择的标签,将打印在日志输出中,相应的标签是TensorFlow图中的Tensor的名称。在这里,
我们
可以在softmax_tensor,当我们生成概率时,我们早期提供了我们的softmax操作的名字中找到probabilities  当我们在 cnn_model_fn中生成概率前,我们提供了我们的softmax操作的名字
注意:如果您没有通过name
 参数明确指定操作的名称,TensorFlow将分配一个默认名称。几个简单的方法来发现应用于操作的名称是在TensorBoard上可视化图形 )或启用
 参数明确指定操作的名称,TensorFlow将分配一个默认名称。几个简单的方法来展示应用于操作上的名称是在TensorBoard上可视化图形 或启用TensorFlow Debugger(tfdbg)

接下来,我们创建LoggingTensorHook,传递tensors_to_log给 tensors参数。我们设定every_n_iter=50,其中规定了每50个训练步骤后记录概率。

训练模型

现在,我们已经准备好训练我们的模型,我们可以通过调用做现在,我们已经准备好训练我们的模型,我们可以通过调用mnist_classifier中的fit()的 mnist_classifier 。将以下内容添加到main()

代码块
languagepy
# Train the model
mnist_classifier.fit(
    x=train_data,
    y=train_labels,
    batch_size=100,
    steps=20000,
    monitors=[logging_hook])
fit通话中,我们的训练特征数据和标签传递到中,我们将训练数据和标签分别传递到xy分别。我们设置中。我们设置batch_size100(这意味着该模型将在每个步骤上的100个例子minibatches培养),和(这意味着该模型将在每步100个样本上训练),steps20000 (这意味着该模型将20 (这意味着该
模型将执行20,000步骤的总训练)。我们通过我们000步的总训练)。将
logging_hook传给monitors论证,以便在培训期间触发。参数,在训练过程中启动。

评估模型

培训完成后,我们要评估我们的模型,以确定其在MNIST测试集上的准确性。要设置我们的模型的精度指标,我们需要创建一个计量训练完成后,我们要评估我们的模型,以确定其在MNIST测试集上的准确性。要设置模型的精度指标,我们需要用tf.contrib.learn.MetricSpec 精度的指标。将以下内容添加到 创建一个计量精度的指标。将以下内容添加到main()

代码块
languagepy
# Configure the accuracy metric for evaluation
metrics = {
    "accuracy":
        learn.MetricSpec(
            metric_fn=tf.metrics.accuracy, prediction_key="classes"),
}
我们创建了我们我们用以下两个参数创建MetricSpec的以下两个参数:
  • metric_fn。计算和返回度量值的函数。在这里,我们可以使用模块中的预定义accuracy功能 。计算和返回度量值的函数。在这里,我们可以使用 tf.metrics模块中的预定义accuracy函数。
  • prediction_key。包含模型函数返回的预测的张量的关键。在这里,因为我们正在建立分类模型。包含模型函数返回预测的张量的key。因为我们正在建立分类模型,所以我们在“生成预测”中指定返回的key是"classes",所以我们在“生成预测”中指定了预测键

现在我们已经设置了我们的我们已经设置了metrics dict,我们可以评估模型。添加以下代码,执行评估并打印结果:dict,现在可以评估模型。添加以下代码,执行评估并打印结果:

代码块
languagepy
# Evaluate the model and print results
eval_results = mnist_classifier.evaluate(
    x=eval_data, y=eval_labels, metrics=metrics)
print(eval_results) 
我们通过我们的评估特征数据和标签来我们将评估数据和标签传给evaluate()中的x和 y分别论据。这个参数。metrics论点取决于我们刚刚定义的指标。参数取决于我们刚刚定义的metrics dict。

运行模型

我们编写了CNN模型函数我们编写了CNN模型函数,Estimator,以及训练/评估逻辑; 现在我们来看看结果。运行cnn_mnist.py

注意:训练CNN是相当计算密集型的。预计完成时间训练CNN需要很大的计算量的。预计完成时间cnn_mnist.py将根据您的处理器而有所不同,但CPU可能会长达1小时。要更快地训练,您可以减少steps传递的数量将根据您的处理器而有所不同,CPU可能会长达1小时。要更快地训练,您可以减少fit(),但请注意,这将影响精度。steps的数量,但请注意,这将影响精度。

作为模型列车,您将看到如下所示的日志输出:作为模型训练,您将看到如下所示的日志输出:

代码块
languagepy
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}
在这里,我们的测试数据集达到了97.3%的准确度。

其他资源

要了解有关TensorFlow中TensorFlow估计器和CNN的更多信息,请参阅以下资源:

在tf

要了解有关TensorFlow Estimators和CNN的更多信息,请参阅以下资源: