0%

MNIST 2.最简单的识别模型

  • 该模型是tensorflow官方文档首个模型,没有使用卷积网络

  • 关键是构建一个公式

公式为y=wx+b,带有二维像素值的数组(图片)作为输入x,标签(图片结果)作为输出y

用正向传播把数据(x,y)带入训练,再反向传播提升梯度来不断调整参数(w,b),使得公式的输出尽量准确。

  • 正确率约为92%

一、模型构建(计算公式实现)

为了得到一章图片(28*28=784个像素值)属于某个特定数字类的特征,我们对像素值进行加权求和。如果结果特征即加权值为负,就不属于该类,为正就属于该类。

1.特征值(需要学习参数W、b)

image

2.softmax转换特征值为概率(0-1之间):

image

其中xi是输入数据,evidencei是特征,y为通过特征softmax后得到的最终概率,

而参数W和b是我们要学习得到的数据,Wi是一个[784,10]的数据,bi是一个[10]的数据,就是模型(也是一个计算公式)的核心部分。

代码:y=tf.nn.softmax(tf.matmul(x,W)+b)

3.构建交叉熵

可以将W和b初始化为全0向量(或随意设置),通过迭代输入变量的计算结果反向传播(bp),从而使用梯度下降算法(gradient descent algorithm)完成最优化参数W和b,最优化的结果可以计算出最终的模型准球率

梯度下降需要设置学习率即学习的速率,还需要一个损失函数(最长见的是交叉熵cross-entropy),该函数得到一个loss值来刻画模型训练的结果(准确率)

image

y是预测的分布,y`是实际的分布,

代码:cross_entropy = -tf.reduce_sum(y_*tf.log(y))

4.训练(BP和反向传播,学习过程)

训练是一系列计算,包括1.计算梯度 2.每个参数的步长变化 3.更新参数

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

train_step是一个对象,计算时会使用梯度下降来更新参数,通过反复运行该对象完成。

1
2
3
4
5
6
7
for i in range(1000):
batch = mnist.train.next_batch(50)
train_step.run(feed_ditc={x:batch[0],y:batch[1]})
#x,y为具体数据,替代占位符(placeholder)
#等价于:
#train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
#sess.run(train_step,feed_ditc={x:batch[0],y:batch[1]})

二、实现代码:

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
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./MNIST_data/",one_hot=True)

print(mnist.train.images)
print(type(mnist.train.images))
print(mnist.train.images.shape)

print(mnist.train.labels)
print(type(mnist.train.labels))
print(mnist.train.labels.shape)

x = tf.placeholder('float',[None,784]) #该占位符第一维可以是任意长度,表示图像数据可以是28*28=784的n张图

W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
#w和b是需要学习的值,初始化为0

y = tf.nn.softmax(tf.matmul(x,W)+b)
#模型即计算公式,y是预测值

y_ = tf.placeholder('float',[None,10])
#y_是真实值

cross_entropy = -tf.reduce_sum(y_*tf.log(y))
#计算交叉熵

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
#优化器,计算梯度,并将梯度作用于变量.
#使用minimize()操作,该操作不仅可以优化更新训练的模型参数,也可以为全局步骤(global step)计数

init = tf.initialize_all_variables()

sess = tf.Session()
sess.run(init)

for i in range(1000):
batch_xs,batch_ys = mnist.train.next_batch(100)
sess.run(train_step,feed_dict={x:batch_xs,y_:batch_ys})

correct_predict = tf.equal(tf.argmax(y,1),tf.argmax(y_,1))
#y是一个含有10个元素的标签
#argmax(a,b)返回集合a中和数值b相同的索引值

accuracy = tf.reduce_mean(tf.cast(correct_predict,"float"))
#tf.cast将bool值转化为浮点数
#tf.reduce_mean可以取平均值,如[1,0,1,1]为0.75

sess.run(accuracy,feed_dict={x:mnist.test.images,y_:mnist.test.labels})
sess.close()
#准确率为0.9129



三、实现代码2

增加了测试过程的准确率,以1000次为一步

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
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./MNIST_data/",one_hot=True)

x = tf.placeholder('float',[None,784]) #该占位符第一维可以是任意长度,表示图像数据可以是28*28=784的n张图

W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
#w和b是需要学习的值,初始化为0

y = tf.nn.softmax(tf.matmul(x,W)+b)
#模型即计算公式,y是预测值
y_ = tf.placeholder('float',[None,10])
#y_是真实值

cross_entropy = -tf.reduce_sum(y_*tf.log(y))
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

correct_predict = tf.equal(tf.argmax(y,1),tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_predict,"float"))

init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)

for i in range(10000):
batch_xs,batch_ys = mnist.train.next_batch(100)
sess.run(train_step,feed_dict={x:batch_xs,y_:batch_ys})
if i%1000 == 0:
acc=sess.run(accuracy,feed_dict={x:mnist.validation.images,y_:mnist.validation.labels})
#训练1000次后(更新的参数W,b),对整体validation的测试
print('step %d is %g'%(i,acc))
#上两行代码等价于:
#print(accuracy.eval(feed_dict={x:mnist.validation.images,y_:mnist.validation.labels}))


accFinal=sess.run(accuracy,feed_dict={x:mnist.test.images,y_:mnist.test.labels})
print(accFinal)
sess.close()
#准确率为0.9129