📜  TensorFlow中CNN的培训

📅  最后修改于: 2021-01-11 10:41:37             🧑  作者: Mango

在TensorFlow中训练CNN

MNIST数据库(美国国家标准技术研究院数据库的修改版)是一个广泛的手写数字数据库,用于训练各种图像处理系统。它是通过“重新整合” MNIST原始数据集中的样本创建的。

如果我们熟悉Connects的构建基块,就可以使用TensorFlow构建一个。我们使用MNIST数据集进行图像分类。

准备数据与上一教程中的相同。我们可以运行代码,直接跳入CNN的体系结构。

在这里,我们正在Google Colab (机器学习的在线编辑器)中执行代码。

我们可以通过以下链接转到TensorFlow编辑器: https://colab.research.google.com

这些是用于训练CNN(卷积神经网络)的步骤。

脚步:

第1步:上传数据集

步骤2:输入层

步骤3:卷积层

步骤4:汇聚层

步骤5:卷积层和池化层

步骤6:密集层

步骤7: Logit层

第1步:上传数据集

scikit可提供MNIST数据集,以便在此URL(统一资源定位符)中进行学习。我们可以下载它并将其存储在我们的下载文件中。我们可以使用fetch_mldata(“ MNIST原始”)上传它。

创建测试/训练集

我们需要将数据集拆分为train_test_split

缩放功能

最后,我们借助MinMax Scaler缩放函数。

import numpy as np
import tensorflow as tf

from sklearn.datasets import fetch_mldata
#Change USERNAME by the username of the 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
A_train, A_test, B_train, B_test = train_test_split(mnist.data,mnist.target, test_size=0.2, random_state=45)
B_train  = B_train.astype(int)
B_test  = B_test.astype(int)
batch_size =len(X_train)
print(A_train.shape, B_train.shape,B_test.shape )
## rescale
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
# Train the Dataset
X_train_scaled = scaler.fit_transform(A_train.astype(np.float65))
#test the dataset
X_test_scaled = scaler.fit_transform(A_test.astype(np.float65))
feature_columns = [tf.feature_column.numeric_column('x',shape=A_train_scaled.shape[1:])]
X_train_scaled.shape[1:]

定义CNN(卷积神经网络)

与传统神经网络的全局模式相比,CNN使用任何图像像素上的滤镜来学习详细模式。要创建CNN,我们必须定义:

  • 卷积层:将过滤器的数量应用于特征图。卷积后,我们需要使用中继激活函数为网络添加非线性。
  • 汇聚层: 《公约》之后的下一步是对最大设施进行缩减采样。目的是减少特征图的移动性,以防止过度拟合并提高计算速度。最大池化是一种传统技术,该技术将要素图拆分为子字段,并且仅保留最大值。
  • 完全连接的层:过去层中的所有神经元都与其他下一层相关。 CNN已根据卷积层的特征对标签进行了分类,并通过任何合并层进行了缩减。

CNN架构

  • 卷积层:应用14个5×5滤镜(提取5×5像素子区域),
  • 池化层:这将使用2×2过滤器和跨度为2(指定池化的区域不重叠)来执行最大池化。
  • 卷积层:应用36个5×5滤镜,并具有ReLU激活函数
  • 池化层:同样,使用2×2滤镜执行最大池化,步幅为2。
  • 1,764个神经元,辍学正规化率为0.4(其中任何给定元素在训练中被丢弃的概率为0.4)
  • 密集层(登录层):有十个神经元,每个数字目标类别(0-9)一个。

创建CNN时要使用的重要模块:

  • Conv2d()。用过滤器的数量,过滤器内核的大小,填充和像参数一样的激活函数构造一个二维卷积层。
  • max_pooling2d()。使用最大池化算法构造一个二维池化层。
  • 密集()。用隐藏的层和单元构造一个密集层

我们可以定义一个函数来构建CNN。

让我们详细了解如何在将所有内容包装到函数之前构造每个构造块。

步骤2:输入层

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

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

图片具有宽度,高度和通道。 MNIST数据集是28×28大小的单色图片。我们在shape参数中将批处理大小设置为-1,以便采用特征[“ x”]的形状。好处是可以将批处理大小调整为超参数。如果批量大小为7,则张量将馈送5488个值( 28 * 28 * 7 )。

步骤3:卷积层

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

第一卷积层具有18个滤镜,内核大小为7×7,填充相同。相同的填充使输出张量和输入张量具有相同的宽度和高度。 TensorFlow将在行和列中添加零以确保大小相同。

