教你用TensorFlow实现手写数字识别

版权声明:很高兴认识你,我叫邵龙飞 原创文章,转载请注明 https://blog.csdn.net/qq_37482202/article/details/84937581

弱者用泪水安慰自己,强者用汗水磨练自己。

这段时间因为项目中有一块需要用到图像识别,最近就一直在炼丹,宝宝心里苦,但是宝宝不说。。。

能点开这篇文章的朋友估计也已经对TensorFlow有了一定了解,至少知道这是个什么东西,我也就不过多介绍了。

没安装TensorFlow的建议去下一个Anaconda,可以很方便的下载配置好各种科学计算的常用库,对于Anaconda的配置和更新问题可以去搜一些文章去看,这里就不多说了。

实现手写数字识别几乎是所有入手图像识别的入门程序了,TensorFlow库里面也有手写数字识别的示例程序,在这个路径下,你可以对应自己的电脑去找一下C:\ProgramData\Anaconda3\pkgs\tensorflow-base-1.12.0-gpu_py36h6e53903_0\Lib\site-packages\tensorflow\examples\tutorials\mnist。

首先载入MNIST数据集,并创建默认的Interactive Session

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

mnist=input_data.read_data_sets("MNIST/",one_hot=True)
sess=tf.InteractiveSession()

接下来要实现的这个卷积神经网络会有很多的权重和偏置要创建,因此我们先定义好初始化函数以便重复使用。我们需要给权重制造一些随机的噪声来打破完全对称,比如截断的正太分布噪声,标准差为0.1。同时因为我们使用的ReLU激活函数,也给偏置增加一些大于零的值来避免死亡节点。

def weight_variable(shape):
    initial=tf.truncated_normal(shape,stddev=0.1)
    return tf.Variable(initial)

def bias_variable(shape):
    inital=tf.constant(0.1,shape=shape)
    return tf.Variable(inital)

卷积层、池化层也是接下来要重复使用的,因此也要为他们定义方法。这里的tf.nn.conv2d是TensorFlow中的2维卷积函数,参数中X是输入,W是卷积的参数,比如[5,5,1,32],前面两个数字代表卷积核的尺寸,第三个数字代表通道数量,因为我们只是灰度图,所以是1,如果是RGB彩图那么就应该为3,最后一个数字代表卷积核的数量,也就是这个卷积层要提取多少类的特征。Strides代表卷积模板移动的步长,都是1代表会一个不落的划过每个点,Padding代表边界处理方式,这里的SAME代表给边界加上Padding让卷积的输出和输入保持同样的尺寸。

tf.nn.max_pool是TensorFLow中的最大池化函数,我们这里使用2X2的最大池化,就是说把一个2X2的像素块降到1X1的像素。最大池化会保留原始像素块中灰度值最高的哪一个像素,即保留最显著的特征。因为希望整体上缩小图片尺寸,因此池化层的strides也设为横竖两个方向以2为步长。如果步长还是1,那么我们会得到一个尺寸不变的图片。

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')

在设计卷积神经网络之前,我们还需要定义输入的placeholder,x是特征,y_是真实的类别,因为卷积神经网咯会利用到哦控件结构信息,因此需要将1D的输入向量转为2D的图片结构,就是说从1X784变成28X28,,又因为只有一个颜色通道,所以最终的尺寸应该是[-1,28,28,1],前面的-1代表样本数量不固定,最后的1代表颜色通道数量。

x=tf.placeholder(tf.float32,[None,784])
y_=tf.placeholder(tf.float32,[None,10])
x_image=tf.reshape(x,[-1,28,28,1])

定义第一个卷积层,先初始化参数,[5,5,1,32]代表卷积核的尺寸为5X5,1个颜色通道,32个不同的卷积核。然后用conv2d进行卷积操作,加上偏置,用ReLU激活函数进行非线性处理。最后,使用最大池化函数max_pool_2x2对卷积的输出结果进行池化操作。

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_2x2(h_conv1)

定义第二层卷积,大体上和第一层一样,把卷积核数量改为64就OK了

w_conv2=weight_variable([5,5,32,64])
b_conv2=bias_variable([64])
h_conv2=tf.nn.relu(conv2d(h_pool1,w_conv2)+b_conv2)
h_pool2=max_pool_2x2(h_conv2)

因为前面经历了两次步长为2X2的最大池化,所以边长已经只有1/4了,图片尺寸从28X28变到了7X7,而第二个卷积层的卷积核数量为64,其输出的tensor尺寸也就是7X7X64。用tf.reshape对第二个卷积层的输出tensor进行变形,转为1D的向量,然后连接一个全连接层,隐藏节点为1024,使用ReLU激活函数。

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层,该层会随机丢弃一些节点之间的连接,这样可减轻过拟合,提高模型泛化性。

keep_prob=tf.placeholder(tf.float32)
h_fc1_drop=tf.nn.dropout(h_fc1,keep_prob)

将Dropout层连接一个Softmax层,得到最后的概率输出。

w_fc2=weight_variable([1024,10])
b_fc2=bias_variable([10])
y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop,w_fc2)+b_fc2)

定义损失函数cross_entropy,优化器用Adam,学习效率尽量往小里设置。

cross_entropy=tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y_conv),reduction_indices=[1]))
train_step=tf.train.AdagradOptimizer(1e-4).minimize(cross_entropy)

定义评测准确率

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

接下里就是训练过程了。开始初始化所有参数,设置训练时Dropout层的丢弃率为0.5.使用大小为50的mini-batch训练20000次,每100次训练输出一次准确率。

tf.global_variables_initializer().run()
for i in range(20000):
    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:1.0})

最后训练完成后要输出一次最后的测试结果

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

程序到这就完事了,就开始跑吧,你大概会跑上20分钟,你的窗口就会一直输出准确率

step 4300,training accuracy 0.88
step 4400,training accuracy 0.92
step 4500,training accuracy 0.82
step 4600,training accuracy 0.84
step 4700,training accuracy 0.94

猜你喜欢

转载自blog.csdn.net/qq_37482202/article/details/84937581