TensorFlow实现MNIST的卷积神经网络

在此篇博客中我们将学习使用TensorFlow搭建一个卷积神经网络(CNN)模型,并使用它来训练MNIST数据集。

构建一个CNN模型需要以下几个步骤:

(1) 定义输入数据,并预处理数据。这里我们首先读取MNIST数据集,并分别得到训练集的图片和标签的矩阵,以及测试集的图片和标签矩阵。代码如下:

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)
trX,trY,teX,teY=mnist.train.images,mnist.train.labels,mnist.test.images,mnist.test.labels

接着需要对数据进行处理,我们要把trX和trY的shape变成[-1,28,28,1]这里-1表示不需要考虑输入图像的数量,28×28是图像的长宽像素值,1表示图像的通道数(这里是黑白图像所以为1通道)。代码如下:

trX=trX.reshape(-1,28,28,1)
teX=teX.reshape(-1,28,28,1)

X=tf.placeholder('float',[None,28,28,1])
Y=tf.placeholder('float',[None,10])

(2) 初始化权重与定义网络。这里我们将搭建一个拥有3个卷基层和三个池化层,随后接1个全连接层和1个输出层的卷积神经网络。代码如下:

#定义权重函数
def init_weights(shape):
    return(tf.Variable(tf.random_normal(shape,stddev=0.01)))
#初始化权重
w=init_weights([3,3,1,32])#patch大小为3*3,输入维度1,输出维度32
w2=init_weights([3,3,32,64])#patch大小为3*3,输入维度32,输出维度64
w3=init_weights([3,3,64,128])#patch大小为3*3,输入维度64,输出维度128
w4=init_weights([128*4*4,625])#全连接层,输入128*4*4,是上一层输出数据三维转变为1维,输出维度625
w_o=init_weights([625,10])#输出层,输入维度625,输出维度10(表示10类)

#定义神经网络
def model(X,w,w2,w3,w4,w_o,p_keep_conv,p_keep_hidden):
    #定义第一组卷积层和池化层,最后dropout掉一些神经元
    l1a=tf.nn.relu(tf.nn.conv2d(X,w,strides=[1,1,1,1],padding='SAME'))
    l1=tf.nn.max_pool(l1a,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
    l1=tf.nn.dropout(l1,p_keep_conv)
    
    #定义第二组卷积层和池化层,最后dropout掉一些神经元
    l2a=tf.nn.relu(tf.nn.conv2d(l1,w2,strides=[1,1,1,1],padding='SAME'))
    l2=tf.nn.max_pool(l2a,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
    l2=tf.nn.dropout(l2,p_keep_conv)
    
    #定义第三组卷积层和池化层,最后dropout掉一些神经元
    l3a=tf.nn.relu(tf.nn.conv2d(l2,w3,strides=[1,1,1,1],padding='SAME'))
    l3=tf.nn.max_pool(l3a,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
    l3=tf.reshape(l3,[-1,w4.get_shape().as_list()[0]])
    l3=tf.nn.dropout(l3,p_keep_conv)
    
    #全连接层,最后dropout掉一些神经元
    l4=tf.nn.relu(tf.matmul(l3,w4))
    l4=tf.nn.dropout(l4,p_keep_hidden)
    
    #输出层
    pyx=tf.matmul(l4,w_o)
    return(pyx)

我们接下来定义dropout的占位符——keep_conv和keep_hidden,它表示一层中有多少比例的神经元被留下来,这个东西可以有效的避免过拟合问题。然后利用定义的model生成网络模型得到预测值,代码如下:

p_keep_conv=tf.placeholder('float')
p_keep_hidden=tf.placeholder('float')
py_x=model(X,w,w2,w3,w4,w_o,p_keep_conv,p_keep_hidden)

接下来定义损失函数,这里采用tf.nn.softmax_cross_entropy_with_logits来比较预测值和真值的差异,并做均值处理。定义训练操作(train_op),这里采用RMProp算法的优化器tf.train.RMSPropOptimizer,学习率为0.001,衰减值为0.9,使损失减小,代码如下:

cost=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=py_x,labels=Y))
train_op=tf.train.RMSPropOptimizer(0.001,0.9).minimize(cost)
predict_op=tf.argmax(py_x,1)

(3) 训练模型和评估模型

#定义训练和测试时的批次
batch_size=128
test_size=256

#在会话中启动图,开始训练和测试
with tf.Session() as sess:
    tf.global_variables_initializer().run()
    
    for i in range(100):
        training_batch=zip(range(0,len(trX),batch_size),
                           range(batch_size,len(trX)+1,batch_size))
        for star,end in training_batch:
            sess.run(train_op,feed_dict={X:trX[star:end],Y:trY[star:end],
                                         p_keep_conv:0.8,p_keep_hidden:0.5})
        test_indices=np.arange(len(teX))
        np.random.shuffle(test_indices)
        test_indices=test_indices[0:test_size]
            
        print(i,np.mean(np.argmax(teY[test_indices],axis=1)==sess.run(predict_op,feed_dict={X:teX[test_indices],
                                                                                        p_keep_conv:1.0,
                                                                                        p_keep_hidden:1.0})))
    

结果如下(此程序为Python3,如果程序报错可以删除中文注释,有时候Python程序中不允许出现中文注释):

猜你喜欢

转载自blog.csdn.net/qq_38375282/article/details/81436296