非常教程

TensorFlow Guide参考手册

教程 | Tutorials

A Guide to TF Layers: Building a Convolutional Neural Network(TF层指南:构建卷积神经网络)

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

A Guide to TF Layers: Building a Convolutional Neural Network(TF层指南:构建卷积神经网络)

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

入门

让我们为我们的TensorFlow程序设置骨架。创建一个名为的文件cnn_mnist.py,并添加以下代码:

  • 点击复制代码
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

# Imports
import numpy as np
import tensorflow as tf

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

# Our application logic will be added here

if __name__ == "__main__":
  tf.app.run()

在您完成本教程时,您将添加代码来构建,训练和评估卷积神经网络。完整的最终代码可以在这里找到。

卷积神经网络简介

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

  • 卷积图层,将特定数量的卷积滤镜应用于图像。对于每个子区域,图层执行一组数学运算以在输出特征映射中生成单个值。卷积层通常将ReLU激活函数(https://en.wikipedia.org/wiki/Rectifier_(neural_networks%29))应用于输出以将非线性引入到模型中。
  • 池化层,其由卷积层提取的图像数据进行下采样以减少特征映射的维度以便减少处理时间。常用的池化算法是最大池化,其提取特征地图的子区域(例如,2×2像素的块),保持其最大值并丢弃所有其他值。
  • 密集(全连接)图层,对由卷积图层提取的特征执行分类并由共用图层进行下采样。在密集层中,层中的每个节点都连接到前一层中的每个节点。通常情况下,CNN由执行特征提取的一叠卷积模块组成。每个模块由一个卷积层和一个池化层组成。最后的卷积模块之后是一个或多个执行分类的密集层。CNN中的最终稠密层包含模型中每个目标类的单个节点(模型可能预测的所有可能类),softmax激活函数为每个节点生成0-1之间的值(所有这些softmax值的总和等于1)。我们可以将给定图像的softmax值解释为图像落入每个目标类别的可能性的相对测量值。注意:有关CNN更全面的介绍,请参阅斯坦福大学用于视觉识别的卷积神经网络课。构建CNN MNIST分类器使用以下CNN体系结构构建模型,以对MNIST数据集中的图像进行分类:
  • 卷积层#1:应用32个5x5滤波器(提取5x5像素子区域),具有ReLU激活功能
  • 池层#1:使用2x2过滤器和步幅2执行最大池化(指定池池不重叠)
  • 卷积层#2:应用64个5x5滤波器,具有ReLU激活功能
  • 池层#2:同样,使用2x2滤波器和步幅为2进行最大池化
  • 密集层#1:1,024个神经元,丢失正则化率为0.4(概率为0.4,任何给定元素在训练期间将被丢弃)
  • 密集层#2(Logits Layer):10个神经元,每个数字目标类别(0-9)一个。

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

  • conv2d()。构造一个二维卷积层。采用过滤器数量,过滤内核大小,填充和激活函数作为参数。
  • max_pooling2d()。使用max-pooling算法构造一个二维池化层。采用过滤器大小和步幅作为参数。
  • dense()。构建一个密集的图层。以神经元数量和激活函数作为参数。

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

打开cnn_mnist.py并添加以下cnn_model_fn函数,该函数符合TensorFlow的Estimator API预期的界面(稍后在创建估算器中的更多内容)。cnn_mnist.py取MNIST特征数据,标签和模型模式(TRAINEVALPREDICT)作为参数; 配置CNN; 并返回预测,损失和训练操作:

  • 点击复制代码
def cnn_model_fn(features, labels, mode):
  """Model function for CNN."""
  # Input Layer
  input_layer = tf.reshape(features["x"], [-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 == tf.estimator.ModeKeys.TRAIN)

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

  predictions = {
      # Generate predictions (for PREDICT and EVAL mode)
      "classes": tf.argmax(input=logits, axis=1),
      # Add `softmax_tensor` to the graph. It is used for PREDICT and by the
      # `logging_hook`.
      "probabilities": tf.nn.softmax(logits, name="softmax_tensor")
  }

  if mode == tf.estimator.ModeKeys.PREDICT:
    return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)

  # Calculate Loss (for both TRAIN and EVAL modes)
  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 == tf.estimator.ModeKeys.TRAIN:
    optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
    train_op = optimizer.minimize(
        loss=loss,
        global_step=tf.train.get_global_step())
    return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op)

  # Add evaluation metrics (for EVAL mode)
  eval_metric_ops = {
      "accuracy": tf.metrics.accuracy(
          labels=labels, predictions=predictions["classes"])}
  return tf.estimator.EstimatorSpec(
      mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)

