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

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

一、TensorFlow相关函数

复制代码
1
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的交叉熵损失值。

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

参数:

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

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

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
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、对张量的列求平均值

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
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、对张量的行求平均值

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
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代码实现

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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实现手写数字识别改进版内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部