TensorFlow下进行MNIST手写数字识别实例,从最简单的两层到LeNet5

MNIST是很适合深度学习初学者入门的例子,可谓是helloword级别的练习,建议入门必学。

先来一段最简单的MNIST训练程序

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


# 1.Import data
mnist = input_data.read_data_sets("./MNIST_data/", one_hot=True)

#Print the shape of mist
print (mnist.train.images.shape,mnist.train.labels.shape)
print(mnist.test.images.shape, mnist.train.labels.shape)
print(mnist.validation.images.shape, mnist.validation.labels.shape)

# 2.Create the model
# y=wx+b
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
y = tf.matmul(x, W) + b

# Define loss and optimizer
y_ = tf.placeholder(tf.float32, [None, 10])

# The raw formulation of cross-entropy,
#
#   tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(tf.nn.softmax(y)),
#                                 reduction_indices=[1]))
#
# can be numerically unstable.
#
# So here we use tf.nn.softmax_cross_entropy_with_logits on the raw
# outputs of 'y', and then average across the batch.
cross_entropy = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))

cross_entropy_mean = tf.reduce_mean(cross_entropy)
loss = cross_entropy_mean

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

# Init model
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
# Train
for i in range(100000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
    if(i%10000==0):
        print(i)

# Test trained model
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(sess.run(accuracy, feed_dict={x: mnist.test.images,
                                    y_: mnist.test.labels}))

这只是一个简单的模型,甚至称不上神经网络,训练后识别率只有92%,但训练速度较快,可以让初学者对TensorFlow有更直观的理解。

读者可以自行改进代码,加入隐藏层、激活函数、正则化等代码,将识别率大大提升。

修改后的代码如下

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

INPUT_NODE = 784
OUTPUT_NODE = 10
LAYER1_NODE = 500
BATCH_SIZE = 100
REGULARIZATION_RATE = 0.0001
LEARNING_RATE_BASE = 0.8
LEARNING_RATE_DECAY = 0.99

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

x = tf.placeholder(tf.float32, [None, INPUT_NODE])
W1 = tf.Variable(tf.truncated_normal([INPUT_NODE, LAYER1_NODE]))
b1 = tf.Variable(tf.zeros([LAYER1_NODE]))
W2 = tf.Variable(tf.truncated_normal([LAYER1_NODE, OUTPUT_NODE]))
b2 = tf.Variable(tf.zeros([OUTPUT_NODE]))
lay1 = tf.nn.relu(tf.matmul(x, W1) + b1)
y = tf.matmul(lay1, W2) + b2

global_step = tf.Variable(0,trainable=False)

# Define loss and optimizer
y_ = tf.placeholder(tf.float32, [None, OUTPUT_NODE])

cross_entropy = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits_v2(labels=y_, logits=y))
cross_entropy_mean = tf.reduce_mean(cross_entropy)

regularizer = tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)
regularization = regularizer(W1) +regularizer(W2)
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)

# Init model
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
# Train
for i in range(100000):
    batch_xs, batch_ys = mnist.train.next_batch(BATCH_SIZE)
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
    if(i%1000==0):
        correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        validate_acc = sess.run(accuracy, feed_dict={x: mnist.test.images,
                                    y_: mnist.test.labels})
        print("%d %g"%(i,validate_acc))
        
# Test trained model
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(sess.run(accuracy, feed_dict={x: mnist.test.images,
                                    y_: mnist.test.labels}))

经过50000次迭代训练后,识别准确率达到98%,为了避免过拟合,这个结果已经比较令人满意。


最后改进结构,使用LeNet5的七层卷积神经网络。

import tensorflow as tf  
from tensorflow.examples.tutorials.mnist import input_data  
  
mnist = input_data.read_data_sets('./MNIST_data/', one_hot=True)  
  
sess = tf.InteractiveSession()  
  