以下部分(包含与上面每个代码块相对应的标题)更深入地介绍了tf.layers用于创建每个图层的代码,以及如何计算损失,配置训练操作并生成预测。如果您已经有了CNN和TensorFlow Estimator的经验,并且直观地找到上述代码,您可能需要浏览这些部分,或者直接跳到“训练和评估CNN MNIST分类器”。

输入层

layers用于为二维图像数据创建卷积层和合并层的模块中的方法期望输入张量具有的形状[batch_size, image_width, image_height, channels]定义如下:

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

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

为了将我们的输入特征映射(features)转换为这种形状,我们可以执行以下reshape操作:

  • 点击复制代码
input_layer = tf.reshape(features["x"], [-1, 28, 28, 1])
  1. 请注意,我们已经指出-1为批量大小,它指定此维度应根据输入值的数量进行动态计算features["x"],并保持所有其他维度的大小不变。这使我们可以把它batch_size当作一个我们可以调整的超参数。例如,如果我们将样例以5批次的形式提供给我们的模型,features["x"]将包含3,920个值(每个图像中的每个像素都有一个值),并且input_layer将具有一个形状[5, 28, 28, 1]。同样,如果我们以100个批次为例提供示例,features["x"]将包含78,400个值,并且input_layer将具有一个形状[100, 28, 28, 1]

卷积层#1

在我们的第一个卷积层中,我们希望将32个5x5滤波器应用到输入层,并具有ReLU激活功能。我们可以使用模块中的conv2d()方法layers来创建此图层,如下所示:

  • 点击复制代码
conv1 = tf.layers.conv2d(
    inputs=input_layer,
    filters=32,
    kernel_size=[5, 5],
    padding="same",
    activation=tf.nn.relu)

inputs参数指定了我们的输入张量,它必须具有这种形状[batch_size, image_width, image_height, channels]。在这里,我们将我们的第一个卷积层连接到input_layer,具有这种形状。[batch_size, 28, 28, 1]

注意: conv2d()将接受数传递参数时的形状[channels, batch_size, image_width, image_height] 。当传递参数data_format=channels_first时。

所述filters参数指定的过滤器,以应用(here,32)的数量,并且kernel_size作为过滤器的尺寸(here,[5, 5])。指定了维度[width, height]

提示:如果过滤器宽度和高度具有相同的值,则可以改为为kernel_size-eg 指定一个整数kernel_size=5

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

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

我们的输出张量conv2d()的形状为[batch_size, 28, 28, 32]:与输入相同的宽度和高度尺寸,但现在有32个通道保持每个滤波器的输出。

池化层#1

接下来,我们将第一个池化层连接到我们刚刚创建的卷积层。我们可以使用该max_pooling2d()方法在layers中构建一个使用2x2过滤器和2步进行最大池化的图层:

  • 点击复制代码
pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)

再次inputs指定输入张量,形状为[batch_size, image_width, image_height, channels]。这里,我们的输入张量是来自第一卷积层的输出,其形状为。conv1[batch_size, 28, 28, 32]

注意:与之相反conv2d()max_pooling2d()将会在接受参数时接受一个形状。[channels, batch_size, image_width,。 当传递image_height]data_format=channels_first时。

pool_size参数将最大池过滤器的大小指定为(在这里)[width, height][2, 2]。如果两个维度具有相同的值,则可以改为指定一个整数(例如,pool_size=2)。

strides参数指定步幅的大小。在这里,我们设置了2的步幅,这表明由滤波器提取的子区域在宽度和高度维度上都应该分开2个像素(对于2x2滤波器,这意味着没有提取的区域会重叠)。如果要为宽度和高度设置不同的跨度值,则可以改为指定元组或列表(例如,stride=[3, 6])。

我们由max_pooling2d()pool1)生成的输出张量具有以下形状[batch_size, 14, 14, 32]:2×2滤波器将宽度和高度分别减小50%。

卷积层#2和池化层#2

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

  • 点击复制代码
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)的输出张量作为输入,并生成张量conv2作为输出。conv2具有与pool1(由于padding="same")相同的宽度和高度的形状[batch_size, 14, 14, 64],并且应用了64个过滤器的64个通道。

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

密集层

接下来,我们要添加一个密集层(有1024个神经元和ReLU激活)到我们的CNN,以对由卷积/合并图层提取的特征执行分类。然而,在我们连接图层之前,我们会将我们的特征映射(pool2)变成形状[batch_size, features]以便我们的张量只有两个维度:

  • 点击复制代码
pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 64])

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

现在,我们可以使用下面的dense()方法layers来连接我们的密集层:

  • 点击复制代码
dense = tf.layers.dense(inputs=pool2_flat, units=1024, activation=tf.nn.relu)

inputs参数指定输入张量:我们的平坦特征图pool2_flat。该units参数指定密集层中的神经元数(1,024)。该activation参数可使用的激活函数; 再次,我们将使用tf.nn.relu添加ReLU激活。

为了帮助改进我们的模型的结果,我们还将丢弃正则化应用于我们的密集层,使用以下dropout方法在layers中:

  • 点击复制代码
dropout = tf.layers.dropout(
    inputs=dense, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN)

再次inputs指定输入张量,它是来自我们密集层(dense)的输出张量。

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

所述training参数使用boolean指定是否模型目前正在训练模式下运行; 如果是training过程,则仅执行丢弃True。在这里,我们检查mode传递给我们的模型函数cnn_model_fn是否是TRAIN模式。

我们的输出张量dropout已经具备形状[batch_size, 1024]

Logits图层

我们的神经网络中的最后一层是logits层,它会返回我们预测的原始值。我们创建了一个包含10个神经元(每个目标类为0-9)的密集层,使用线性激活(默认值):

  • 点击复制代码
logits = tf.layers.dense(inputs=dropout, units=10)

我们最终的CNN输出张量logits已经具有形状[batch_size, 10]

生成预测

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

  • 每个示例的预测类别:0-9的数字。
  • 每个样例的概率为每个可能的目标类:该示例是0的概率,是1,是2等

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

  • 点击复制代码
tf.argmax(input=logits, axis=1)

input参数指定了从中提取最大值的张量 - 在这里是logits。该axis参数指定了input找到最大值的张量的轴。在这里,我们希望找到指数为1的维度中的最大值,这对应于我们的预测(回想我们的logits张量已经形成)[batch_size, 10]

我们可以通过应用softmax激活来从我们的logits层中得出概率使用指令tf.nn.softmax

  • 点击复制代码
tf.nn.softmax(logits, name="softmax_tensor")

注意:我们使用name参数来显式命名这个操作softmax_tensor,所以我们可以在以后引用它。(我们将在“设置日志挂钩”中设置softmax值的日志记录。

我们用字典编译我们的预测,并返回一个EstimatorSpec对象:

  • 点击复制代码
predictions = {
    "classes": tf.argmax(input=logits, axis=1),
    "probabilities": tf.nn.softmax(logits, name="softmax_tensor")
}
if mode == tf.estimator.ModeKeys.PREDICT:
  return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)

计算损失

For both training and evaluation, we need to define a loss function that measures how closely the model's predictions match the target classes. For multiclass classification problems like MNIST, cross entropy is typically used as the loss metric. The following code calculates cross entropy when the model runs in either TRAIN or EVAL mode:

  • 点击复制代码
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 encoding

  • 点击复制代码
[[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()有两个必要的参数:

  • indicesone-hot张量中的位置将具有“开始值” - 即,1展示出的张量中的值的位置。
  • depth表示one-hot 张量的深度 - 即目标类别的数量。在这里,深度是10

以下代码为我们的标签创建一个one-hot张量onehot_labels

  • 点击复制代码
onehot_labels = tf.one_hot(indices=tf.cast(labels, tf.int32), depth=10)

由于labels包含0-9的一系列值,indices因此只是我们的labels张量,其值将转换为整数。depth10因为我们有10个可能的目标类别,每个数字一个。

接下来,我们计算onehot_labels来自logits层的预测的交叉熵和softmax。tf.losses.softmax_cross_entropy()需要onehot_labelslogits作为参数,执行SOFTMAX激活上logits,计算交叉熵,并返回我们loss作为一个标量Tensor

  • 点击复制代码
loss = tf.losses.softmax_cross_entropy(
    onehot_labels=onehot_labels, logits=logits)

Configure the Training Op

在前一节中,我们将CNN的损失定义为logits层和我们标签的softmax交叉熵。让我们配置我们的模型以在训练期间优化这个损失值。我们将使用0.001的学习率和随机梯度下降作为优化算法:

  • 点击复制代码
if mode == tf.estimator.ModeKeys.TRAIN:
  optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
  train_op = optimizer.minimize(
      loss=loss,
      global_step=tf.train.get_global_step())
  return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op)

注意:有关为Estimator模型函数配置培训操作的更深入观察,请参阅“在tf.estimator中创建估计”教程中的“为模型定义培训操作”。

添加评估指标

要在我们的模型中添加准确性度量,我们eval_metric_ops在EVAL模式中定义字典,如下所示:

  • 点击复制代码
eval_metric_ops = {
    "accuracy": tf.metrics.accuracy(
        labels=labels, predictions=predictions["classes"])}
return tf.estimator.EstimatorSpec(
    mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)

训练和评估CNN MNIST分类器

我们编写了我们的MNIST CNN模型函数; 现在我们准备好进行培训和评估了。

载入训练和测试数据

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

  • 点击复制代码
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)

