前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >tensorflow实现手写体数字识别

tensorflow实现手写体数字识别

作者头像
luxuantao
发布2021-02-24 11:24:31
1K0
发布2021-02-24 11:24:31
举报
文章被收录于专栏:Fdu弟中弟Fdu弟中弟

调用tensorflow实现手写体数字识别。

内容参考自北京大学曹健教授的tensorflow课程,在此感谢 代码原址:https://github.com/cj0012/AI-Practice-Tensorflow-Notes

之前在人工智能课上自己手动搭建过一个BP神经网络实现MNIST数据集的手写体数字识别,使用的是c++,最终准确率的上限在95%至96%左右(毕竟水平有限)。这次不一样了,使用tensorflow进行实验,准确率确实提高了不少。可能有人会觉得tensorflow有点过时,现在的大企业不怎么用tensorflow了,但我觉得,对于初学者来说,tensorflow还是不错的选择。

实验环境

  • ubuntu 16.04
  • python 2.7.13
  • tensorflow 1.3.0
  • MNIST数据集

我不清楚windows下可不可以装tensorflow,反正很久以前是不行,现在好像可以了???

总体框架

主要分为三个部分如下:

  • 前向传播过程(mnist_forward.py)
  • 进行网络参数优化方法的反向传播过程 ( mnist_backward.py )
  • 验证模型准确率的测试过程(mnist_test.py)

每个部分都单独写成了一个模块文件。

源代码

mnist_forward.py

代码语言:javascript
复制
import tensorflow as tf

INPUT_NODE = 784
OUTPUT_NODE = 10
LAYER1_NODE = 500

def get_weight(shape, regularizer):
	w = tf.Variable(tf.truncated_normal(shape, stddev=0.1))
	if regularizer != None:
		tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(regularizer)(w))
	return w

def get_bias(shape):
	b = tf.Variable(tf.zeros(shape))
	return b

def forward(x, regularizer):	
	w1 = get_weight([INPUT_NODE, LAYER1_NODE], regularizer)
	b1 = get_bias([LAYER1_NODE])
	y1 = tf.nn.relu(tf.matmul(x, w1) + b1)

	w2 = get_weight([LAYER1_NODE, OUTPUT_NODE], regularizer)
	b2 = get_bias([OUTPUT_NODE])
	y = tf.matmul(y1, w2) + b2	
	return y

mnist_backward.py

代码语言:javascript
复制
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import mnist_forward
import os

STEPS = 50000
BATCH_SIZE = 200
LEARNING_RATE_BASE = 0.1
LEARNING_RATE_DECAY = 0.99
REGULIZER = 0.0001
MOVING_AVERAGE_DECAY = 0.99
MODEL_SAVE_PATH = "./model/"
MODEL_NAME = "mnist_model"

def backward(mnist):
	x = tf.placeholder(tf.float32, [None, mnist_forward.INPUT_NODE])
	y_ = tf.placeholder(tf.float32, [None, mnist_forward.OUTPUT_NODE])
	y = mnist_forward.forward(x, REGULIZER)
	global_step = tf.Variable(0, trainable = False)

	ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_,-1))
	cem = tf.reduce_mean(ce)
	loss = cem + tf.add_n(tf.get_collection('losses'))

	learning_rate = tf.train.exponential_decay(
		LEARNING_RATE_BASE,
		global_step,
		mnist.train.num_examples / BATCH_SIZE,
		LEARNING_RATE_DECAY,
		staircase = True
		)

	train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)
	ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
	ema_op = ema.apply(tf.trainable_variables())

	with tf.control_dependencies([train_step, ema_op]):
		train_op = tf.no_op(name = 'train')

	saver = tf.train.Saver()

	with tf.Session() as sess:
		init_op = tf.global_variables_initializer()
		sess.run(init_op)

		ckpt = tf.train.get_checkpoint_state(MODEL_SAVE_PATH)
		if ckpt and ckpt.model_checkpoint_path:
			saver.restore(sess, ckpt.model_checkpoint_path)

		for i in range(STEPS):
			xs,ys = mnist.train.next_batch(BATCH_SIZE)
			_,loss_value,step = sess.run([train_op, loss, global_step], feed_dict={x:xs, y_:ys})
			if i % 1000 == 0:
				print "after %d training steps, loss on training batch is %g" % (step, loss_value)
				saver.save(sess, os.path.join(MODEL_SAVE_PATH,MODEL_NAME), global_step=global_step)	

def main():
	mnist = input_data.read_data_sets("./data/", one_hot=True)
	backward(mnist)

if __name__ == '__main__':
	main()

mnist_test.py

代码语言:javascript
复制
#coding utf-8
import time
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import mnist_forward
import mnist_backward
TEST_INTERVAL_SECS = 5

