TensorFlow实现简单卷积神经网络-MNIST手写数字识别

# -*- coding:utf-8 -*-
import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data

#加载数据集
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
# x: 任意数量的MNIST图像,每一张图展平成784维的向量。我们用2维的浮点数张量来表示这些
# 图,这个张量的形状是[None,784 ]。(这里的None表示此张量的第一个维度可以是任何
# 长度 batch取批量的大小 x图片的数量。)

# x = tf.placeholder("float",shape=[None,784])
#
# """
# placeholder,shape
# 参数是可选的,但有了它,TensorFlow能够自动捕捉因数据维度不一致导致的错误。
#
# # 图片设为“xs”,把这些标签设为“ys”
# # softmax模型可以用来给不同的对象分配概率
# """
# W = tf.Variable(tf.zeros([784,10]))  #28*28,0-9
# b = tf.Variable(tf.zeros([10]))   #0-9
#
# #构建模型
# y = tf.nn.softmax(tf.matmul(x,W)+b)  #y的概率
#
# # 训练构建的模型
# # 先定义指标评估模型好坏(指标称为 成本cost,损失loss。小化这个指标)
# # 成本函数“交叉熵”cross-entropy。
# # 计算交叉熵 需要添加新的占位符 y_: 实际分布one-hot [1,0,0,0,0,0,0,0,0,0]  ??
#
# y_ = tf.placeholder("float",[None,10])
#
# #交叉熵
# cross_entropy = -tf.reduce_sum(y_*tf.log(y))
#
# # tf的优化算法,根据交叉熵降低指标(成本,损失)
# # 梯度算法,0.01的学习率不断地最小化交叉熵(指标)
# trian_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
#
# #运行模型前,初始化变量
# init = tf.global_variables_initializer()
#
# #启动init,Session
# sess = tf.Session()
# sess.run(init)
#
# # 训练模型,运行1000次,每次随机抽取100个
# for i in range(1,1000):
#     batch_xs,batch_ys = mnist.train.next_batch(100)
#     sess.run(trian_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}))
#

sess = tf.InteractiveSession()

"""
接下来要实现这个卷积神经网络的权重和偏置,要先定义好初始化函数以便复用。
需要给权重制造一些随机的噪声来打破完全对称,比如:截断的正态分布噪声,标准差为0.1,
使用ReLU,也给偏置增加一些小的正值(0.1)用来避免死亡节点。
"""

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)

"""
卷积层和池化层也是要复用的,因此要创建函数。
tf.nn.conv2d是TF的2维卷积函数,x是输入,W是卷积参数。
[5,5,1,32],5表示卷积核的尺寸,1代表有多个通道channel,因为是灰色所以是1,彩色的事3.
32代表卷积核的数量,也就是这个卷积层会提取多少类的特征。Strides代表卷积模板移动的步长,
都是1代表会不遗漏地划过图片每一个点。Padding代表边界的处理方式,SAME代表给边界加上
Padding让卷积的输出和输入保持同样的SAME的尺寸。
tf.nn.max_pool是TF的最大池化函数,使用2*2的最大池化,即将一个2*2的像素块降维1*1的像素。
因为希望缩小图片尺寸,所以横竖两个方向的步长为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_是真是的label。
"""

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

"""
定义第一层卷积层,先使用前面写好的函数进行参数初始化,然后卷积函数,池化函数
"""
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,也就是这一层会提取64种特征。
"""
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层,通过一个placeholder传入keep_pro比率来控制,在训练的时候,
随机丢弃一部分节点的数据来减轻过拟合,预测的时候则保留全部数据来追求最好的预测性能。
"""
keep_pro = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1,keep_pro)

"""
将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,并使用一个比较小的学习速率1e-4
"""
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y_conv),reduction_indices=[1]))
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,tf.float32))

"""
下面开始训练。首先初始化所以参数,设置训练是的dropout的keep_pro比率为0.5。然后使用大小为50的mini-batch,
共进行20000次训练迭代,参与的训练样本数量共100万。其中每100次训练,会对准备率进行一次;名册
用以实时监测模型的性能。
"""

tf.global_variables_initializer().run()
for i in range(20000):
    batch = mnist.train.next_batch(50)
    if i%100==0:
        train_accuriacy=accuracy.eval(feed_dict={x:batch[0],y_:batch[1],keep_pro:1.0})
        print("step%d,training accuracy %g"%(i,train_accuriacy))
    train_step.run(feed_dict={x:batch[0],y_:batch[1],keep_pro:0.5})

"""
全部训练完成后,最好的测试集进行全面的测试,得到整体的分类准确率。
"""
print("test accuracy %g"%accuracy.eval(feed_dict={x:mnist.test.images,y_:mnist.test.labels,keep_pro:1.0}))

最后的结果准确率达到99%.

利用tensorflow实现卷积神经网络来进行MNIST手写数字图像分类。 #导入numpy模块 import numpy as np #导入tensorflow模块,程序使用tensorflow实现卷积神经网络 import tensorflow as tf #下载mnist数据集,并从mnist_data目录中读取数据 from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets('mnist_data',one_hot=True) #(1)这里的“mnist_data” 是和当前文件相同目录下的一个文件夹。自己先手工建立这个文件夹,然后从https://yann.lecun.com/exdb/mnist/ 下载所需的4个文件(即该网址中第三段“Four files are available on this site:”后面的四个文件),并放到目录MNIST_data下即可。 #(2)MNIST数据集是手写数字字符的数据集。每个样本都是一张28*28像素的灰度手写数字图片。 #(3)one_hot表示独热编码,其值被设为true。在分类问题的数据集标注时,如何不采用独热编码的方式, 类别通常就是一个符号而已,比如说是9。但如果采用独热编码的方式,则每个类表示为一个列表list,共计有10个数值,但只有一个为1,其余均为0。例如,“9”的独热编码可以为[00000 00001]. #定义输入数据x和输出y的形状。函数tf.placeholder的目的是定义输入,可以理解为采用占位符进行占位。 #None这个位置的参数在这里被用于表示样本的个数,而由于样本个数此时具体是多少还无法确定,所以这设为None。而每个输入样本的特征数目是确定的,即为28*28。 input_x = tf.placeholder(tf.float32,[None,28*28])/255 #因为每个像素的取值范围是 0~255 output_y = tf.placeholder(tf.int32,[None,10]) #10表示10个类别 #输入层的输入数据input_x被reshape成四维数据,其中第一维的数据代表了图片数量 input_x_images = tf.reshape(input_x,[-1,28,28,1]) test_x = mnist.test.images[:3000] #读取测试集图片的特征,读取3000个图片 test_y = mnist.test.labels[:3000] #读取测试集图片的标签。就是这3000个图片所对应的标签
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值