我们分别存储和训练标记(从0-9的相应值对每个图像)作为训练特征数据(的手绘数字55000个图像的原始像素值)numpy的阵列中train_datatrain_labels。同样,我们分别将评估特征数据(10,000张图像)和评估标签存储在eval_dataeval_labels中。

创建估算器

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

  • 点击复制代码
# Create the Estimator
mnist_classifier = tf.estimator.Estimator(
    model_fn=cnn_model_fn, model_dir="/tmp/mnist_convnet_model")

model_fn参数指定的模型函数用于训练,评估,和预测; 我们把它传递给cnn_model_fn我们在“建立CNN MNIST分类器”中创建的。该model_dir参数指定了模型数据(检查站)将被保存的目录(这里,我们指定的临时目录/tmp/mnist_convnet_model,但随时更改为您选择的另一个目录)。

注意:有关TensorFlow EstimatorAPI 的深入演练,请参阅“在tf.estimator中创建估计器”教程。

设置Logging Hook

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

  • 点击复制代码
# 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_to_log。每个键都是我们选择的标签,将打印在日志输出中,相应的标签是TensorTensorFlow图形中的名称。在这里,我们可以在softmax_tensor中找到probabilities,我们早先给出我们的softmax操作的名称,当我们在cnn_model_fn中生成概率时。

注意:如果您未通过name参数明确指定操作的名称,TensorFlow将分配默认名称。发现应用于操作的名称的一对简单方法是在TensorBoard上显示图形)或启用TensorFlow调试器(tfdbg)。

接下来,我们创建LoggingTensorHook,将tensors_to_log传递给tensors参数。我们设定了这个标准every_n_iter=50,它规定在每50个步骤的训练结束后应该记录概率。

训练模型

现在,我们已经准备好训练我们的模型,我们可以通过在mnist_classifier上创建train_input_fn、调用train()。将以下内容添加到main()

  • 点击复制代码
# Train the model
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(作为字典)y。我们设置batch_size100(这意味着该模型将上的100个例子minibatches培养在每一个步骤)。num_epochs=None意味着模型将训练到达到指定的步数。我们也shuffle=True打算洗牌培训数据。在train调用中,我们设定了steps=20000(这意味着模型将训练总共20,000步)。我们通过我们logging_hookhooks参数,以便它在训练期间被触发。

评估模型

一旦训练完成,我们想评估我们的模型以确定其在MNIST测试集上的准确性。我们称该evaluate方法为评估我们在eval_metric_ops参数中指定的度量model_fn。将以下内容添加到main()

  • 点击复制代码
# Evaluate the model and print results
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)

为了创建eval_input_fn,我们进行设置num_epochs=1,以便该模型评估一个数据历元上的指标并返回结果。我们还设置了shuffle=False来迭代遍历数据。

运行模型

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

Note: Training CNNs is quite computationally intensive. Estimated completion time of cnn_mnist.py will vary depending on your processor, but will likely be upwards of 1 hour on CPU. To train more quickly, you can decrease the number of steps passed to train(), but note that this will affect accuracy.

模型训练时,您会看到如下所示的日志输出:

  • 点击复制代码
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.estimator中创建估计器。介绍TensorFlow Estimator API,介绍配置Estimator,编写模型函数,计算损失值和定义训练操作。
  • 专业深度MNIST:建立一个多层CNN。通过如何构建MNIST CNN分类模型,无需使用底层TensorFlow操作的层。
TensorFlow Guide

TensorFlow是谷歌基于DistBelief进行研发的第二代人工智能学习系统,其命名来源于本身的运行原理。Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算,TensorFlow为张量从流图的一端流动到另一端计算过程。TensorFlow是将复杂的数据结构传输至人工智能神经网中进行分析和处理过程的系统。

主页 https://www.tensorflow.org/
源码 https://github.com/tensorflow/tensorflow
版本 Guide
发布版本 1.4

TensorFlow Guide目录

1.指南 | Guide
2.教程 | Tutorials
3.配置 | Deploy
4.扩展 | Extend
5.开始 | Get Started
6.表现 | Performance