用Tensorflow实现简单的CNN分类MNIST数据集

时间:2022-10-27 13:53:33

网络结构

用Tensorflow实现简单的CNN分类MNIST数据集

用Tensorflow实现简单的CNN分类MNIST数据集

除最后一个全连接层(FC2)激励函数是Softmax外,其他各层均为ReLU

测试结果

训练用时约11min(使用了自己笔记本上的垃圾独显NVIDIA 930MX)

训练过程中,训练集上的准确率曲线:

用Tensorflow实现简单的CNN分类MNIST数据集

最终在测试集上的准确率:0.992300

代码

#coding:utf-8

import tensorflow as tf
import tensorflow.examples.tutorials.mnist.input_data as input_data

def train():
    mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

    sess = tf.InteractiveSession()

    def weight_variable(shape,var_name='W'):
        initial=tf.truncated_normal(shape,stddev=0.1)
        return tf.Variable(initial,name=var_name)

    def bias_variable(shape,var_name='b'):
        initial=tf.constant(0.1,shape=shape)
        return  tf.Variable(initial,name=var_name)

    def variable_summaries(var):
        with tf.name_scope('Variable_Summary'):
            mean=tf.reduce_mean(var)
            tf.summary.scalar('Var_mean',mean)
            with tf.name_scope('stddev'):
                stddev=tf.sqrt(tf.reduce_mean(tf.square(var-mean)))
            tf.summary.scalar('stddev',stddev)
            tf.summary.scalar('max',tf.reduce_max(var))
            tf.summary.scalar('min', tf.reduce_min(var))
            tf.summary.histogram('histogram',var)

    def conv2d(x,W): #input tensor is x,the conv weight parameter is W
        return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME')

    def max_pool_2x2(x): #input tensor is x,the max pooling size is 2x2:
        return  tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')

    # Input data and label data
    with tf.name_scope('Input_Data'):
        x_data=tf.placeholder(tf.float32,[None,784],name='x_data')
        y_data=tf.placeholder(tf.float32,[None,10],name='y_data')

    # Conv 1
    with tf.name_scope('Conv_1'):
        x=tf.reshape(x_data,shape=[-1,28,28,1],name='x') #Convert the 784 dim input tensor into 28x28 image
        W_conv1=weight_variable([5,5,1,32],'W_conv1') #5x5 filter x32,in_channel=1,out_channel=32
        b_conv1=bias_variable([32],'b_conv1') #32 biases w.r.t. 32 conv results
        layer_conv1=tf.nn.relu(conv2d(x,W_conv1)+b_conv1)

    # Pool 1
    with tf.name_scope('Pool_1'):
        layer_pool1=max_pool_2x2(layer_conv1)

    # Conv 2
    with tf.name_scope('Conv_2'):
        W_conv2=weight_variable([5,5,32,64],'W_conv2') #5x5 filter x2,in_channel=32,out_channel=64
        b_conv2=bias_variable([64],'b_conv2') #64 biases w.r.t. 64 conv results
        layer_conv2=tf.nn.relu(conv2d(layer_pool1,W_conv2)+b_conv2)

    # Pool 2
    with tf.name_scope('Pool_2'):
        layer_pool2=max_pool_2x2(layer_conv2)

    # Fully Connected Layer 1
    with tf.name_scope('FC_1'):
        W_fc1=weight_variable([7*7*64,1024],var_name='W_fc1') #the weight param of FC_1
        b_fc1=bias_variable([1024],var_name='b_fc1') #the bias param of 1024 FC_1 nodes
        layer_pool2_flat=tf.reshape(layer_pool2,[-1,7*7*64]) #Convert [7,7,64] size tensor into a 7*7*64 tensor
        layer_fc1=tf.nn.relu(tf.matmul(layer_pool2_flat,W_fc1)+b_fc1)
        # Dropout of FC1
        with tf.name_scope('Dropout'):
            keep_prob=tf.placeholder(tf.float32,name='keep_prob')
            layer_fc1_dropout=tf.nn.dropout(layer_fc1,keep_prob,name='fc1_dropout')

    # Fully Connected Layer 2
    with tf.name_scope('FC_2'):
        W_fc2=weight_variable([1024,10],var_name='W_fc2') #the weight param of FC_2
        b_fc2=bias_variable([10],var_name='b_fc2') #the bias param of 10 FC_2 nodes
        y=tf.nn.softmax(tf.matmul(layer_fc1_dropout,W_fc2)+b_fc2)

    with tf.name_scope('Optimizer'):
        cross_entropy=-tf.reduce_sum(y_data*tf.log(y),name='cross_entropy_error')
        train_step=tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

    with tf.name_scope('Accuracy'):
        correct_prediction = tf.equal(tf.argmax(y_data, 1), tf.argmax(y, 1))
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32),name='accuracy')

    train_writer = tf.summary.FileWriter('E:/code/python/mnist_cnn_logs', sess.graph)
    test_writer = tf.summary.FileWriter('E:/code/python/mnist_cnn_logs')

    tf.summary.scalar('Accuracy',accuracy)
    merged = tf.summary.merge_all()

    # Before training, initialize all variables
    sess.run(tf.initialize_all_variables())

    # The procedure of training
    for iter in range(20000):
        x_batch,y_batch=mnist.train.next_batch(50) #batch size=50
        train_step.run(feed_dict={x_data: x_batch, y_data:y_batch,keep_prob:0.5})
        print("Iteration: %d\n"%iter)


        if(iter%100==0):
            #train_accuracy = accuracy.eval(session=sess,feed_dict={x_data: x_batch, y_data: y_batch, keep_prob: 1.0})
            train_accuracy,result=sess.run([accuracy,merged],feed_dict={x_data: x_batch, y_data: y_batch, keep_prob: 1.0})
            print("Train accuracy: %lf\n" % train_accuracy)
            train_writer.add_summary(result,iter)

    test_accuracy=0

    for id in range(0,200):
        x_tmp=mnist.test.images[id*50:(id+1)*50,0:784]
        y_tmp=mnist.test.labels[id*50:(id+1)*50,0:10]
        test_accuracy += accuracy.eval(session=sess,
                                  feed_dict={x_data: x_tmp, y_data: y_tmp,
                                             keep_prob: 1.0})
    test_accuracy/=200
    print("Test accuracy: %lf\n" % test_accuracy)

    train_writer.close();
    test_writer.close();

if __name__ == '__main__':
    train()