我是靠谱客的博主 义气自行车,最近开发中收集的这篇文章主要介绍TensorFlow实现手写数字识别改进版,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在TensorFlow实现手写数字的识别这篇博客中,介绍了通过TensorFlow构造一个神经网络来实现手写数字的识别,最后通过MNIST数据集,最后在测试集的识别率大约为91%左右。这篇博客主要对这个程序训练的模型进行优化和准确率的提升。在原来的基础上,增加了指数衰减学习率、L2正则化以及滑动平均模型的应用,关于这三种方式在之前的博客已经介绍过了。

一、TensorFlow相关函数

sparse_softmax_cross_entropy_with_logits(_sentinel=None,labels=None, logits=None, name=None)

功能:计算稀疏的softmax交叉熵通过logits和labels参数,计算离散分类任务的错误的可能性,被分类的类别都是互相独立的。

参数:

labels:tensor,类型是int32、int64,它代表每一个正确类别的下标。如,下面的例子中,对于每一个图片都会有一个10维的向量,如[1,0,0,0,0,0,0,0,0,0]这个就代表这张图片对应的数字是0,也就是这个向量为1的下标。

logits:神经网络的前向传播结果,不包括softmax层。

返回值:tensor,与labels的大小相同,与logits的数据类型相同,是一个softmax的交叉熵损失值。

reduce_mean(input_tensor,axis=None,keep_dims=False,name=None,reduction_indices=None)
功能:根据张量的维度来计算张量的平均值。

参数:

input_tensor:需要计算平均值的输入tensor(张量),是一个数字类型的。

axis:默认是None是对所有的元素求平均值,如果设置为0则是对列求平均值,如果为1则是对行求平均值。

1、对张量的所有值求平均值

    a = tf.Variable(tf.constant([1.,2.,3.,4.,5.,6.],shape=[2,3]),dtype=tf.float32)
    sess = tf.Session()
    init = tf.initialize_all_variables()
    sess.run(init)
    result = tf.reduce_mean(a)
    print(a.eval(session=sess))
    '''
    [[ 1.  2.  3.]
     [ 4.  5.  6.]]
    '''
    print(result.eval(session=sess))
    #3.5
2、对张量的列求平均值

    a = tf.Variable(tf.constant([1.,2.,3.,4.,5.,6.],shape=[2,3]),dtype=tf.float32)
    sess = tf.Session()
    init = tf.initialize_all_variables()
    sess.run(init)
    result = tf.reduce_mean(a,0)
    print(a.eval(session=sess))
    '''
    [[ 1.  2.  3.]
     [ 4.  5.  6.]]
    '''
    print(result.eval(session=sess))
    #[ 2.5  3.5  4.5]
3、对张量的行求平均值

    a = tf.Variable(tf.constant([1.,2.,3.,4.,5.,6.],shape=[2,3]),dtype=tf.float32)
    sess = tf.Session()
    init = tf.initialize_all_variables()
    sess.run(init)
    result = tf.reduce_mean(a,1)
    print(a.eval(session=sess))
    '''
    [[ 1.  2.  3.]
     [ 4.  5.  6.]]
    '''
    print(result.eval(session=sess))
    #[ 2.  5.]
二、神经网络结构介绍

1、在之前写的使用神经网络实现手写数字的识别,之前的神经网络是由两层网络组成,第一层是线性层,一共由784*10=7840个权重和10个偏置组成,由于结构比较简单连激活函数也没有,然后通过第二层的softmax层,最后的准确率只有91.8%,我们通过改进这次的准确率可以达到98.4%
2、这次改进后的结构是由三层结构组成的,第一层是线性层,由784*500个权重和500个偏置组成,然后再通过RELU激活层去线性化,第二层是由500*10个权重和10个偏置组成,然后通过RELU激活层,第三层也是softmax层,除了结构上有改进之外,我们还加了三种对模型的优化算法。

三、TensorFlow代码实现

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


#通过输入,神经网络的参数来进行输出
def inference(input_tensor,avger,weight1,biase1,weight2,biase2):
    #判断是否使用滑动平均模型
    #不使用滑动平均模型
    if avger == None:
        #计算第一层神经网络的前向传播,并使用RELU激活函数
        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,avger.average(weight1))+avger.average(biase1))
        #计算第二层神经网络的前向传播
        return tf.matmul(layer1,avger.average(weight2)) + avger.average(biase2)


