Распознавание цифр MNIST с помощью глубоких нейронных сетей

искусственный интеллект глубокое обучение регулярное выражение Нейронные сети
Распознавание цифр MNIST с помощью глубоких нейронных сетей

Заявление об авторских правах: эта статья является оригинальной статьей блоггера, опубликованной сЗаметки Ноогеля. Перепечатать вмой почтовый ящикПрименять.

В этом разделе применяются концепции глубокой нейронной сети, изученные в предыдущем разделе, для реализации распознавания рукописных слов MNIST с помощью tf.
Сначала импортируйте библиотеку tf и данные обучения:

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data", one_hot=True)

Определите глобальную начальную константу, где количество INPUT_NODE — это количество 28 * 28 пикселей в каждом изображении, OUTPUT_NODE — это количество классификаций 10, LAYER1_NODE — это количество скрытых узлов слоя, BATCH_SIZE — это количество обучающих данных каждый раз; LEARNING_RATE_BASE — базовая скорость обучения, LEARNING_RATE_DECAY — скорость затухания скорости обучения, REGULARIZATION_RATE — коэффициент функции потерь регуляризации, TRAINING_STEPS — количество раз обучения, а MOVING_AVERAGE_DECAY — скорость затухания скользящего среднего.

INPUT_NODE = 784
OUTPUT_NODE = 10
LAYER1_NODE = 500
BATCH_SIZE = 100
LEARNING_RATE_BASE = 0.8
LEARNING_RATE_DECAY = 0.99
REGULARIZATION_RATE = 0.0001
TRAINING_STEPS = 30000
MOVING_AVERAGE_DECAY = 0.99

Функция вывода определена для вычисления результата прямого распространения нейронной сети, а делинеаризация достигается с помощью функции RELU. Параметр avg_class используется для поддержки использования модели скользящего среднего во время тестирования.Когда мы используем модель скользящего среднего, значения весов и смещений берутся из avg_class.

def inference(input_tensor, avg_class, weights1, biases1, weights2, biases2):
    if avg_class is None:
        layer1 = tf.nn.relu(tf.matmul(input_tensor, weights1) + biases1)
        return tf.matmul(layer1, weights2) + biases2
    else:
        layer1 = tf.nn.relu(tf.matmul(input_tensor, avg_class.average(weights1)) + avg_class.average(biases1))
        return tf.matmul(layer1, avg_class.average(weights2)) + avg_class.average(biases2)

Определите входной слой, сгенерируйте параметры скрытого слоя и выходного слоя

x = tf.placeholder(tf.float32, [None, INPUT_NODE])
y_ = tf.placeholder(tf.float32, [None, OUTPUT_NODE])
weights1 = tf.Variable(tf.truncated_normal([INPUT_NODE, LAYER1_NODE], stddev=0.1))
biases1 = tf.Variable(tf.constant(0.1, shape=[LAYER1_NODE]))
weights2 = tf.Variable(tf.truncated_normal([LAYER1_NODE, OUTPUT_NODE], stddev=0.1))
biases2 = tf.Variable(tf.constant(0.1, shape=[OUTPUT_NODE]))

Рассчитайте эффект прямого распространения нейронной сети при текущих параметрах.

y = inference(x, None, weights1, biases1, weights2, biases2)

Здесь этот класс инициализируется скоростью затухания скользящего среднего и количеством раз обучения, которое используется для ускорения скорости обновления переменных на ранней стадии обучения; global_step — количество раз обучения в динамическом хранилище.

global_step = tf.Variable(0, trainable=False)
variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)

Здесь variable_averages_op использует скользящее среднее для всех верхних параметров нейронной сети, что не работает для параметров, для которых указано trainable=False. Вычисляет результат прямого распространения, обработанный с помощью модели скользящего среднего.

variables_averages_op = variable_averages.apply(tf.trainable_variables())
average_y = inference(x, variable_averages, weights1, biases1, weights2, biases2)

