Tensorflow: MNIST 专家级

训练过程:

MNIST初学者教程中所述,我们的深度学习过程由以下几个步骤定义:

  • 读取训练/测试数据集(MNIST)
  • 定义神经网络架构
  • 定义损失函数和优化方法
  • 根据数据批次训练神经网络
  • 评估测试数据的性能

在这里,我们从清单中总结了几乎每个步骤,并将严格地在神经网络体系结构设计部分上进行工作。

整个过程在training.py文件中定义,并将导入到特定文件中,包括用于不同神经网络体系结构的代码。

training.py代码如下:

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

def train_network(training_data, labels, output, keep_prob=tf.placeholder(tf.float32)):
    learning_rate = 1e-4
    steps_number = 1000
    batch_size = 100

    # Read data
    mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

    # Define the loss function
    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=labels, logits=output))

    # Training step
    train_step = tf.train.AdamOptimizer(learning_rate).minimize(loss)

    # Accuracy calculation
    correct_prediction = tf.equal(tf.argmax(output, 1), tf.argmax(labels, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

    # Run the training
    sess = tf.InteractiveSession()
    sess.run(tf.global_variables_initializer())

    for i in range(steps_number):
        # Get the next batch
        input_batch, labels_batch = mnist.train.next_batch(batch_size)

        # Print the accuracy progress on the batch every 100 steps
        if i%100 == 0:
            train_accuracy = accuracy.eval(feed_dict={training_data: input_batch, labels: labels_batch, keep_prob: 1.0})
            print("Step %d, training batch accuracy %g %%"%(i, train_accuracy*100))

        # Run the training step
        train_step.run(feed_dict={training_data: input_batch, labels: labels_batch, keep_prob: 0.5})

    print("The end of training!")

    # Evaluate on the test set
    test_accuracy = accuracy.eval(feed_dict={training_data: mnist.test.images, labels: mnist.test.labels, keep_prob: 1.0})
    print("Test accuracy: %g %%"%(test_accuracy*100))

其中dense.py包括简单的一个输出层网络,该网络与初学者教程中介绍的相同。在该场景的后面,我们将创建一个更复杂的模型。 dense.py代码如下:

import tensorflow as tf

image_size = 28
labels_size = 10

# Define placeholders
training_data = tf.placeholder(tf.float32, [None, image_size*image_size])
labels = tf.placeholder(tf.float32, [None, labels_size])

# Variables to be tuned
W = tf.Variable(tf.truncated_normal([image_size*image_size, labels_size], stddev=0.1))
b = tf.Variable(tf.constant(0.1, shape=[labels_size]))

# Build the network (only output layer)
output = tf.matmul(training_data, W) + b

# Train & test the network
import training
training.train_network(training_data, labels, output)

您可以使用以下命令来运行网络培训:

python dense.py

W_h = tf.Variable(tf.truncated_normal([image_size*image_size, hidden_size], stddev=0.1)) b_h = tf.Variable(tf.constant(0.1, shape=[hidden_size]))

TensorFlow提供tf.nn.relu将在执行矩阵乘法之后应用的功能。

hidden = tf.nn.relu(tf.matmul(training_data, W_h) + b_h)

最后,我们将隐藏层与输出层连接起来并返回所需的对象。注意,我们更改了weights变量的尺寸以适合隐藏层而不是输入层。

W = tf.Variable(tf.truncated_normal([hidden_size, labels_size], stddev=0.1)) b = tf.Variable(tf.constant(0.1, shape=[labels_size]))

output = tf.matmul(hidden, W) + b

您可以使用以下命令运行整个程序:

python hidden.py

import tensorflow as tf

image_size = 28
labels_size = 10
hidden_size = 1024

# Define placeholders
training_data = tf.placeholder(tf.float32, [None, image_size*image_size])
labels = tf.placeholder(tf.float32, [None, labels_size])

# Variables for the hidden layer
W_h = tf.Variable(tf.truncated_normal([image_size*image_size, hidden_size], stddev=0.1))
b_h = tf.Variable(tf.constant(0.1, shape=[hidden_size]))

# Hidden layer with reLU activation function
hidden = tf.nn.relu(tf.matmul(training_data, W_h) + b_h)

# Variables for the output layer
W = tf.Variable(tf.truncated_normal([hidden_size, labels_size], stddev=0.1))
b = tf.Variable(tf.constant(0.1, shape=[labels_size]))

# Connect hidden to the output layer
output = tf.matmul(hidden, W) + b

# Train & test the network
import training
training.train_network(training_data, labels, output)

卷积层

接下来要添加的两层是卷积网络的组成部分。它们的工作方式不同于密集的,并且在二维或更多维度输入中表现尤其出色。卷积层参数是卷积窗口和步幅的大小。填充设置为'SAME'表示所得图层的大小相同。在此步骤之后,我们应用max pooling。我们将构建两个卷积层,并将其连接到密集的隐藏层。生成的体系结构可以如下所示:

卷积网络

整个网络的代码都可以在中找到convolutional.py,我们现在将逐步引导您。在前面的示例中,占位符表示展平的数字的图像和相应的标签。尽管卷积层可以处理高维数据,但是我们需要重塑图像。

training_data = tf.placeholder(tf.float32, [None, image_size*image_size]) training_images = tf.reshape(training_data, [-1, image_size, image_size, 1]) labels = tf.placeholder(tf.float32, [None, labels_size])

下一步是为第一卷积层设置变量。然后,我们启动卷积和最大轮询阶段。正如你可以看到我们使用了各种类似tf.nn功能reluconv2dmax_pool。该层直接从输入数据读取重塑图像。

W_conv1 = tf.Variable(tf.truncated_normal([5, 5, 1, 32], stddev=0.1)) b_conv1 = tf.Variable(tf.constant(0.1, shape=[32]))

conv1 = tf.nn.relu(tf.nn.conv2d(training_images, W_conv1, strides=[1, 1, 1, 1], padding='SAME') + b_conv1) pool1 = tf.nn.max_pool(conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

第二层是类比的,下面进行了定义。请注意,作为输入,它采用上一步的最大轮询结果。

W_conv2 = tf.Variable(tf.truncated_normal([5, 5, 32, 64], stddev=0.1)) b_conv2 = tf.Variable(tf.constant(0.1, shape=[64]))

conv2 = tf.nn.relu(tf.nn.conv2d(pool1, W_conv2, strides=[1, 1, 1, 1], padding='SAME') + b_conv2) pool2 = tf.nn.max_pool(conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

剩下的最后一件事是将其连接到下一层,这是一个隐藏的密集层。密集层不适用于卷积的尺寸,因此我们需要使卷积阶段的结果平坦。

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

下一步将显示如何将其连接到隐藏的密集层。

Dropout

在最后一步中,我们创建了两个卷积层并将结果展平。现在是时候将其连接到密集的隐藏层了。这pool2_flat类似于本教程第二步中已经看到的内容,不同之处在于这次我们使用的是图像而不是图像作为输入。

W_h = tf.Variable(tf.truncated_normal([7 * 7 * 64, hidden_size], stddev=0.1)) b_h = tf.Variable(tf.constant(0.1, shape=[hidden_size]))

hidden = tf.nn.relu(tf.matmul(pool2_flat, W_h) + b_h)

现在,我们可以将隐藏的密集层连接到输出,但是我们还要做一件事-应用dropout。辍学是一种用于通过训练网络时不使用某些神经元来避免过度拟合的技术。

退出

仅在训练阶段丢弃神经元非常重要,而在评估模型时则不行。这就是为什么定义一个额外的占位符以保持丢失概率的原因。然后我们使用tf.nn.dropout函数。

keep_prob = tf.placeholder(tf.float32) hidden_drop = tf.nn.dropout(hidden, keep_prob)

最后一步是将其连接到输出层。

W = tf.Variable(tf.truncated_normal([hidden_size, labels_size], stddev=0.1)) b = tf.Variable(tf.constant(0.1, shape=[labels_size]))

output = tf.matmul(hidden_drop, W) + b

您可以使用以下命令运行代码:

python convolutional.py
import tensorflow as tf

image_size = 28
labels_size = 10
hidden_size = 1024

# Define placeholders
training_data = tf.placeholder(tf.float32, [None, image_size*image_size])
training_images = tf.reshape(training_data, [-1, image_size, image_size, 1])

labels = tf.placeholder(tf.float32, [None, labels_size])

# 1st convolutional layer variables
W_conv1 = tf.Variable(tf.truncated_normal([5, 5, 1, 32], stddev=0.1))
b_conv1 = tf.Variable(tf.constant(0.1, shape=[32]))

# 1st convolution & max pooling
conv1 = tf.nn.relu(tf.nn.conv2d(training_images, W_conv1, strides=[1, 1, 1, 1], padding='SAME') + b_conv1)
pool1 = tf.nn.max_pool(conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

# 2nd convolutional layer variables
W_conv2 = tf.Variable(tf.truncated_normal([5, 5, 32, 64], stddev=0.1))
b_conv2 = tf.Variable(tf.constant(0.1, shape=[64]))

# 2nd convolution & max pooling
conv2 = tf.nn.relu(tf.nn.conv2d(pool1, W_conv2, strides=[1, 1, 1, 1], padding='SAME') + b_conv2)
pool2 = tf.nn.max_pool(conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

# Flatten the 2nd convolution layer
pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 64])

#Variables for the hidden dense layer
W_h = tf.Variable(tf.truncated_normal([7 * 7 * 64, hidden_size], stddev=0.1))
b_h = tf.Variable(tf.constant(0.1, shape=[hidden_size]))

# Hidden layer with reLU activation function
hidden = tf.nn.relu(tf.matmul(pool2_flat, W_h) + b_h)

# Dropout
keep_prob = tf.placeholder(tf.float32)
hidden_drop = tf.nn.dropout(hidden, keep_prob)

# Variables to be tuned
W = tf.Variable(tf.truncated_normal([hidden_size, labels_size], stddev=0.1))
b = tf.Variable(tf.constant(0.1, shape=[labels_size]))

# Connect hidden to the output layer
output = tf.matmul(hidden_drop, W) + b

# Train & test the network
import training
training.train_network(training_data, labels, output, keep_prob)

请注意,网络的复杂性不仅影响训练的速度,而且还提高了准确性。尝试通过更改训练参数来调整结果。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章