if __name__ == "__main__":
    #定义第一层网络的输入节点数
    #输入为784是因为,每张手写数字的图片大小为28*28的矩阵,将它转成一维向量就是1*784
    input_node = 784
    #定义最后一层网络的输出节点数
    #输出为一个1*10的向量,正好可以表示0-9,10个数字
    output_node = 10

    #定义神经网络的结构
    #定义第一层隐藏层的节点数
    layer1_node = 500
    #定义每次训练图片的张数,可以有效防止内存溢出
    batch_size = 100
    #定义基础的学习率用于指数衰减的学习率中
    learning_rate_base = 0.8
    #设置学习率的衰减率
    learning_rate_decay = 0.99
    #设置L1正则化中,模型复杂度在损失函数中所占的比例
    regularization_rate = 0.0001
    #设置训练的轮数
    training_steps = 30000
    #设置滑动平均的衰减率
    moving_average_decay = 0.99
    #定义输入节点
    x = tf.placeholder(tf.float32,[None,input_node],name="x_input")
    #定义输出节点
    y_ = tf.placeholder(tf.float32,[None,output_node],name="y_output")
    #设置第一层神经网络的权重
    weight1 = tf.Variable(tf.truncated_normal([input_node,layer1_node],stddev=0.1))
    #设置第一层神经网络的偏置
    biase1 = tf.Variable(tf.constant(0.1,shape=[layer1_node]))
    #设置第二层神经网络的权重
    weight2 = tf.Variable(tf.truncated_normal([layer1_node,output_node],stddev=0.1))
    #设置第二层神经网络的偏置
    biase2 = tf.Variable(tf.constant(0.1,shape=[output_node]))
    #计算神经网络的前向传播结果
    #不适用参数的滑动平均值
    y = inference(x,None,weight1,biase1,weight2,biase2)
    #定义滑动平均的global_step
    global_step = tf.Variable(0,trainable=False)
    #初始化滑动平均
    averge = tf.train.ExponentialMovingAverage(moving_average_decay,global_step)
    #定义滑动平均所更新的列表,tf.trainable_variables()获取所有的列表
    variables_averages = averge.apply(tf.trainable_variables())
    #通过滑动平均,获取神经网络的前向传播参数
    averge_y = inference(x,averge,weight1,biase1,weight2,biase2)
    #使用交叉熵作为损失函数
    # cross_entropy = -tf.reduce_sum(y_*tf.log(y))
    cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=tf.argmax(y_,1),logits=y)
    #计算交叉熵的平均值
    cross_entropy_mean = tf.reduce_mean(cross_entropy)
    #计算L2正则化损失函数
    regularizer = tf.contrib.layers.l2_regularizer(regularization_rate)
    #计算模型参数的L2正则化
    regularization = regularizer(weight1) + regularizer(weight2)
    #计算中的损失
    loss = cross_entropy_mean + regularization
    # 下载minist的手写数字的数据集
    mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
    #设置指数衰减学习率
    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(0.01).minimize(loss)
    #每迭代一次需要更新神经网络中的参数
    train_op = tf.group(train_step,variables_averages)
    correct_prediction = tf.equal(tf.argmax(averge_y,1),tf.argmax(y_,1))
    #计算数据的准确率
    accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
    #初始化会话
    with tf.Session() as sess:
        #初始化参数
        tf.initialize_all_variables().run()
        # 验证数据
        validate_feed = {x: mnist.validation.images, y_: mnist.validation.labels}
        #迭代训练
        for i in range(training_steps):
            batch_x,batch_y = mnist.train.next_batch(batch_size)
            sess.run(train_op,feed_dict={x:batch_x,y_:batch_y})
            if i % 1000 == 0:
                validate_acc = sess.run(accuracy,feed_dict=validate_feed)
                print("After %d training step(s),validate accuracy using average"
                      "model is %g" % (i, validate_acc))

        # 测试数据
        test_feed = {x: mnist.test.images, y_: mnist.test.labels}
        #训练完成之后,测试测试集的准确率
        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))
        #0.9841
        #不使用滑动平均模型的准确率
        #0.9838
        #不使用L2正则化
        #0.9845
        #不使用指数衰减
        #0.9681
四、总结

在使用三种优化算法对模型进行优化的时候发现,对模型使用三种优化算法的时候准确率为98.41%(每次运行结果可能不一样,因为模型训练过程的随机因素),只使用正则化和指数衰减算法的时候准确率为98.45%和同时使用三种优化算法的结果差不多。但,如果不是指数衰减算法你会发现在训练过程中,对于验证集的准确率是慢慢的提升上去的,而不是从一开始的10%左右,直接变为了97%。这个结果也能更好的解释了,指数衰减对于模型的作用。





最后

以上就是义气自行车为你收集整理的TensorFlow实现手写数字识别改进版的全部内容,希望文章能够帮你解决TensorFlow实现手写数字识别改进版所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部