TensorFlow 中的 CNN 图像分类(附步骤和示例)

⚡ 智能摘要

卷积神经网络使用小型滤波器扫描图像,而不是对每个像素赋予相同的权重,这正是它们在计算机视觉领域占据主导地位的原因。本教程将解释每一层,并使用 TensorFlow 对 MNIST 数字数据集进行分类。

  • 🔘 四个组成部分: 每个卷积神经网络都包含卷积层、ReLU非线性激活函数、池化层和全连接分类层。
  • ☑️ 卷积机制: 一个 3×3 或 5×5 的滤波器在图像上滑动,逐元素相乘构建特征图。
  • 三个控制点: 深度设置过滤器数量,步长设置窗口之间的跳跃距离,零填充保持输出维度。
  • 🧪 Pooling效应: 使用 2×2 窗口和步长 2 进行最大池化,每个轴减半,减少权重并限制过拟合。
  • 🛠️ 七个搭建步骤: 上传数据集,然后定义输入层、卷积层、池化层、二次卷积层、密集层和logits层。
  • 📈 测量结果: 经评估的估计器在 MNIST 数据集上的准确率为 0.9689286,高于普通神经网络达到的 96%。

TensorFlow 中的 CNN 图像分类

什么是卷积神经网络?

卷积神经网络卷积神经网络(也称卷积神经网络或 CNN)是计算机视觉应用中一种广为人知的方法。它是一类用于分析视觉图像的深度神经网络。这种架构在识别图片或视频中的物体方面占据主导地位。它被广泛应用于图像或视频识别、自然语言处理和推荐系统等领域。

Archi卷积神经网络的结构

想想几年前的 Facebook,当你将照片上传到个人资料后,系统会要求你手动为照片上的脸部添加姓名。如今,Facebook 使用 convnet 自动在照片中标记你的朋友。

用于图像分类的卷积神经网络并不难理解。输入图像在卷积阶段进行处理,然后被赋予标签。

典型的卷积神经网络架构可以用下图概括。首先,将一幅图像输入到网络中,这幅图像被称为输入图像。然后,输入图像经过一系列步骤,这是网络的卷积部分。最后,神经网络可以预测图像中的数字。

从输入图像到卷积阶段,再到预测数字,这是一个端到端的卷积神经网络架构。
Archi卷积神经网络(CNN)的结构

图像由具有高度和宽度的像素数组组成。灰度图像只有一个通道,而彩色图像有三个通道(分别对应红色、绿色和蓝色)。这些通道彼此堆叠。在本教程中,您将使用一个只有一个通道的灰度图像。每个像素的值介于 0 到 255 之间,用于反映颜色的强度。例如,值为 0 的像素显示白色,而值接近 255 的像素则显示较暗的颜色。

让我们看一下存储在 MNIST 数据集下图展示了如何将左侧的图像表示为矩阵格式。请注意,原始矩阵已被标准化为介于 0 和 1 之间的值。对于较深的颜色,矩阵中的值约为 0.9,而白色像素的值为 0。

手写 MNIST 数字显示在 28x28 像素矩阵旁边,矩阵值标准化在 0 到 1 之间。

卷积运算

模型中最关键的组成部分是卷积层。这一部分旨在减小图像尺寸,从而加快权重计算速度并提高泛化能力。

在卷积部分,网络保留图像的基本特征并排除不相关的噪声。例如,该模型正在学习如何从背景为山脉的图片中识别大象。如果使用传统的神经网络,模型将为所有像素分配权重,包括那些不重要的、可能误导网络的山脉像素。

相反, Keras 卷积神经网络将使用一种数学技术来扩展trac它只提取最相关的像素。这种数学运算称为卷积。这项技术使网络能够在每一层学习越来越复杂的特征。卷积将矩阵分割成许多小块,从而学习每块中最关键的元素。

卷积神经网络(ConvNet 或 CNN)的组成部分

卷积神经网络由四个部分组成:

  1. 卷积
  2. 非线性(ReLU)
  3. Pooling 或子采样
  4. 分类(全连接层)

卷积

卷积的目的是……trac局部地学习图像中物体的特征。这意味着网络将学习图像中的特定模式,并能够在图像的任何位置识别这些模式。

卷积是一种逐元素相乘的运算。这个概念很容易理解。计算机扫描图像的一部分(通常为 3×3 大小),并将其与一个滤波器相乘。逐元素相乘的输出称为特征图。重复此步骤,直到扫描完整幅图像。需要注意的是,卷积运算后,图像尺寸会减小。