Подсчитайте потери. Перекрестная энтропия используется для описания функции потерь разницы между прогнозируемым значением и истинным значением, а затем мы превращаем результат в распределение вероятностей с помощью регрессии softmax. tf предоставляет функцию для объединения этих двух функций, первый параметр — результат прямого прохода, а второй параметр — ответ обучающих данных. Затем вычислите среднюю кросс-энтропию всех выборок.

cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))
cross_entropy_mean = tf.reduce_mean(cross_entropy)

Функция потерь регуляризации L2 используется здесь для вычисления потерь регуляризации модели, вычисления весов, а не вычисления смещения. Чтобы избежать переобучения, используется регуляризованная функция потерь.

regularizer = tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)
regularization = regularizer(weights1) + regularizer(weights2)

Результирующая общая потеря равна сумме кросс-энтропийной потери и потери регуляризации.

loss = cross_entropy_mean + regularization

Устанавливает экспоненциально убывающую скорость обучения.

learnging_rate = tf.train.exponential_decay(
    LEARNING_RATE_BASE, global_step, mnist.train.num_examples / BATCH_SIZE, LEARNING_RATE_DECAY)

Используйте алгоритм оптимизации для оптимизации общих потерь.

train_step = tf.train.GradientDescentOptimizer(learnging_rate).minimize(loss, global_step=global_step)

Параметры необходимо обновлять каждый раз при передаче данных.

with tf.control_dependencies([train_step, variables_averages_op]):
    train_op = tf.no_op()

Убедитесь, что результаты прямого распространения с использованием модели скользящего среднего верны.

correct_prediction = tf.equal(tf.argmax(average_y, 1), tf.argmax(y_, 1))

Вычислите среднюю точность.

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

Наконец, начнем наше обучение и проверим точность данных.

with tf.Session() as sess:
    # 初始化全部变量
    tf.global_variables_initializer().run()
    # 准备验证数据
    validate_feed = {x: mnist.validation.images,
                    y_: mnist.validation.labels}
    # 准备测试数据
    test_feed = {x: mnist.test.images, y_: mnist.test.labels}
    # 迭代
    for i in range(TRAINING_STEPS):
        if i % 1000 == 0:
            # 使用全部的验证数据去做了验证
            validate_acc = sess.run(accuracy, feed_dict=validate_feed)
            print "训练轮数:", i, ",准确率:", validate_acc * 100, "%"
        # 取出一部分训练数据
        xs, ys = mnist.train.next_batch(BATCH_SIZE)
        # 训练
        sess.run(train_op, feed_dict={x: xs, y_: ys})
    # 计算最终的准确率。
    test_acc = sess.run(accuracy, feed_dict=test_feed)
    print "训练轮数:", TRAINING_STEPS, ",准确率:", test_acc * 100, "%"

Чтобы начать процесс обучения, сначала инициализируйте все переменные.

tf.global_variables_initializer().run()

Данные MNIST делятся на обучающие данные, проверочные данные и тестовые данные. Сначала мы подготавливаем проверочные данные и тестовые данные, поскольку объем данных невелик, мы можем напрямую использовать все данные для обучения. Затем начнем наше итеративное обучение.Обучающих данных много.Мы каждый раз берем только часть данных для обучения.Это уменьшает объем вычислений и ускоряет обучение нейронной сети, не слишком сильно влияя на результаты.

Обучение tf осуществляется через функцию sess.run.Первый параметр — это окончательный расчет, который является выходом формулы.Второй параметр подачи — это вход плейсхолдера.

sess.run(train_op, feed_dict={x: xs, y_: ys})

Благодаря обучению снова и снова общие потери будут становиться все меньше и меньше, а предсказание модели будет становиться все более и более точным, достигая критической точки.

