tensorflow卷积神经网络实现手写识别

本文介绍了一种基于卷积神经网络(CNN)的手写数字识别方法,并详细讲解了使用TensorFlow实现的具体步骤,包括构建网络结构、训练过程及评估模型精度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://scs.ryerson.ca/~aharley/vis/conv/  很炫酷的一个手写识别网站


卷积神经网络(CNN)是深度学习一个特殊示例,在计算机视觉上有着非常重要的影响。


CNN的一个典型特性就是输入的基本上全是图片,这可以有很搞笑的实现并减少需要的参数。

读入MNIST数据并定义placeholder后:

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)     #下载并加载mnist数据
x = tf.placeholder(tf.float32, [None, 784])                        #输入的数据占位符
y_actual = tf.placeholder(tf.float32, shape=[None, 10])            #输入的标签占位符

定义四个函数,分别用于初始化权值W,初始化偏置项b, 构建卷积层和构建池化层。

#定义一个函数,用于初始化所有的权值 W
def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)

#定义一个函数,用于初始化所有的偏置项 b
def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)
  
#定义一个函数,用于构建卷积层
def conv2d(x, W):
  return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

#定义一个函数,用于构建池化层
def max_pool(x):
  return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1], padding='SAME')

定义卷积神经网络有两个基本概念:filter与characteristic maps。

卷积层的主要目的就是为了检测图像中的特性或可见性,如边缘、线,块,颜色等等,这些都是由隐藏层负责的,

它们会与输入层相连接,在CNN中,输入数据平不是与隐藏层中的神经元全连接,而只是很小的包含图片像素值

的局部控件相连。


在本例子中,隐藏层的每一个神经元是与输入层中5*5(25个神经元)小区域相连接。


对于我们描述的卷积层,经常在卷积层后面加一个池化层,池化层简单的浓缩卷积层的输出结果并创建一个压缩

版本的信息并输出,max-pooling这种方法中通过保留2*2区域中的最大值来压缩信息。


接下来构建网络。整个网络由两个卷积层(包含激活层和池化层),一个全连接层,一个dropout层和一个softmax层组成。 

#构建网络
x_image = tf.reshape(x, [-1,28,28,1])         #转换输入数据shape,以便于用于网络中


在这里我们把shape转换成了4D tensor,第二与第三唯独对应的是照片的宽度与高度,最后一个维度是颜色通道数,

阶	形状	维数	实例
0	[ ]	0-D	一个 0维张量. 一个纯量.
1	[D0]	1-D	一个1维张量的形式[5].
2	[D0, D1]	2-D	一个2维张量的形式[3, 4].
3	[D0, D1, D2]	3-D	一个3维张量的形式 [1, 4, 3].
n	[D0, D1, ... Dn]	n-D	一个n维张量的形式 [D0, D1, ... Dn].

W_conv1 = weight_variable([5, 5, 1, 32])      
b_conv1 = bias_variable([32])       
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)     #第一个卷积层
h_pool1 = max_pool(h_conv1)                                  #第一个池化层


实现第一层卷积与池化层,使用32个filters,每一个都有一个大小为5*5的窗口,shape【5,5,1,32】的权重矩阵W,前两个是窗口的大小,第三个是channel的数量,最后一个定义我们想使用多少个特征,

ReLU(Rectified Linear unit)激活函数最近变成了神经网络中隐藏层的默认激活函数。这个简单的函数包含了返回max(0,x),所以对于负值,它会返回0,其它返回x。在我们的例子中,我们会在卷积层后的隐藏层中使用这个激活函数。

 当构建一个深度神经网络时,可以相互叠加很多层。为演示如何做到这样,我会创建64个filters且窗口大小为5*5的第二层卷积层。此时我们会需传递32个channels,因为这是前一层的输出结果:

W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])              #reshape成向量
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)    #第一个全连接层

  tensor的第一维度表示第二层卷积层的输出,大小为7*7带有64个filters,第二个参数是层中的神经元数量,我们可自由设置。

  接下来,我们将tensor打平到vector中。我们在之前章节中已经看到softmax需要将图片打平成一个vector任为输入。通过打平后的vector乘以权重矩阵W_fc1,

再加上bias b_fc1,最后应用ReLU激活函数后就能实现


keep_prob = tf.placeholder("float") 
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)                  #dropout层
根据给出的keep_prob参数,将输入tensor x按比例输出。
x                 :  输入tensor
keep_prob    :  float类型,每个元素被保留下来的概率

W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
y_predict=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)   #softmax层
最后在模型中添加softmax层,softmax函数返回输入属于每一个分类的概率且概率的综合为1


网络构建好后,就可以开始训练了。

cross_entropy = -tf.reduce_sum(y_actual*tf.log(y_predict))     #交叉熵
train_step = tf.train.GradientDescentOptimizer(1e-3).minimize(cross_entropy)    #梯度下降法
correct_prediction = tf.equal(tf.argmax(y_predict,1), tf.argmax(y_actual,1))    
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))                 #精确度计算
sess=tf.InteractiveSession()                          
sess.run(tf.initialize_all_variables())
for i in range(20000):
  batch = mnist.train.next_batch(50)
  if i%100 == 0:                  #训练100次,验证一次
    train_acc = accuracy.eval(feed_dict={x:batch[0], y_actual: batch[1], keep_prob: 1.0})
    print 'step %d, training accuracy %g'%(i,train_acc)
    train_step.run(feed_dict={x: batch[0], y_actual: batch[1], keep_prob: 0.5})

test_acc=accuracy.eval(feed_dict={x: mnist.test.images, y_actual: mnist.test.labels, keep_prob: 1.0})
print "test accuracy %g"%test_acc

Tensorflow依赖于一个高效的C++后端来进行计算。与后端的这个连接叫做session。一般而言,使用TensorFlow程序的流程是先创建一个图,然后在session中启动它。

这里,我们使用更加方便的InteractiveSession类。通过它,你可以更加灵活地构建你的代码。它能让你在运行图的时候,插入一些计算图,这些计算图是由某些操作(operations)构成的。这对于工作在交互式环境中的人们来说非常便利,比如使用IPython。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值