下图显示了图像的一个区域与滤波器相乘,从而生成特征图的单个单元格。

将 3×3 图像块逐元素乘以滤波器,即可得到特征图的一个值。

下面的动画显示了相同的卷积运算在整个图像上运行的过程。

动画滤镜在输入图像上滑动,逐个单元格地构建特征图。

有很多过滤器可供选择。下面我们列出了一些。可以看到,每个过滤器都有其特定的用途。请注意,下图中的“内核”是过滤器的同义词。

常用卷积核(例如边缘检测、锐化和模糊)及其输出图像表格

卷积背后的算法

卷积阶段会将滤波器应用于图像中的一小块像素区域。滤波器会沿着输入图像移动,其窗口大小通常为 3×3 或 5×5。这意味着网络会将这些窗口滑动遍历整个输入图像并计算卷积。下面的动画展示了卷积的工作原理。图像块的大小为 3×3,输出矩阵是图像矩阵与滤波器逐元素运算的结果。

逐步动画演示 3x3 滤波器如何将图像值相乘并求和得到输出矩阵。

您会注意到输出的宽度和高度可能与输入的宽度和高度不同。这是由于边框效果而发生的。

边界效应

图像包含一个 5×5 的特征图和一个 3×3 的滤波器。滤波器仅在中心区域设置了一个窗口,用于筛选 3×3 的网格。输出的特征图在每个轴上缩小两个图块,最终得到一个 3×3 的维度。

由于 3x3 滤波器无法到达边界,因此将 5x5 的特征图缩小为 3x3 的输出。

为了使输出维度与输入维度相同,需要添加填充。填充是指在矩阵的每一侧添加正确数量的行和列。这样可以使卷积运算能够居中拟合每个输入图块。在下图所示的示例中,输入矩阵和输出矩阵的维度相同,均为 5×5。

输入为 5x5 矩阵,周围环绕着一圈零填充,因此卷积运算返回 5x5 的输出矩阵。

当你定义网络时,卷积特征由三个参数控制:

宽度: 它定义了卷积过程中要应用的滤波器数量。在前面的例子中,深度为 1,这意味着只使用了一个滤波器。大多数情况下,会使用多个滤波器。下面的动画展示了使用三个滤波器时的操作。

三个独立的滤波器对同一输入进行卷积,生成三个堆叠的特征图。

步幅: 它定义了两个切片之间“像素跳跃”的次数。如果步长等于 1,窗口将以一个像素的距离移动。如果步长等于 2,窗口将以 2 个像素的距离跳跃。增加步长会缩小特征图。下面的两个图比较了步长为 1 和步长为 2 的情况。

步幅 1 示例

筛选窗口以步长 1 沿输入行一次移动一个像素。

大步2

跳过筛选窗口ping 位置之间间隔两个像素,步长设置为 2,从而产生更短的输出。

零填充: 填充是指在输入特征图的两侧分别添加相应数量的行和列。这样,输出图的维度就与输入图的维度相同。

非线性(ReLU)

卷积运算结束后,输出会经过激活函数处理,以引入非线性。卷积神经网络常用的激活函数是 ReLU。所有值为负的像素都会被替换为零。

Pooling OperaTION

这一步骤很容易理解。池化的目的是降低输入图像的维度。这些步骤是为了降低运算的计算复杂度。通过降低维度,网络需要计算的权重减少,从而防止过拟合。

在这个阶段,你需要定义池化窗口的大小和步长。一种标准的输入图像池化方法是使用特征图的最大值。请看下图。池化操作会筛选 4×4 特征图的四个子矩阵,并返回最大值。池化操作会取一个 2×2 数组的最大值,然后将该窗口移动两个像素。例如,第一个子矩阵是 [3,1,3,2],因此池化操作将返回最大值,即 3。

通过最大池化(窗口大小为 2x2,步长为 2),将 4x4 的特征图缩小到 2x2 的输出。

还有另一种池化操作,例如均值。

此操作会大幅减小特征图的大小。

全连接层

最后一步是建立一个传统的 人工神经网络 就像您在上一个教程中所做的那样。您将上一层的所有神经元连接到下一层。您使用 softmax 激活函数对输入图像上的数字进行分类。

回顾:

TensorFlow 卷积神经网络在进行预测之前会构建不同的层。神经网络具有:

  • 卷积层
  • ReLU激活函数
  • Poolin层
  • 密集连接层

卷积层对图像的子区域应用不同的滤波器。ReLU激活函数增加了非线性,池化层降低了特征图的维度。

所有这些层trac从图像中提取关键信息。最后,将特征图输入到带有softmax函数的全连接层进行预测。

