6 TensorFlow实现cnn识别手写数字

————————————————————————————————————

写在开头:此文参照莫烦python教程(墙裂推荐!!!)

————————————————————————————————————

  • 这个实验的内容是:基于TensorFlow,实现手写数字的识别。
  • 这里用到的数据集是大家熟知的mnist数据集。
  • mnist有五万多张手写数字的图片,每个图片用28x28的像素矩阵表示。所以我们的输入层每个案列的特征个数就有28x28=784个;因为数字有0,1,2…9共十个,所以我们的输出层是个1x10的向量。输出层是十个小于1的非负数,表示该预测是0,1,2…9的概率,我们选取最大概率所对应的数字作为我们的最终预测。
  • 真实的数字表示为该数字所对应的位置为1,其余位置为0的1x10的向量。

下面直接贴代码,解释和笔记都在注释上了!!

#卷积神经网络(cnn)

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

#导入数据
mnist = input_data.read_data_sets('MNIST_data',one_hot=True)#如果还没下载mnist就下载

#定义计算正确率的函数
def t_accuracy(t_xs,t_ys):
    global prediction
    y_pre = sess.run(prediction,feed_dict={xs:t_xs})
    correct_pre = tf.equal(tf.argmax(y_pre,1),tf.argmax(t_ys,1))
    accuracy = tf.reduce_mean(tf.cast(correct_pre,tf.float32))
    result = sess.run(accuracy,feed_dict={xs:t_xs,ys:t_ys})
    return result

#定义权重
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)

#定义卷积神经网络层
def conv2d(x,W):
    #strides[1,x_,y_,1]
    return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME')  #x,y,z方向的跨度都为1

#定义pooling
def max_pool_2x2(x):
    return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')#strides[0]=strides[3]=1

#定义神经网络的输入值和输出值
xs = tf.placeholder(tf.float32,[None,784]) #None是不规定大小,这里指的是案例个数,而输入特征个数为28x28 = 784
ys = tf.placeholder(tf.float32,[None,10]) #Nnoe也是案例个数,不做规定;10是因为有10个数字,所以输出是10
#keep_prob = tf.placeholder(tf.float32)  #dropout
x_image = tf.reshape(xs,[-1,28,28,1])#-1:把所有图片的维度丢到一边不管;28,28是像素,1是维度,因为这里的图片是黑白的。输出为[n_samoles,28,28,1]

#定义第一层卷积层
W_conv1 = weight_variable([5,5,1,32]) #patch5x5,in_size(单位) 1,out_size(高度) 32
b_conv1 = bias_variable([32])
h_conv1 = tf.nn.relu(conv2d(x_image,W_conv1) + b_conv1) #输出格式28x28x32
h_pool1 = max_pool_2x2(h_conv1)  #输出为14x14x32

#定义第二层卷积层
W_conv2 = weight_variable([5,5,32,64]) #patch5x5,in_size(单位) 32,out_size(高度) 64
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1,W_conv2) + b_conv2) #输出格式14x14x64
h_pool2 = max_pool_2x2(h_conv2)  #输出为7x7x64

#定义第一层全连接网络层
W_fc1 = weight_variable([7*7*64,1024])
b_fc1 = bias_variable([1024])
#将h_pool2展平
h_pool2_flat = tf.reshape(h_pool2,[-1,7*7*64])
h_fc1_drop = tf.nn.relu(tf.matmul(h_pool2_flat,W_fc1)+b_fc1)
#h_fc1_drop = tf.nn.dropout(h_fc1,keep_prob)

#定义第二层全连接网络层
W_fc2=weight_variable([1024,10]) #因为有10个数字,所以输出10个
b_fc2=bias_variable([10])  #因为有十个数字,所以输出10个
prediction=tf.nn.softmax(tf.matmul(h_fc1_drop,W_fc2)+b_fc2)  #进行分类

#计算误差
cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys*tf.log(prediction),reduction_indices=[1])) #此误差计算方式和softmax配套用,效果好

#训练
train_step=tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

#开始训练
sess = tf.Session()
sess.run(tf.global_variables_initializer())

for i in range(2000):
    batch_xs,batch_ys = mnist.train.next_batch(100)   #提取数据集的100个数据,因为原来数据太大了
    sess.run(train_step,feed_dict={xs:batch_xs,ys:batch_ys})
    if i%200 == 0:
        print (t_accuracy(mnist.test.images,mnist.test.labels))  #每隔50个,打印一下正确率。注意:这里是要用test的数据来测试
Extracting MNIST_data\train-images-idx3-ubyte.gz
Extracting MNIST_data\train-labels-idx1-ubyte.gz
Extracting MNIST_data\t10k-images-idx3-ubyte.gz
Extracting MNIST_data\t10k-labels-idx1-ubyte.gz
0.0993
0.9236
0.956
0.9626
0.97
0.9742
0.9778
0.9725
0.9796
0.9826

由于是在装有强劲的显卡的台式机上运行的,所以几秒就出结果了,看得也是畅快!!训练了2000次,效果就有98.26%了,算不错吧?