实战|TensorFlow 实践之手写体数字识别!

转载 2018年04月17日 00:00:00


本文的主要目的是教会大家运用google开源的深度学习框架tensorflow来实现手写体数字识别,给出两种模型,一种是利用机器学习中的softmax regression作分类器,另一种将是搭建一个深度神经网络以达到99%正确率的手写体数字识别模型。 其次,理解tensorflow工作流程和运行机制。最后,也会让大家了解一下深度神经网络的搭建过程。

640?wx_fmt=png&wxfrom=5&wx_lazy=1

第一种模型
我们知道,做机器学习的项目离不开数据,行业里有句话叫做“得数据者,得天下”,虽有点言过其实,但事实上,足够的样本数据是你获得较好模型的前提之一。这里,用到的是大名鼎鼎的mnist,其官网是http://yann.lecun.com/exdb/mnist/,大家可以自由下载。google给出的下载源码是input_data.py,可以从https://github.com/xupeng082008/tensorflow_mnist下载。下载后的数据集分为训练集、验证集、测试集(也就是train_data,validation_data,test_dasta,记住,这样的划分很重要,它可以检验我们得到的模型在真实场景下的识别能力)。无论是训练、验证还是测试集,单个样本都是一帧包含手写数字的28x28图像以及其对应的标签。有了数据,我们开始建立模型。这里的模型是机器学习经常用到的softmax regression。
简单地用图片来表示一下:

用乘积形式表示如下:

在tensorflow中,它是这样实现的:
import tensorflow as tf
y=tf.nn.softmax(tf.matmul(x,w) + b)
x是输入(这里可以理解为28x28的图像拉伸为一个1x784向量),w是网络权重系数,b是偏置。
代码相当简单,好理解。

下面贴出该模型所有的代码并作出解释
import tensorflow as tf
import input_data

#加载数据,注意一下one_hot 在tensorflow中,
#表示一个列向量,其中一个不为0,剩下的为0
mnist=input_data.read_data_sets("Mnist_data/",one_hot=True)
#在tensorflow中,tf.placeholder表示一个占位符,x不是一个特定的值,
#在运行时,才有值
x = tf.placeholder("float",[None,784])
#在tensorflow中,tf.Variable表示变量,且可以用不同的方式初始化
w = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
#softmax模型
y = tf.nn.softmax(tf.matmul(x,w) + b)
y_ = tf.placeholder("float",[None,10])
#模型的损失是交叉熵,详情可以见原创 干货|深度学习——损失函数不同,
收敛效率不同
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
#随机梯度下降优化算法
#主要:TensorFlow 在这里实际上所做的是,它会在后台给述你的计算的那张图
#里面增加一系列新的计算操作单元用于实现反向传播算法和梯度下降算法.然后,
#它返回给你的只是一个单一的操作,当运行这个操作时,它用梯度下降算法训练
#你的模型,微调你的变量,不断减少成本
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
#这里的代码跟tensorflow运行机制相关
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
for i in range(1000):#1000 or more
    batch_xs,batch_ys = mnist.train.next_batch(100)
    sess.run(train_step,feed_dict={x:batch_xs,y_:batch_ys})

correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,"float"))
print sess.run(accuracy,feed_dict={x:mnist.test.images,y_:mnist.test.labels})

这里简单说说tensorflow运行机制相关,让读者有一个感性的认识:
tensorflow使用图(graphs)来表示模型的整个计算过程
tensorflow在会话(Session)中执行图所表示的运行过程
tensorflow使用张量(tensors)来代表数据,可以表示为输入向量,权重系数等等
tensorflow通过变量(Variables)维护变量的运行状态
tensorflow使用供给(feeds)和取回(fetches)将数据传入或传出等操作
总之,tensorflow是以图来表示整个程序运行系统,图中以节点为组织,在会话中执行运行,然后产生张量,这个张量是一个四维向量,在图中流动起来。可以理解前面部分代码是在构建,后面是在执行。
上面的代码执行情况如下:
迭代次数正确率100091.19%500092.21%2000092.27%
可以,softmax regression在这里达到的最好成绩92%左右,跟理想的还差很远。

