利用tensorflow实现CNN的MNIST图像识别

将本代码直接在环境中运行即可。

若数据集加载慢,可先下载mnist数据集,并放到代码所在文件夹。
在这里插入图片描述

# -*- coding: utf-8 -*-
"""
ENVS: python3.6, Tensorflow1.14
"""
#引入tensorflow和数据集
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import ssl
ssl._create_default_https_context = ssl._create_unverified_context

#---------------1 定义后面会引用的函数---------------#
#权值初始化
def weight_value(shape):
    #随机初始化一个shape大小的,均值为0且标准差为0.1的,权重矩阵
    init=tf.truncated_normal(shape,mean=0.0,stddev=0.1)
    return tf.Variable(init)

#偏置初始化
def biase_value(shape):
    #偏置值,根据shape填充全是0.1的矩阵
    init=tf.constant(0.1,shape=shape)
    return tf.Variable(init)

#卷积层
#根据输入数据和filter做卷积
def conv2d(Inputs,Weight):
    #调用tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, name=None)
    
    #strides([1,x_movements,y_movements,1])为卷积核滑动步长
    #padding为补零方法,比如3列用2*2的核取max,最后一列是直接舍弃(valid)还是再多补一列的0(same)
    return tf.nn.conv2d(Inputs,Weight,strides=[1,1,1,1],padding='SAME')

#池化层
def maxpooling(Inputs):
    #ksize为池化核的大小,2*2
    #strides([1,x_movements,y_movements,1])为卷积核滑动步长
    #padding为补零方法
    return tf.nn.max_pool(Inputs,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')

#------------2 前向定义网络------------#

mnist=input_data.read_data_sets("MNIST_data",one_hot=True)

#placeholder是TensorFlow中的占位符,用于将外部的数据传到TensorFlow当中,形成一个TensorFlow的数据。
#读入图片,因为输入数据是28*28的矩阵(包括了所有的输入图片),[None,784]表示列是784,行不定
xs=tf.placeholder(tf.float32,[None,784])

#读入标签,10是因为有0—9十个数字,[None,10]表示列是10,行不定
ys=tf.placeholder(tf.float32,[None,10])

#dropout的失活率(下面有解释)
keep_prob=tf.placeholder(tf.float32)
 
#将输入的图片reshape
#其中的-1代表着一共输入了多少数据,两个28即为输入数据矩阵的大小,1为输入图片的通道数(因为是灰色照片)
Image=tf.reshape(xs,[-1,28,28,1])

#第一个卷积层
conv1_W=weight_value([5,5,1,32])
#定义第一个filter,大小为[5,5,1,32],权重调用weight_value随机初始化(满足均值=0和标准差=0.1)
#上面的两个5代表卷积核的大小为5*5
#1代表输入的一张图片的通道数
#32代表经过这一神经层处理后生成的通道数(特征数)  也是卷积核的深度 depth,类似于几个5*5的核

conv1_b=biase_value([32])# 因为生成了32个通道,产生32个0.1数组

conv1_h=tf.nn.relu(conv2d(Image,conv1_W)+conv1_b)#卷积核+偏置值+relu
#tf.nn.relu()函数是将大于0的数保持不变,小于0的数置为0
#即判断  conv2d(Image,conv1_W)+conv1_b  是否>0

conv1_out=maxpooling(conv1_h)#调用函数,每2*2取max

#第二个卷积层
conv2_W=weight_value([5,5,32,64])
#两个5代表卷积核的大小为5*5
#32代表经conv1处理后的通道数(与上一层的32对应)
#64代表经本层后会生成的通道数

conv2_b=biase_value([64])# 因为生成了64个通道
conv2_h=tf.nn.relu(conv2d(conv1_out,conv2_W)+conv2_b)
conv2_out=maxpooling(conv2_h)


#全连接层的定义
fcnn_in=tf.reshape(conv2_out,[-1,49*64])#把第二个卷积层的输出拉开成49*64的一排
#疑问:为什么可以拉成49*64啊,原来只有4*4*64啊

fcnn1_W=weight_value([49*64,49*64])#卷积核大小为(49*64)*(49*64)
fcnn1_b=biase_value([49*64])#随机生成偏置值

fcnn1_out=tf.nn.relu(tf.matmul(fcnn_in,fcnn1_W)+fcnn1_b)
#防止过拟合Dropout就是在不同的训练过程中随机扔掉一部分神经元。
#也就是让某个神经元的激活值以一定的概率p,停止工作
#这次训练过程中不更新权值,也不参加神经网络的计算。
#但是它的权重得保留下来(只是暂时不更新而已),因为下次样本输入时它可能又得工作了

fcnn1_dropout=tf.nn.dropout(fcnn1_out,keep_prob)

#输出10个分类,0-9
fcnn2_W=weight_value([49*64,10])
fcnn2_b=biase_value([10])

#进行分类,计算概率-使用softmax算法计算概率,两个矩阵中对应元素各自相乘
prediction=tf.nn.softmax(tf.matmul(fcnn1_dropout,fcnn2_W)+fcnn2_b)

#采用交叉熵做目标函数,交叉熵就是用来判定实际的输出与期望的输出的接近程度!
#reduce_sum应该理解为压缩求和,用于降维
cross_entropy=-tf.reduce_sum(ys*tf.log(prediction))

#精确度计算
num=tf.equal(tf.argmax(prediction,1),tf.argmax(ys,1))
accurate=tf.reduce_mean(tf.cast(num,tf.float32))

#------------3 正式开始训练模型------------#

#定义训练函数
#使用Adam 算法 梯度下降优化器,最小化交叉熵
train_step=tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

 
sess=tf.Session()#上下文管理器
sess.run(tf.initialize_all_variables())# 激活神经网络  初始化所有的参数
 
for step in range(2000):
    batch_x,batch_y=mnist.train.next_batch(100)
    sess.run(train_step,feed_dict={xs:batch_x,ys:batch_y,keep_prob:0.5})#dropout 随机率为0.5
    if step%50==0:
        #每迭代50步输出在测试集上的精确度,应该会越来越准确
        print(sess.run(accurate,feed_dict={xs:mnist.test.images,ys:mnist.test.labels,keep_prob:1.0}))

运行结果:

0.0643
0.8212
0.8974
0.924
0.9325
0.9436
0.9471
0.9512
0.9552
0.959
0.96
0.9629
0.9664
0.9649
0.9679
0.967
0.9715
0.9709
0.9741
0.9726
0.9745
0.975
0.9773
0.977
0.9772
0.9782
0.9785
0.9795
0.9797
0.9801
0.9798
0.9803
0.9814
0.9806
0.9801
0.9804
0.9818
0.9823
0.9821
0.9808

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值