我们使用Relu激活函数。输出大小将为[28、28和14]。

步骤4:汇聚层

卷积之后的下一步是合并计算。池计算将减少数据的扩展。我们可以使用大小为3×3,步幅为2的模块max_pooling2d。我们将上一层用作输入。输出大小可以为[batch_size,14、14和15]。

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

步骤5:池化层和第二卷积层

第二个CNN恰好具有32个过滤器,输出大小为[batch_size,14,14,32]。池化层的大小与前面相同,并且输出形状为[batch_size,14、14和18]。

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的模块重塑。

密集层将连接1764个神经元。我们添加了Relu激活函数,并且可以添加Relu激活函数。我们以0.3的比率添加一个辍学正则化项,这意味着30%的权重将为0。辍学仅在训练阶段发生。 cnn_model_fn()具有一个参数模式,用于声明模型是否需要训练或评估。

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:Logits层

最后,我们用模型的预测定义最后一层。输出形状等于批处理大小12,等于图层中图像的总数。

#Logit Layer
logits = tf.layers.dense(inputs=dropout, units=12)    

我们可以创建一个包含类以及每个类的可能性的字典。如果logit层,模块将使用tf.argmax()返回最大值。 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 EVAL and TRAIN modes)
loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)

最后一步是优化模型,即找到最佳的权重值。为此,我们使用梯度下降优化器,其学习速率为0.001。目的是减少损失。

optimizer= tf.train.GradientDescentOptimizer(learning_rate=0.0001)
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) 

CNN需要花费很多时间进行训练,因此,我们创建了一个日志挂钩,以每50次迭代存储软件层的值。

# 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,并将数据随机分成许多部分。请注意,我们将训练步骤设置为18000,这将花费大量时间进行训练。

#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=18000, 
    hooks=[logging_hook])

现在,模型已经过训练,我们可以对其进行评估并轻松打印结果。

# Evaluate the model and print the 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 2019-08-10-12:53:40
INFO:tensorflow:Graph is finalized.
INFO:tensorflow:Restoring parameters from train/mnist_convnet_model/model.ckpt-15652
INFO:tensorflow: Running local_init_op
INFO:tensorflow: Running local_init_op
INFO:tensorflow:Finished evaluation at 2019-07-05-12:52:56
INFO:tensorflow: Saving dict for global step 15652: accuracy = 0.9589586, global_step = 15852, loss = 0.13894269{'accuracy': 0.9689286, 'loss': 0.13894269, 'global_step': 15652}

借助体系结构,我们可以达到97%的准确性。我们可以更改体系结构,批处理大小和迭代次数以提高准确性。体系结构,批处理大小和迭代次数可提高准确性。

CNN神经网络的性能远远优于ANN或逻辑回归。在关于人工神经网络的教程中,我们的准确度为96% ,这是CNN偏低的原因。在速度计算和准确性方面,CNN凭借丰富的图像集的性能令人印象深刻。

要构建CNN,我们需要遵循以下六个步骤:

1)输入层:

此步骤将重置数据。大小等于像素数的平方根。例如,如果图片有156个像素,则数字为26×26。我们需要指定图像是否包含颜色。如果是这样,我们的RGB-大小为3到3,否则为1。

Input_layer= tf.reshape(tensor= features["x"], shape= [-1,30,30,1])

2)卷积层

我们需要创建一致的图层。我们应用各种过滤器来学习网络的重要功能。我们定义内核的大小和过滤器的体积。

conv1= tf.layers.conv2d(
inputs=input_layer,
filters=14,
kernel_size=[6, 6],
padding="same",
activation= tf.nn.relu)

3)池化层

第三步,我们添加一个池化层。该层减小了输入的大小。它通过取子矩阵的最大值来实现。

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

4)添加卷积层和池化层

在此步骤中,我们可以根据需要添加任意数量的池化层。它使用具有20多个硬层的Google体系结构。

5)致密层

步骤5压平前一个以形成完全连接的层。在此步骤中,我们可以使用其他激活函数并添加删除效果。

pool2_flat = tf.reshape(pool2, [-1, 8 * 8 * 36])
dense = tf.layers.dense(inputs=pool3_flat, units=8 * 8 * 36, activation=tf.nn.relu)
dropout = tf.layers.dropout(
Inputs=dense, rate=0.3, trainingmode == tf.estimator.ModeKeys.TRAIN)

6)Logit层

最后一步是预测。

logits = tf.layers.dense(inputs=dropout, units=12)