Полный код выглядит следующим образом:

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data", one_hot=True)
# MNIST数据集相关常数,其中输入节点数为每一张图片 28 * 28 的像素数,输出的节点数就是分类的个数 10; LAYER1_NODE 为隐藏层节点数,
# BATCH_SIZE 为每次训练数据的个数;LEARNING_RATE_BASE 为基础学习率,LEARNING_RATE_DECAY 为学习率的衰减率,
# REGULARIZATION_RATE 为正则化损失函数的系数,TRAINING_STEPS 为训练的次数,MOVING_AVERAGE_DECAY 为滑动平均衰减率
INPUT_NODE = 784
OUTPUT_NODE = 10
LAYER1_NODE = 500
BATCH_SIZE = 100
LEARNING_RATE_BASE = 0.8
LEARNING_RATE_DECAY = 0.99
REGULARIZATION_RATE = 0.0001
TRAINING_STEPS = 30000
MOVING_AVERAGE_DECAY = 0.99
# 这个函数用来计算神经网络的向前传播结果,并且通过 RELU 函数实现了去线性化。avg_class 参数是用来支持测试时使用滑动平均模型。
def inference(input_tensor, avg_class, weights1, biases1, weights2, biases2):
    if avg_class is None:
        layer1 = tf.nn.relu(tf.matmul(input_tensor, weights1) + biases1)
        return tf.matmul(layer1, weights2) + biases2
    else:
        layer1 = tf.nn.relu(tf.matmul(input_tensor, avg_class.average(weights1)) + avg_class.average(biases1))
        return tf.matmul(layer1, avg_class.average(weights2)) + avg_class.average(biases2)
# 输入层
x = tf.placeholder(tf.float32, [None, INPUT_NODE])
y_ = tf.placeholder(tf.float32, [None, OUTPUT_NODE])
# 生成隐藏层参数
weights1 = tf.Variable(tf.truncated_normal([INPUT_NODE, LAYER1_NODE], stddev=0.1))
biases1 = tf.Variable(tf.constant(0.1, shape=[LAYER1_NODE]))
# 生成输出层参数
weights2 = tf.Variable(tf.truncated_normal([LAYER1_NODE, OUTPUT_NODE], stddev=0.1))
biases2 = tf.Variable(tf.constant(0.1, shape=[OUTPUT_NODE]))
# 计算当前参数下神经网络向前传播的效果。
y = inference(x, None, weights1, biases1, weights2, biases2)
# 这个变量用来存储当前训练的次数。
global_step = tf.Variable(0, trainable=False)
# 这里通过滑动平均衰减率和训练次数初始化这个类,用来加快训练早期变量的更新速度。
variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
# 这里将所有的神经网络的上参数使用滑动平均,对于指定 trainable=False 的参数不作用。
variables_averages_op = variable_averages.apply(tf.trainable_variables())
# 计算使用了滑动平均模型处理的向前传播结果。
average_y = inference(x, variable_averages, weights1, biases1, weights2, biases2)
# 计算交叉熵,用来刻画预测值与真实值差距的损失函数,第一个参数是向前传播的结果,第二个是训练数据的答案。
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))
# 计算所有样例的交叉熵平均值。
cross_entropy_mean = tf.reduce_mean(cross_entropy)
# 计算 L2 正则化损失函数
regularizer = tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)
# 计算模型的正则化损失,计算权重的,不计算偏置。
regularization = regularizer(weights1) + regularizer(weights2)
# 总损失等于交叉熵损失和正则化损失之和。
loss = cross_entropy_mean + regularization
# 设置指数衰减的学习率。
learnging_rate = tf.train.exponential_decay(
    LEARNING_RATE_BASE, global_step, mnist.train.num_examples / BATCH_SIZE, LEARNING_RATE_DECAY)
# 使用优化算法优化总损失。
train_step = tf.train.GradientDescentOptimizer(learnging_rate).minimize(loss, global_step=global_step)
# 每过一次数据需要更新一下参数。
with tf.control_dependencies([train_step, variables_averages_op]):
    train_op = tf.no_op()