第二种模型
这里,我们的模型是一个有着两个卷积层,2个全联接层,一个输出层组成,继续使用交叉熵损失函数,激活函数是relu,并且使用dropout技术,结构图如下:
Inputconv1pool1conv2pool2fc1dropoutfc2softmax

下面,我们来看看在tensorflow如何实现上面表格实现的深度神经网络
import tensorflow as tf 
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])

w = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))

#init weights and biases
#初始化权重系数、偏置,注意这里初始化不是用0来填充,以打破对称性
def weight_variable(shape):
    initial = tf.truncated_normal(shape,stddev = 0.1)
    return tf.Variable(initial)
def bias_variable(shape):
    initial = tf.constant(0.1,shape = shape)
    return tf.Variable(initial)

#define convolution and pool function
#定义卷积、池化,tensorflow中有实现,具体实践,我们自行修改参数
def conv2d(x,w):
    return tf.nn.conv2d(x,w,strides = [1,1,1,1],padding = 'SAME')

def max_pool_2x2(x):
    return tf.nn.max_pool(x,ksize=[1,2,2,1],strides = [1,2,2,1],
            padding='SAME')
#conv and pool 
#the first conv_pool
#patchsize(5x5) input_channels(1) output_channels(32 feature_maps)
w_conv1 = weight_variable([5,5,1,32])
b_conv1 = bias_variable([32])
x_image = tf.reshape(x,[-1,28,28,1])

#1st hidden outputs
h_conv1 = tf.nn.relu(conv2d(x_image,w_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

#the second conv_pool
w_conv2 = weight_variable([5,5,32,64])
b_conv2 = bias_variable([64])

#2nd hidden outputs
h_conv2 = tf.nn.relu(conv2d(h_pool1,w_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

#fc全联接层
w_fc1 = weight_variable([7*7*64,1024])
b_fc1 = bias_variable([1024])

h_pool2_flat = tf.reshape(h_pool2,[-1,7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat,w_fc1) + b_fc1)

#dropout使用dropout技术可以防止过拟合
keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1,keep_prob)

#readout layer
w_fc2 = weight_variable([1024,10])
b_fc2 = bias_variable([10])

#softmax output
y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop,w_fc2) + b_fc2)

#define loss function
cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))
#optimizer method choice
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1),tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,"float"))
sess.run(tf.initialize_all_variables())
for i in range(10000):
    batch = mnist.train.next_batch(50)
    if i%100==0:
        train_accuracy = accuracy.eval(feed_dict={
            x:batch[0],y_:batch[1],keep_prob:1.0})
        print "step %d, training accuracy %g"%(i,train_accuracy)
    train_step.run(feed_dict={x:batch[0],y_:batch[1],keep_prob:0.5})
print "test accuracy %g"%accuracy.eval(feed_dict={
        x:mnist.test.images,y_:mnist.test.labels,keep_prob:1.0})
下面给出一些训练过程中间图:

可以看出,训练识别率还是很不错的,我们看下最终迭代10000次的训练和测试结果:

测试集上的正确率是99%左右。
可见深度神经网络,在手写体识别项目上表现地相比于softmax regression,效果会好的多的多。

总结
我们学习了在tensorflow中实现softmax regression、一种深度神经网络的过程;简单了解了tensorflow的运行机制和内部参数、函数机构,相信看完大家可以手动设计一个神经网络将识别率继续提高。


代码:https://github.com/xupeng082008/tensorflow_mnist

∞∞∞


640?wx_fmt=jpeg&wx_lazy=1&wxfrom=5

IT派 - {技术青年圈}持续关注互联网、区块链、人工智能领域640?wx_fmt=jpeg&wx_lazy=1&wxfrom=5



