Tensorflow Mnist手写数字识别学习(一)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_44547562/article/details/102675883

准备工作

%matplotlib inline
import matplotlib.pyplot as plt
import tensorflow as tf
import tensorflow.examples.tutorials.mnist.input_data as input_data

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

由于使用jupyter notebook,若不加入%matplotlib inline,图片将不会在notebook中显示。
其中read_data_sets("MNIST_data/", one_hot=True)的第一个参数是数据集保存的位置,第二个参数决定数据是否采用独热编码。因为是分类问题,一般使用独热编码,设置其参数为 T r u e True 。如果此时该目录下没有数据文件,那么将花费几分钟下载后再读取;如果有数据文件,则会自动读取。

定义模型

定义占位符

x = tf.placeholder(tf.float32, [None, 784], name="X")
y = tf.placeholder(tf.float32, [None, 10], name="Y")

定义占位的 x , y x,y ,最后在 S e s s i o n Session 中将数据通过 f e e d _ d i c t feed\_dict 喂入神经网络。
注:placeholder是Tensorflow1.x版本中定义占位符的函数,在最新的Tensorflow2.x中失效。

定义神经网络和前向传播过程

# 隐藏层神经元数量
H1_NN = 256
W1 = tf.Variable(tf.random_normal([784, H1_NN], stddev=0.1),name="W1")
b1 = tf.Variable(tf.zeros([H1_NN]),name="b1")
Y1 = tf.nn.relu(tf.matmul(x,W1) + b1)
W = tf.Variable(tf.random_normal([H1_NN,10], stddev=0.1),name="W")
b = tf.Variable(tf.zeros([10]),name="b")

# 前向传播
forward = tf.matmul(Y1,W) + b
pre = tf.nn.softmax(forward)

p r e pre 即我们最后得到的一个一行十列的向量,用来训练模型或者预测图片上的数字。由于在这里只定义了一个隐藏层,所以本文中的是简单的一层神经网络模型,下次将使用模块化思想设计定义隐藏层函数。

损失函数及优化器

# 交叉熵损失函数
loss_fun = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=forward, labels=y))
# 优化器
lr = 0.0001
opt = tf.train.AdamOptimizer(lr).minimize(loss_fun)

由于此问题是一个多元分类问题,所以不能使用逻辑回归中的损失函数
J ( W , b ) = ( x , y ) D ( y log ( y ) ( 1 y ) log ( 1 y ) ) J(W,b) = \sum_{(x,y) \in D}(-y\log(y‘)-(1-y)\log(1-y’))
而使用 s o f t m a x softmax 将逻辑回归延申到多类别。
这里优化器使用的是 A d a m Adam 优化器,其中参数 l r lr 是学习率,.minimize(loss_fun)是将 l o s s _ f u n loss\_fun 降低,可以尝试换成别的优化器观察一下结果。

定义准确率

# 检查预测类别tf.argmax(pre, 1)与实际类别tf.argmax(y, 1)的匹配情况
correct_pre = tf.equal(tf.argmax(pre, 1), tf.argmax(y, 1))
# cast将布尔值投射成浮点数
acc = tf.reduce_mean(tf.cast(correct_pre, tf.float32))

函数argmax用来得到一行或者一列中数值最大的数的位置,若参数设置为1,则得到同一列中的最大值的位置;若设置为0,则得到同一行中最大值的位置。

超参数及参数的设置

# 训练轮数
epochs = 50
# 一次喂入神经网络的个数
batch_size = 40
totle_batch = int(mnist.train.num_examples/batch_size)
# 显示粒度
display_step = 1
Loss = []

每训练 d i s p l a y _ s t e p display\_step 轮即输出当前的轮数,损失和准确率。
Loss用来保存每次验证集测试的损失,并在最后通过画图显示出来。

训练模型

init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    for epoch in range(epochs):
        for batch in range(totle_batch):
            xs, ys = mnist.train.next_batch(batch_size)
            # 使用feed_dict将xs和ys喂入神经网络中,训练神经网络
            sess.run(opt,feed_dict = {x:xs, y:ys})
        # 每训练一轮测试模型在验证集上的表现    
        loss, accuracy = sess.run([loss_fun, acc], feed_dict={x:mnist.validation.images, y:mnist.validation.labels})
        Loss.append(loss)
        # 每训练display_step轮就输出当前训练信息
        if (epoch+1) % display_step == 0:
            print("Train Epoch:%02d" % (epoch+1),"Loss=%f" % loss, "Acc=%.4f" % accuracy)
    # 模型在测试集上的正确率
    acca = sess.run(acc, feed_dict={x:mnist.test.images, y:mnist.test.labels})

plt.plot(Loss)
plt.show()
print("Accuracy=%f" % acca)
print("Train Finished")

训练结果

在这里插入图片描述
在这里插入图片描述
可见训练50轮后验证集的正确率已达到98.3%,测试集上的准确率达到98.12%,正确率算是比较高。
观察Loss的图像发现后面部分loss在波动,猜测应该是由于学习率高导致,后面可采用动态指数下降学习率来使学习率逐渐降低,以弱化或者避免这种结果的出现。

猜你喜欢

转载自blog.csdn.net/weixin_44547562/article/details/102675883