# 检验使用了滑动平均模型的向前传播结果是否正确。
correct_prediction = tf.equal(tf.argmax(average_y, 1), tf.argmax(y_, 1))
# 计算平均准确率。
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
if __name__ == "__main__":
    with tf.Session() as sess:
        # 初始化全部变量
        tf.global_variables_initializer().run()
        # 准备验证数据
        validate_feed = {x: mnist.validation.images,
                        y_: mnist.validation.labels}
        # 准备测试数据
        test_feed = {x: mnist.test.images, y_: mnist.test.labels}
        # 迭代
        for i in range(TRAINING_STEPS):
            if i % 1000 == 0:
                # 使用全部的验证数据去做了验证
                validate_acc = sess.run(accuracy, feed_dict=validate_feed)
                print "训练轮数:", i, ",准确率:", validate_acc * 100, "%"
            # 取出一部分训练数据
            xs, ys = mnist.train.next_batch(BATCH_SIZE)
            # 训练
            sess.run(train_op, feed_dict={x: xs, y_: ys})
        # 计算最终的准确率。
        test_acc = sess.run(accuracy, feed_dict=test_feed)
        print "训练轮数:", TRAINING_STEPS, ",准确率:", test_acc * 100, "%"
Extracting MNIST_data/train-images-idx3-ubyte.gz
Extracting MNIST_data/train-labels-idx1-ubyte.gz
Extracting MNIST_data/t10k-images-idx3-ubyte.gz
Extracting MNIST_data/t10k-labels-idx1-ubyte.gz
训练轮数: 0 ,准确率: 9.20000001788 %
训练轮数: 1000 ,准确率: 97.619998455 %
训练轮数: 2000 ,准确率: 98.0799973011 %
训练轮数: 3000 ,准确率: 98.2599973679 %
训练轮数: 4000 ,准确率: 98.1999993324 %
训练轮数: 5000 ,准确率: 98.1800019741 %
训练轮数: 6000 ,准确率: 98.2400000095 %
训练轮数: 7000 ,准确率: 98.2200026512 %
训练轮数: 8000 ,准确率: 98.1999993324 %
训练轮数: 9000 ,准确率: 98.2599973679 %
训练轮数: 10000 ,准确率: 98.2400000095 %
训练轮数: 11000 ,准确率: 98.2400000095 %
训练轮数: 12000 ,准确率: 98.1599986553 %
训练轮数: 13000 ,准确率: 98.2599973679 %
训练轮数: 14000 ,准确率: 98.299998045 %
训练轮数: 15000 ,准确率: 98.4200000763 %
训练轮数: 16000 ,准确率: 98.2800006866 %
训练轮数: 17000 ,准确率: 98.3799993992 %
训练轮数: 18000 ,准确率: 98.3600020409 %
训练轮数: 19000 ,准确率: 98.3200013638 %
训练轮数: 20000 ,准确率: 98.3399987221 %
训练轮数: 21000 ,准确率: 98.3799993992 %
训练轮数: 22000 ,准确率: 98.400002718 %
训练轮数: 23000 ,准确率: 98.400002718 %
训练轮数: 24000 ,准确率: 98.4200000763 %
训练轮数: 25000 ,准确率: 98.3200013638 %
训练轮数: 26000 ,准确率: 98.4200000763 %
训练轮数: 27000 ,准确率: 98.3799993992 %
训练轮数: 28000 ,准确率: 98.400002718 %
训练轮数: 29000 ,准确率: 98.3200013638 %
训练轮数: 30000 ,准确率: 98.3900010586 %

В следующем разделе обобщены тенденции в точности, средней перекрестной энтропии, общих потерях, скорости обучения и среднем абсолютном градиенте.


Если эта статья может принести вам небольшое улучшение, пожалуйста, дайте мне небольшую похвалу, чтобы побудить меня писать лучшие статьи!Noogel's WeChat Pay

WeChat награда

Noogel's Alipay

Вознаграждение Alipay