使用 TensorFlow 训练 CNN

现在你已经熟悉了卷积神经网络的基本组成部分,可以开始构建一个卷积神经网络了。 TensorFlow.我们将使用 MNIST 数据集进行 CNN 图像分类。

数据准备与上一个教程相同。您可以运行代码并直接跳转到 CNN 的架构。

您将按照以下步骤使用 CNN 进行图像分类:

  1. 步骤 1:上传数据集
  2. 第 2 步:输入层
  3. 步骤3:卷积层
  4. 第三步: Poolin层
  5. 步骤 5:第二卷积层和 Poolin层
  6. 步骤 6:密集层
  7. 步骤 7:Logit 层

版本说明: 以下列表针对 TensorFlow 1.x 版本。在 TensorFlow 2 中,`tf.layers` 命名空间和 `tf.estimator.inputs.numpy_input_fn` 已不再存在;其等效项为 `tf.keras.layers.Conv2D` 和 `Max`。Pooling2D、Dense 和 Dropout 被组合成一个 tf.keras.Model,并使用 model.fit() 进行训练。请阅读各层的具体步骤,然后将其映射到 Keras API。

步骤 1:上传数据集

MNIST 数据集可通过 scikit-learn 获取。请下载并将其保存在 Downloads 文件夹中。您可以使用 fetch_mldata('MNIST original') 上传它。

版本说明: mldata.org 已关闭,scikit-learn 0.22 中已移除 fetch_mldata() 函数。在任何当前安装的 scikit-learn 中,请使用以下命令加载相同的数字: fetch_openml 改为使用 fetch_openml('mnist_784', version=1)。管道的其余部分保持不变。

创建训练/测试集

你需要使用 train_test_split 函数分割数据集。

扩展功能

最后,您可以使用 MinMaxScaler 对特征进行缩放,如下面的使用 TensorFlow CNN 的图像分类示例所示。

import numpy as np
import tensorflow as tf
from sklearn.datasets import fetch_mldata

#Change USERNAME by the username of your machine
## Windows USER
mnist = fetch_mldata('C:\\Users\\USERNAME\\Downloads\\MNIST original')
## Mac User
mnist = fetch_mldata('/Users/USERNAME/Downloads/MNIST original')

print(mnist.data.shape)
print(mnist.target.shape)
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(mnist.data, mnist.target, test_size=0.2, random_state=42)
y_train  = y_train.astype(int)
y_test  = y_test.astype(int)
batch_size =len(X_train)

print(X_train.shape, y_train.shape,y_test.shape )
## resclae
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
# Train
X_train_scaled = scaler.fit_transform(X_train.astype(np.float64))
# test
X_test_scaled = scaler.fit_transform(X_test.astype(np.float64))
feature_columns = [tf.feature_column.numeric_column('x', shape=X_train_scaled.shape[1:])]
X_train_scaled.shape[1:]

定义 CNN

与传统神经网络学习全局模式不同,卷积神经网络 (CNN) 使用滤波器处理图像的原始像素,从而学习图像的细节模式。要构建 CNN,您需要定义:

  1. 卷积层:对特征图应用 n 个滤波器。卷积之后,需要使用 ReLU 激活函数为网络添加非线性。
  2. Pooling层:卷积之后的下一步是对特征图进行下采样。其目的是降低特征图的维度,以防止过拟合并提高计算速度。最大池化是一种常用的技术,它将特征图分割成子区域(通常为2×2大小),并仅保留最大值。
  3. 全连接层:前几层的所有神经元都连接到下一层。CNN 将根据卷积层的特征对标签进行分类,并使用池化层进行缩减。

CNN 架构

  • 卷积层:应用 14 个 5×5 滤波器(例如)trac划分 5×5 像素子区域),并使用 ReLU 激活函数
  • Pooling 层:使用 2×2 过滤器和步幅为 2 执行最大池化(指定池化区域不重叠)
  • 卷积层:应用 36 个 5×5 滤波器,具有 ReLU 激活函数
  • Pooling 第 2 层:同样使用 2×2 过滤器和步长为 2 执行最大池化
  • 1,764 个神经元,dropout 正则化率为 0.4(训练过程中任何给定元素被丢弃的概率为 0.4)
  • 密集层(Logits 层):10 个神经元,每个数字目标类别(0-9)一个。

创建 CNN 有三个重要模块:

  • conv2d().以过滤器数量、过滤器核大小、填充和激活函数作为参数构造一个二维卷积层。
  • max_pooling2d(). 使用最大池化算法构造二维池化层。
  • 密集()。用隐藏层和单元构造一个密集层

