Tensorflow训练MNIST数据集(卷积神经网络)

本文简单介绍了用Tensorflow训练MNIST数据集的卷积神经网络的构建过程。非卷积神经网络的训练见我的上篇博客Tensorflow训练MNIST数据集(由浅层到深层神经网络的构建和调参)

MNIST数据集

由于从官网下载速度较慢,百度网盘下载地址:
链接:https://pan.baidu.com/s/1M8Ldp1WspnjJ7s8xvwT41Q
提取码:42bl

一、数据集的读取与使用

数据集的读取用到的是tensorflow提供的读取MNIST数据集的代码,可以点击链接查看代码input_data.py
由于已经下载好了数据集,加载时直接输入路径即可。

import tensorflow as tf
import input_data
minst = input_data.read_data_sets('D:/huohu/mnist_dataset/mnist_dataset',one_hot = True)

上述是我的数据集的下载路径,此处路径需要按照实际情况做出修改。

二、构建计算图

sess = tf.InteractiveSession()

三、创建占位符

x = tf.placeholder("float",shape=[None,784])
y_ = tf.placeholder("float",shape=[None,10])

注意变量的尺寸,784是输入图片的展平的尺寸,因为输出有10类,所以y_输出尺寸为10。

四、构建模型

卷积神经网络的大致结构如下:
Conv–>Relu–>Pooling–> Conv–>Relu–>Pooling–>Full Connection Layer–>Dropout

1、卷积层

x1 = tf.reshape(x,[-1,28,28,1])
filter1 = tf.Variable(tf.truncated_normal([5,5,1,32],stddev=0.1))
filter2 = tf.Variable(tf.truncated_normal([5,5,32,64],stddev=0.1))
conv1 = tf.nn.conv2d(x1,filter1,strides=[1,1,1,1],padding='SAME')
z1 = tf.nn.relu(conv1)
pool1 = tf.nn.max_pool(z1,[1,2,2,1],[1,2,2,1],padding='SAME')
conv2 = tf.nn.conv2d(pool1,filter2,strides=[1,1,1,1],padding='SAME')
z2 = tf.nn.relu(conv2)
pool2 = tf.nn.max_pool(z2,[1,2,2,1],[1,2,2,1],padding='SAME')

tf.nn.conv2d(input,filter,strides,padding)参数说明

1、input:[batch,in_height,in_width,in_channels]
因为conv2d的输入要求是四维,故代码中第一行要改变x的维度(MNIST数据集中图片大小为28*28,且为灰度图像,所以最后一个参数in_channels为1,若为彩色图像,此参数为3)
2、filter:[height,width,in_channels,out_channels]
filter用来定义卷积核,filter的前两个参数用来定义卷积核的尺寸,第三个参数跟input的第四个参数一致,最后一个参数是卷积核的数量。注意:filter参数是一个变量(Variable),必须被创建和初始化,因为这个变量只定义了卷积核的尺寸,而卷积核中的数字大小应该由初始化得来。
3、strides是窗口在每一个维度上滑动的步长,一般是[1, stride,stride, 1],因为不在batch和in_channels上做卷积。
4、padding有两种参数可以选择:‘VALID’和‘SAME’
取值为‘VALID’时在卷积过程中不会对输入(input)做填充;
取值为‘SAME’时在卷积过程中将会对输入(input)做填充,填充值都是0值,卷积后的输出与输入size保持一致。

tf.nn.max_pool(value, ksize, strides, padding)参数说明
value:需要池化的输入,也是[batch, height, width, channels]这样的shape。同上卷积的input。
ksize:池化窗口的大和卷积类似,窗口在每一个维度上滑动的步长,一般也是[1, stride,stride, 1]小,取一个四维向量,一般是[1, height, width, 1],因为我们不在batch和channels上做池化,所以这两个维度设为了1。
strides:和卷积类似,窗口在每一个维度上滑动的步长,一般也是[1, stride,stride, 1]。
padding:和卷积类似,可以取’VALID’ 或者’SAME’。

2、全连接层

print(pool2)

在做全连接层之前要得到上述代码最后输出的pool2的尺寸,才能得到全连接层参数的尺寸。
现在很多卷积神经网络模型,都用卷积层替代全连接层,就是因为这个原因。因为全连接层的参数的尺寸与输入图像的尺寸有关,故输入图像尺寸改变,模型参数初始化尺寸亦改变。若采用卷积层替代全连接层,则输入图像尺寸改变,模型不用做任何改变。

w = tf.Variable(tf.truncated_normal([7*7*64,1024],stddev=0.1))
b = tf.constant(0.1,shape=[1024])
h_flat = tf.reshape(pool2,[-1,7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_flat,w)+b)

3、Dropout

keep_prob = tf.placeholder("float")
h_drop = tf.nn.dropout(h_fc1,keep_prob)

为了防止模型过拟合,在输出层的前面添加Dropout模块。

4、输出层

w1 = tf.Variable(tf.truncated_normal([1024,10],stddev=0.1))
b1 = tf.constant(0.1,shape=[10])
y_conv = tf.nn.softmax(tf.matmul(h_drop,w1)+b1)

五、训练和评估模型

cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=y_conv,labels=y_))
train_step = tf.train.AdadeltaOptimizer(0.35).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1),tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,"float"))
sess.run(tf.global_variables_initializer())
for i in range(3000):
    batch = minst.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:0.5})

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

注意:只有在训练过程中才用Dropout,在计算准确率时,不使用Dropout。
最终准确率在97.79%左右。

你可能感兴趣的:(Tensorflow)