#训练数据  
x = tf.placeholder("float", shape=[None, 784])  
#训练标签数据  
y_ = tf.placeholder("float", shape=[None, 10])  
#把x更改为4维张量,第1维代表样本数量,第2维和第3维代表图像长宽, 第4维代表图像通道数, 1表示黑白  
x_image = tf.reshape(x, [-1,28,28,1])  
  
  
#第一层:卷积层  
conv1_weights = tf.get_variable("conv1_weights", [5, 5, 1, 32], initializer=tf.truncated_normal_initializer(stddev=0.1)) #过滤器大小为5*5, 当前层深度为1, 过滤器的深度为32  
conv1_biases = tf.get_variable("conv1_biases", [32], initializer=tf.constant_initializer(0.0))  
conv1 = tf.nn.conv2d(x_image, conv1_weights, strides=[1, 1, 1, 1], padding='SAME') #移动步长为1, 使用全0填充  
relu1 = tf.nn.relu( tf.nn.bias_add(conv1, conv1_biases) ) #激活函数Relu去线性化  
  
#第二层:最大池化层  
#池化层过滤器的大小为2*2, 移动步长为2,使用全0填充  
pool1 = tf.nn.max_pool(relu1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')  
  
#第三层:卷积层  
conv2_weights = tf.get_variable("conv2_weights", [5, 5, 32, 64], initializer=tf.truncated_normal_initializer(stddev=0.1)) #过滤器大小为5*5, 当前层深度为32, 过滤器的深度为64  
conv2_biases = tf.get_variable("conv2_biases", [64], initializer=tf.constant_initializer(0.0))  
conv2 = tf.nn.conv2d(pool1, conv2_weights, strides=[1, 1, 1, 1], padding='SAME') #移动步长为1, 使用全0填充  
relu2 = tf.nn.relu( tf.nn.bias_add(conv2, conv2_biases) )  
  
#第四层:最大池化层  
#池化层过滤器的大小为2*2, 移动步长为2,使用全0填充  
pool2 = tf.nn.max_pool(relu2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')  
  
#第五层:全连接层  
fc1_weights = tf.get_variable("fc1_weights", [7 * 7 * 64, 1024], initializer=tf.truncated_normal_initializer(stddev=0.1)) #7*7*64=3136把前一层的输出变成特征向量  
fc1_baises = tf.get_variable("fc1_baises", [1024], initializer=tf.constant_initializer(0.1))  
pool2_vector = tf.reshape(pool2, [-1, 7 * 7 * 64])  
fc1 = tf.nn.relu(tf.matmul(pool2_vector, fc1_weights) + fc1_baises)  
  
#为了减少过拟合,加入Dropout层  
keep_prob = tf.placeholder(tf.float32)  
fc1_dropout = tf.nn.dropout(fc1, keep_prob)  
  
#第六层:全连接层  
fc2_weights = tf.get_variable("fc2_weights", [1024, 10], initializer=tf.truncated_normal_initializer(stddev=0.1)) #神经元节点数1024, 分类节点10  
fc2_biases = tf.get_variable("fc2_biases", [10], initializer=tf.constant_initializer(0.1))  
fc2 = tf.matmul(fc1_dropout, fc2_weights) + fc2_biases  
  
#第七层:输出层  
# softmax  
y_conv = tf.nn.softmax(fc2)  
  
#定义交叉熵损失函数  
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y_conv), reduction_indices=[1]))  
  
#选择优化器,并让优化器最小化损失函数/收敛, 反向传播  
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)  
  
# tf.argmax()返回的是某一维度上其数据最大所在的索引值,在这里即代表预测值和真实值  
# 判断预测值y和真实值y_中最大数的索引是否一致,y的值为1-10概率  
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))  
  
# 用平均值来统计测试准确率  
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))  
  
#开始训练  
sess.run(tf.global_variables_initializer())
saver = tf.train.Saver()

for i in range(10000):  
    batch = mnist.train.next_batch(100)  
    if i%100 == 0:  
        train_accuracy = accuracy.eval(feed_dict={x:batch[0], y_: batch[1], keep_prob: 1.0}) #评估阶段不使用Dropout  
        print("step %d, training accuracy %f" % (i, train_accuracy))  
    train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5}) #训练阶段使用50%的Dropout  
  
print("W1:", sess.run(conv1_weights)) # 打印v1、v2的值一会读取之后对比
print("W2:", sess.run(conv1_biases))

saver_path = saver.save(sess, "save/model.ckpt")  # 将模型保存到save/model.ckpt文件
print("Model saved in file:", saver_path)
  
#在测试数据上测试准确率  
print("test accuracy %g" % accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))  
这段使用LeNet5的程序可以达到99%以上的准确率


下一步使用自己的手写图片,测试模型是否可用于实际识别。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值