您将定义一个用于构建 CNN 的函数。让我们在封装之前详细了解一下每个构建模块的构造方法。ping 所有内容都集成在这个函数中。

第 2 步:输入层

def cnn_model_fn(features, labels, mode):
    input_layer = tf.reshape(tensor = features["x"],shape =[-1, 28, 28, 1])

您需要定义一个具有数据形状的张量。为此,您可以使用模块 tf.reshape。在此模块中,您需要声明要重塑的张量和张量的形状。第一个参数是数据的特征,它在函数的参数中定义。

一张图片具有高度、宽度和通道数。MNIST 数据集是一张 28×28 像素的单色图片。我们在形状参数中将批大小设置为 -1,使其形状与 features[“x”] 相同。这样做的好处是可以将批大小作为超参数进行调整。如果批大小设置为 7,则张量将包含 5,488 个值 (28*28*7)。

步骤3:卷积层

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

第一个卷积层包含 14 个卷积核,卷积核大小为 5×5,并采用相同的填充方式。相同的填充方式意味着输出张量和输入张量的高度和宽度必须相同。TensorFlow 会在行和列中填充零以确保大小一致。

您使用 ReLU 激活函数。输出大小为 [28, 28, 14]。

第三步: Poolin层

卷积之后的下一步是池化计算。池化计算会降低数据的维度。您可以使用大小为 2×2、步长为 2 的 max_pooling2d 模块。输入层为前一层。输出大小为 [batch_size, 14, 14, 14]。

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

步骤 5:第二卷积层和 Poolin层

第二个卷积层应用了 36 个滤波器,输出大小为 [batch_size, 14, 14, 36]。池化层使用与之前相同的 2×2 窗口和 2 步长,因此它将每个空间轴减半,输出形状变为 [batch_size, 7, 7, 36]。

conv2 = tf.layers.conv2d(
      inputs=pool1,
      filters=36,
      kernel_size=[5, 5],
      padding="same",
      activation=tf.nn.relu)
pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)

步骤 6:密集层

接下来,您需要定义全连接层。在与密集层连接之前,必须先将特征图展平。您可以使用大小为 7*7*36 的 reshape 模块。

全连接层将连接 1,764 个神经元。您添加了 ReLU 激活函数。此外,您还添加了一个 dropout 正则化项,dropout 率为 0.3,这意味着 30% 的激活值将被设置为 0。请注意,dropout 仅在训练阶段执行。函数 `cnn_model_fn` 有一个参数 `mode`,用于声明模型是需要训练还是评估,如下面的 CNN 图像分类 TensorFlow 示例所示。

pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 36])

dense = tf.layers.dense(inputs=pool2_flat, units=7 * 7 * 36, activation=tf.nn.relu)
dropout = tf.layers.dropout(
      inputs=dense, rate=0.3, training=mode == tf.estimator.ModeKeys.TRAIN)

步骤 7:Logit 层

最后,在 TensorFlow 图像分类示例中,您可以定义最后一层,用于输出模型的预测结果。输出形状等于批次大小加上 10,即目标类别的总数。

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

您可以创建一个字典,其中包含类别及其概率。`tf.argmax()` 函数返回 logits 层中最大值的索引。`softmax` 函数返回每个类别的概率。

predictions = {				
	# Generate 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)

下一步是计算模型的损失。在上一篇教程中,您了解到多分类模型的损失函数是交叉熵。可以使用以下代码轻松计算损失:

# Calculate Loss (for both TRAIN and EVAL modes)
loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)

TensorFlow CNN 示例的最后一步是优化模型,即找到权重的最佳值。为此,可以使用学习率为 0.001 的梯度下降优化器。目标是最小化损失。

optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
train_op = optimizer.minimize(
        loss=loss,
        global_step=tf.train.get_global_step())

CNN 已经完成。但是,您希望在评估模式下显示性能指标。多分类模型的性能指标是准确率。TensorFlow 提供了一个准确率模块,该模块接受两个参数:标签和预测值。

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,并准备将所有内容包装到一个函数中,以便使用它来训练和评估模型。

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
  conv1 = tf.layers.conv2d(
      inputs=input_layer,
      filters=32,
      kernel_size=[5, 5],
      padding="same",
      activation=tf.nn.relu)

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

  # Convolutional Layer #2 and Pooling Layer
  conv2 = tf.layers.conv2d(
      inputs=pool1,
      filters=36,
      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 * 36])
  dense = tf.layers.dense(inputs=pool2_flat, units=7 * 7 * 36, 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),
      "probabilities": tf.nn.softmax(logits, name="softmax_tensor")
  }

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

  # Calculate Loss
  loss = tf.losses.sparse_softmax_cross_entropy(labels=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 Evaluation 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)