def test(mnist):
	with tf.Graph().as_default() as g:
		x = tf.placeholder(tf.float32, [None, mnist_forward.INPUT_NODE])
		y_ = tf.placeholder(tf.float32, [None, mnist_forward.OUTPUT_NODE])
		y = mnist_forward.forward(x, None)

		ema = tf.train.ExponentialMovingAverage(mnist_backward.MOVING_AVERAGE_DECAY)
		ema_restore = ema.variables_to_restore()
		saver = tf.train.Saver(ema_restore)

		correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
		accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

		while True:
			with tf.Session() as sess:
				ckpt = tf.train.get_checkpoint_state(mnist_backward.MODEL_SAVE_PATH)
				if ckpt and ckpt.model_checkpoint_path:
					saver.restore(sess, ckpt.model_checkpoint_path)
					global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]
					accuracy_score = sess.run(accuracy, feed_dict={x:mnist.test.images, y_:mnist.test.labels})
					print "after %s training steps, test accuracy = %g" % (global_step, accuracy_score)
				else:
					print "no checkpoint file found"
					return
			time.sleep(TEST_INTERVAL_SECS)

def main():
	mnist = input_data.read_data_sets("./data/", one_hot=True)
	test(mnist)

if __name__ == '__main__':
	main()

代码解析

mnist_forward.py

代码语言:javascript
复制
INPUT_NODE = 784
OUTPUT_NODE = 10
LAYER1_NODE = 500

在前向传播过程中,规定网络输入结点为 784 个(代表每张输入图片的像素个数),隐藏层节点 500 个(一层),输出节点 10 个(表示输出为数字 0-9的十分类)

代码语言:javascript
复制
w = tf.Variable(tf.truncated_normal(shape, stddev=0.1))

参数满足截断正态分布

代码语言:javascript
复制
if regularizer != None:
	tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(regularizer)(w))

使用正则化,将每个参数的正则化损失加到总损失中

mnist_backward.py

代码语言:javascript
复制
ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_,-1))
	cem = tf.reduce_mean(ce)
	loss = cem + tf.add_n(tf.get_collection('losses'))

softmax()函数与交叉熵一起使用,再加上正则化损失以此计算得到总的偏差值

代码语言:javascript
复制
learning_rate = tf.train.exponential_decay(
		LEARNING_RATE_BASE,
		global_step,
		mnist.train.num_examples / BATCH_SIZE,
		LEARNING_RATE_DECAY,
		staircase = True
		)

使用指数衰减学习率使模型在训练的前期快速收敛接近较优解

代码语言:javascript
复制
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)

使用梯度下降算法

代码语言:javascript
复制
ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
	ema_op = ema.apply(tf.trainable_variables())

	with tf.control_dependencies([train_step, ema_op]):
		train_op = tf.no_op(name = 'train')

在模型训练时引入滑动平均使模型在测试数据上表现的更加健壮

代码语言:javascript
复制
saver = tf.train.Saver()
代码语言:javascript
复制
ckpt = tf.train.get_checkpoint_state(MODEL_SAVE_PATH)
		if ckpt and ckpt.model_checkpoint_path:
			saver.restore(sess, ckpt.model_checkpoint_path)
代码语言:javascript
复制
saver.save(sess, os.path.join(MODEL_SAVE_PATH,MODEL_NAME), global_step=global_step)

断点续训,因为训练时间比较长,万一断电了呢。。。为了使得之前训练好的参数(w,b)能够保留下来,调用了saver进行保存和恢复

mnist_test.py

代码语言:javascript
复制
TEST_INTERVAL_SECS = 5
代码语言:javascript
复制
time.sleep(TEST_INTERVAL_SECS)

每隔五秒钟测试一次

代码语言:javascript
复制
ema = tf.train.ExponentialMovingAverage(mnist_backward.MOVING_AVERAGES_DECAY)
		ema_restore = ema.variables_to_restore()
		saver = tf.train.Saver(ema_restore)

实例化具有滑动平均的 saver 对象,从而在会话被加载时,模型中的所有参数被赋值为各自的滑动平均值,增强模型的稳定性

操作步骤

可能你已经注意到了,mnist_forward.py中并没有main函数(说明这个文件只是一个模块用来被其他文件调用,本例中是mnist_backward.py调用了mnist_forward.py),而另两个文件都有main函数。

  • 终端输入python mnist_backward.py,开始训练,会显示实时的损失值,如:after 15005 training steps, loss on training batch is 0.159981
  • 再开一个终端,输入python mnist_test.py,进行同步的测试(每五秒一次),会显示实时的损失值,如:after 15005 training steps, test accuracy = 0.979

实验结果

代码里设置的总循环数是50000次,但是我只跑到15000次(毕竟时间比较久),但已经能有98%的准确率了,如果全跑完的话,预计能达到99%以上。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-09-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实验环境
  • 总体框架
  • 源代码
    • mnist_forward.py
      • mnist_backward.py
        • mnist_test.py
        • 代码解析
          • mnist_forward.py
            • mnist_backward.py
              • mnist_test.py
              • 操作步骤
              • 实验结果
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档