MNIST 是Tensoflow提供的一个入门级的计算机视觉数据集,分为两部分(训练集和测试集)
其中训练集共55000张,测试集共10000张,当为None时随机读取
在看这篇文章前,你必须先对神经网络(NN)、MNIST手写数字是什么有初步的了解
关于神经网络,你可能参考 机器学习(1)--神经网络初探
关MNIST手写数字 你可以参考 TensorFlow实例(4)--MNIST简介及手写数字分类算法
下面简单介绍一下卷积神经网络CNN,
图片也是网上流行的图片,我只做了一些简单的修改,
同时我又分出了两篇文章,阐述卷积(Convolution)、最大池化(MaxPooling)
TensorFlow实例(5.2)--MNIST手写数字进阶算法(卷积神经网络CNN) 之 卷积tf.nn.conv2d
TensorFlow实例(5.3)--MNIST手写数字进阶算法(卷积神经网络CNN) 之 最大池化tf.nn.max_pool
特别注意:这两篇文章旨在说明这两条指令数据演变,数据是另外建立,和这篇文章的数据没有任何关系
本例代码分以下几部份
1、初始化数据及设置输入图像模型
2、构建两次卷积、最大池化模型
3、两次全连接模型
4、建立训练、判断正确、统计模型 及 训练与测试
一、初始化数据及设置输入图像模型
# -*- coding:utf-8 -*-
import tensorflow as tf
import tensorflow.examples.tutorials.mnist.input_data as input_data
import random
#读取mnist数据,下载后的Mnist并解压后,放在项目的同级目录下,通过下面程序即可读取
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
#在训练时,None表示从训练集中取得一张图表(x_data),及图表的值(y_data)
#在测试评估模型时,None表示整个测试集合
x_data = tf.placeholder("float", [None, 784])
y_data = tf.placeholder("float", [None,10])
二、构建两次卷积、最大池化模型
如果你对[5,5,1,32],,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME" 这些参数设置不了解
TensorFlow实例(5.2)--MNIST手写数字进阶算法(卷积神经网络CNN) 之 卷积tf.nn.conv2d
TensorFlow实例(5.3)--MNIST手写数字进阶算法(卷积神经网络CNN) 之 最大池化tf.nn.max_pool
以下对指令做些简述
tf.reshape(x_data,[-1,28,28,1]) 将 图像转为了28*28二维数组,第一维的-1为batch相当于x_data中的None, 第四维的1表示1通道
tf.nn.conv2d ,卷积,卷积后将变为 batch * 28 * 28 * 32 通道 的数组
tf.nn.relu 你可以简单的理解为,对于数组中-1的值设为0,
tf.nn.max_pool 最大池化,ksize=[1,2,2,1],strides=[1,2,2,1] 简单的说图像变一半大
两次的卷积,
第一次以图像输入 28*28*1通道 ,以 14*14*32通道 输出
第二次以第一次的图输出 14*14*32 通道 为输入, 以 7*7*64通道 输出
#第一层卷积与最大池化
w1 = tf.Variable(tf.truncated_normal([5,5,1,32],stddev=0.1)) #建立权重weight
b1 = tf.Variable(tf.constant(0.1,shape=[32]))
h1 = tf.nn.relu(tf.nn.conv2d(tf.reshape(x_data,[-1,28,28,1]) ,w1,strides=[1,1,1,1],padding="SAME") + b1)
p1 = tf.nn.max_pool(h1,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME")
#第二层卷积与最大池化
w2 = tf.Variable(tf.truncated_normal([5,5,32,64],stddev=0.1))
b2 = tf.Variable(tf.constant(0.1,shape=[64]))
h2 = tf.nn.relu(tf.nn.conv2d(p1 ,w2,strides=[1,1,1,1],padding="SAME") + b2)
p2 = tf.nn.max_pool(h2,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME")
三、两次全连接模型
两次全连接
第一次,以卷积输出 7*7*64通道 全连接为 连接成为一个一维向量1024个数据,
第二次,以第一次的一维向量1024个元素输入,全连接为10个元素,
10个元素就对应,输出的每一维都是图片y属于该类别的概率。
如果不明白这个10个元素
可以参考 TensorFlow实例(4)--MNIST简介及手写数字分类算法
Dropout作用其在训练阶段阻止神经元的共适应,本文不对这个做细论,有兴趣可以百度一下。
#紧密连接层一
#将第二层max-pooling的输出连接成为一个一维向量,作为该层的输入。
wf1 = tf.Variable(tf.truncated_normal([7 * 7 * 64,1024],stddev=0.1))
bf1 = tf.Variable(tf.constant(0.1,shape=[1024]))
fc1 = tf.nn.relu(tf.matmul(tf.reshape(p2,[-1,7 * 7 * 64]),wf1) + bf1)
keep_prob = tf.placeholder(tf.float32)
fc1_drop = tf.nn.dropout(fc1,keep_prob=keep_prob)
#紧密连接层二
#Softmax层:输出为10,输出的每一维都是图片y属于该类别的概率。
wf2 = tf.Variable(tf.truncated_normal([1024,10],stddev=0.1))
bf2 = tf.Variable(tf.constant(0.1,shape=[10]))
y = tf.nn.softmax(tf.matmul(fc1_drop,wf2) + bf2)
四、建立训练、判断正确、统计模型 及 训练与测试
#建立训练模型
loss = -tf.reduce_sum(y_data * tf.log(y))
train = tf.train.AdamOptimizer(1e-4).minimize(loss)
#建立判断正确与统计模型
correct = tf.equal(tf.argmax(y_data,1),tf.argmax(y,1))#比较训练集中的结果与计算的结果,返回TRUE
accuracy = tf.reduce_mean(tf.cast(correct,tf.float32))#因为correct返回为TRUE,转化为float32的1.0,对传入的整个batch求平均值,即为正确率
#开始训练
sess = tf.Session()
sess.run(tf.initialize_all_variables())
for i in range(250): #在google提供的例子中循环运算是20000次,太慢了,所以我只设置到250
batch = mnist.train.next_batch(50)#每次的运算提取训练集中的50张图片
if i % 50 == 0:
#每50次,调用一次判断正确与统计模型
trainTmp = sess.run(accuracy,feed_dict={x_data:batch[0],y_data:batch[1],keep_prob:1.0})
print("第%d步,正确率:%g" % (i,trainTmp))
#简单说一下keep_prob设置不同,在做判断与统计时,我们不做dropout,所以设1.0,但在训练时我们需要进行dropout,所以设为0.5
sess.run(train,feed_dict={x_data:batch[0],y_data:batch[1],keep_prob:0.5})
#对测试集进行测试
#在google提供的例子是没有[0:50]的,即计算所有测试集的值,还是因为太慢,我就取了前50个
print("前50个测试集的正确率:" + str(sess.run(accuracy,feed_dict={x_data:mnist.test.images[0:50],y_data:mnist.test.labels[0:50],keep_prob:1})))