关于组装函数的说明: 上面的封装版本将第一个卷积层设置为 32 个滤波器,dropout 设置为 0.4,而逐步代码片段使用 14 个滤波器和 0.3。两者都可以运行,但选择一对值并保持一致,以便打印出的形状与层表匹配。

以下步骤与之前的教程相同。

首先,使用 CNN 模型定义一个用于图像分类的估计器。

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

CNN 训练需要很长时间,因此,您可以创建一个日志钩子,每 50 次迭代存储 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)

您已准备好估计模型。请将批次大小设置为 100 并对数据进行打乱。请注意,我们设置了 16,000 次训练,这可能需要很长时间才能完成训练。请耐心等待。

# Train the model
train_input_fn = tf.estimator.inputs.numpy_input_fn(
    x={"x": X_train_scaled},
    y=y_train,
    batch_size=100,
    num_epochs=None,
    shuffle=True)
mnist_classifier.train(
    input_fn=train_input_fn,
    steps=16000,
    hooks=[logging_hook])

模型训练完成后,您可以对其进行评估并打印结果。

# Evaluate the model and print results
eval_input_fn = tf.estimator.inputs.numpy_input_fn(
    x={"x": X_test_scaled},
    y=y_test,
    num_epochs=1,
    shuffle=False)
eval_results = mnist_classifier.evaluate(input_fn=eval_input_fn)
print(eval_results)

评估过程会打印出恢复的检查点、停止的步骤以及最终的指标字典。

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-08-05-12:52:41
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train/mnist_convnet_model/model.ckpt-15652
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Finished evaluation at 2018-08-05-12:52:56
INFO:tensorflow:Saving dict for global step 15652: accuracy = 0.9589286, global_step = 15652, loss = 0.13894269
{'accuracy': 0.9689286, 'loss': 0.13894269, 'global_step': 15652}

在当前架构下,评估字典报告的准确率为 0.9689286,约为 97%。您可以更改架构、批次大小和迭代次数来提高准确率。CNN 的性能远优于…… 人工神经网络 或者逻辑回归:在关于人工神经网络的教程中,你的准确率达到了 96%,低于 CNN。CNN 在处理更大的图像集时,无论在计算速度还是准确率方面,都表现出色。

常见问题

有效填充不会增加任何内容,因此输出会缩小,并且边界像素会进入更少的神经元。相同填充则会在输入周围填充零,从而使输出保持与输入相同的高度和宽度,这正是本教程中 conv2d 函数请求的内容。

未更改。tf.layers 和 tf.estimator.inputs.numpy_input_fn 已被移除。使用 tf.keras.layers.Conv2D 和 Max 重建相同的堆栈。Pooling2D、Dense 和 Dropout 都包含在内 TensorFlow 然后使用 model.fit() 而不是 Estimator 来训练 Keras 模型。

自动化搜索库并行扫描过滤器数量、内核大小、dropout率和学习率,然后根据验证准确率对运行结果进行排名。它们用精确的比较取代了猜测,但计算预算和关键指标仍然由人来决定。

是的。 GitHub 副驾驶 根据简短的注释,草拟了重复的卷积和池化堆栈以及输入管道。请自行检查输出形状,因为建议经常将已移除的 TensorFlow 1 API 与当前的 Keras API 混用。

随机翻转、旋转、平移和缩放操作会为每张训练图像创建新的变体,从而使网络能够接触到更广泛的样本,并避免记忆单个图像。这种方法与 dropout 结合使用效果更佳,通常可以缩小训练准确率和验证准确率之间的差距。

此处运行使用了 16,000 步,批大小为 100。大部分准确率在很早的时候就达到了,因此要观察评估指标,一旦指标趋于稳定就停止,而不是在慢速机器上等待完整的计数完成。

mldata.org 已关闭,scikit-learn 0.22 版本中也移除了该辅助函数。请改用 fetch_openml('mnist_784', version=1)。它返回的仍然是 70,000 个扁平化的 784 像素数字,因此本教程中的缩放和分割步骤仍然有效。

它们分别代表批次大小、高度、宽度和通道数。因此,14×14 是在 28×28 的数字经过一次池化步骤后的空间大小,而 36 是该卷积层中的滤波器数量,每个滤波器对应一个特征图。

总结一下这篇文章: