TensorFlow入门:《TensorFlow:实战Google深度学习框架》——基础版的MNIST数字识别问题

 
 
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/5/16 8:53
# @Author  : HJH
# @Site    : 
# @File    : classification1.py
# @Software: PyCharm

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

INPUT_SIZE=784
OUT_SIZE=10

# 设置神经网络参数
LAYER1_NODE=500
# 每个Batch的大小
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

#计算神经网络前向传播结果
def inference(input_tensor,avg_class,Weight1,biase1,Weight2,biase2):
    if avg_class == None:
        layer1=tf.nn.relu(tf.matmul(input_tensor,Weight1)+biase1)
        return tf.matmul(layer1,Weight2)+biase2
    else:
        layer1=tf.nn.relu(tf.matmul(input_tensor,avg_class.average(Weight1))+avg_class.average(biase1))
        return tf.matmul(layer1,avg_class.average(Weight2))+avg_class.average(biase2)

def train(mnist):
    X=tf.placeholder(tf.float32,[None,INPUT_SIZE],name='x_input')
    y=tf.placeholder(tf.float32,[None,OUT_SIZE],name='y_input')

    # 隐藏层参数
    Weight1=tf.Variable(tf.truncated_normal([INPUT_SIZE,LAYER1_NODE],stddev=0.1))
    biase1=tf.Variable(tf.constant(0.1,shape=[LAYER1_NODE]))

    # 输出层参数
    Weight2 = tf.Variable(tf.truncated_normal([LAYER1_NODE, OUT_SIZE], stddev=0.1))
    biase2 = tf.Variable(tf.constant(0.1, shape=[OUT_SIZE]))

    pre_y=inference(X,None,Weight1,biase1,Weight2,biase2)
    # 定义存储训练轮数的变量,这个变量不需要计算滑动平均值,所以这个变量为不可训练变量
    # 为什么要把它设为0,在训练过程中,每一次train_step,global_step都会增加1,所以后面这个值会越来越大
    global_step=tf.Variable(0,trainable=False)
    # 给定滑动平均衰减率和训练轮数的变量,初始化滑动平均类
    # 给定训练轮数的变量可以加快训练早期变量的更新速度。
    variable_average=tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step)
    # 在所有神经网络参数的变量上使用滑动平均,所有没有指定trainable=False的参数。
    variable_average_op=variable_average.apply(tf.trainable_variables())
    # 计算滑动平均之后的前向传播结果
    # 滑动平均不会改变变量本身的取值,而是会维护一个影子变量来记录其滑动平均值
    # 所以当需要使用这个滑动平均值时,需要明确调用average函数。
    average_y=inference(X,variable_average,Weight1,biase1,Weight2,biase2)

    # 使用交叉熵计算损失函数,注意这里用的是pre_y来计算交叉熵而不是average_y
    cross_entropy=tf.nn.sparse_softmax_cross_entropy_with_logits(logits=pre_y,labels=tf.argmax(y,1))
    # 计算在当前batch中所有样例的交叉熵平均值
    cross_entropy_mean=tf.reduce_mean(cross_entropy)

    # 正则化
    regularizer=tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)
    # 正则化损失
    regularization=regularizer(Weight1)+regularizer(Weight2)
    # 总体损失
    loss=cross_entropy_mean+regularization

    # 设置指数衰减的学习率
    learning_rate=tf.train.exponential_decay(
        LEARNING_RATE_BASE,                     # 基础的学习率,随着迭代的进行,更新变量时使用的学习率在这个基础上递减
        global_step,                            # 当前迭代的轮数
        mnist.train.num_examples / BATCH_SIZE,   # 过完所有的训练数据需要的迭代次数
        LEARNING_RATE_DECAY)                    # 学习率的衰减速度

    # 优化损失函数
    train_step=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=global_step)

    # 在训练神经网络模型时,每过一遍数据既需要通过反向传播来更新神经网络中的参数,
    # 又要更新每个参数的滑动平均值。为了一次完成多个操作,TensorFlow提供了
    # tf.control_dependencies和tf.group两种机制。下面两行程序和
    # train_op = tf.group(train_step, variables_average_op)是等价的。
    with tf.control_dependencies([train_step,variable_average_op]):
        # tf.no_op是一个没有实际意义的函数
        train_op=tf.no_op(name='train')

    # 检验使用了滑动平均模型的神经网络前向传播结果是否正确。tf.argmax(average_y, 1)
    # 计算每一个样例的预测结果。其中average_y是一个batch_size * 10的二维数组,每一行
    # 表示一个样例的前向传播结果。tf.argmax的第二个参数“1”表示选取最大值的操作仅在第一
    # 个维度中进行,也就是说,只在每一行选取最大值对应的下标。于是得到的结果是一个长度为
    # batch的一维数组,这个一维数组中的值就表示了每一个样例对应的数字识别结果。tf.equal
    # 判断两个张量的每一维是否相等,如果相等返回True,否则返回False。
    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:
        init=tf.global_variables_initializer()
        sess.run(init)
        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("After %d training step(s), validation accuracy "
                      "using average model is %g " % (i, validate_acc))
            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("After %d training step(s), test accuracy using average "
              "model is %g" % (TRAINING_STEPS, test_acc))

def main(argv=None):
    mnist=input_data.read_data_sets('MNIST_data', one_hot=True)
    train(mnist)

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

猜你喜欢

转载自blog.csdn.net/M_Z_G_Y/article/details/80335750