公众号回复“机器学习”

邀你加入{ IT派AI机器学习群 } 


(Tensorflow之八)MNIST数字识别源码--实战Google深度学习框架5.2小节

针对原书本的一点小bug进行了修改,直接贴上源码,供大家参考 训练集与测试集的模型需手动下载,下载地址:http://yann.lecun.com/exdb/mnist/ import tenso...
  • abiggg
  • abiggg
  • 2018-01-05 00:46:12
  • 76

tensorflow08 《TensorFlow实战Google深度学习框架》笔记-05-01minist数字识别问题code

01 mnist数据读取# 《TensorFlow实战Google深度学习框架》05 minist数字识别问题 # win10 Tensorflow1.0.1 python3.5.3 # CUDA v...
  • longji
  • longji
  • 2017-04-08 21:53:57
  • 2188

用CNN解决手写体数字识别。--tensorflow

第一次解决这个问题是应用了机器学习中的Knn算法,发现排名并不是很高。再阅读了kaggle上其他人的一些笔记,知道了神经网络在图片分类上的优秀。我们可以用卷积层来得到数据图片中的某些特征,然后使用激活...
  • weixin_40012507
  • weixin_40012507
  • 2017-11-02 21:02:53
  • 470

Tensorflow实战Google-第五章mnist数字识别

import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data import mnist_infe...
  • SoundSlow
  • SoundSlow
  • 2017-10-03 23:59:53
  • 831

TensorFlow学习_02_CNN卷积神经网络_Mnist手写数字识别

github地址:https://github.com/lawlite19/MachineLearning_TensorFlow 或者上一篇Tensorflow的博客:http://blog.csdn...
  • u013082989
  • u013082989
  • 2016-12-16 16:54:40
  • 3930

深度学习的 helloworld -- 基于 tensorflow 实现的 MNISI 数字手写体识别

1. MNIST 数据集的下载及其介绍下载地址为:点击打开链接内容:下载下来的数据集被分成两部分:60000行的训练数据集(mnist.train)和10000行的测试数据集(mnist.test)。...
  • tkzc_csk
  • tkzc_csk
  • 2018-02-18 23:42:55
  • 101

用Tensorflow实现CNN手写数字识别

这是自己的第一篇博客,写的不好请见谅,就是想把自己这段时间所学的相关tensorflow的相关东西做个总结,帮助自己记忆,也希望能对别人有点帮助。   通过Tensorflow做的关于Mnist的数字...
  • chengge_chengzi
  • chengge_chengzi
  • 2017-03-05 21:36:25
  • 2550

Tensorflow 改进的MNIST手写体数字识别

上篇简单的Tensorflow解决MNIST手写体数字识别可扩展性并不好。例如计算前向传播的函数需要将所有的变量都传入,当神经网络的结构变得复杂、参数更多时,程序的可读性变得非常差。而且这种方式会导致...
  • lilong117194
  • lilong117194
  • 2018-02-01 18:19:42
  • 77

《机器学习实战》之K—近邻算法实现手写体数字识别

一、问题描述 主要程序为kNN.py,在主程序中,包含函数: classify0(inX, dataSet, labels, k):实现分类 file2matrix(filename):将文本文件转...
  • moulei0322
  • moulei0322
  • 2017-07-10 18:27:16
  • 385

用TensorFlow构造CNN进行手写数字识别

在前两篇文章中,分别用Softmax回归和普通的3层神经网络在MNIST上进行了手写数字的识别。这两种方法都是将图片转换成一维的数组进行处理,没有考虑图片的二维结构信息,所以准确率都还不够高。在这篇文...
  • clcwcxfwf
  • clcwcxfwf
  • 2017-06-03 20:26:04
  • 1946
收藏助手
不良信息举报
您举报文章:实战|TensorFlow 实践之手写体数字识别!
举报原因:
原因补充:

(最多只允许输入30个字)