CNN实现手写0-9数字识别

CNN实现手写识别

本个网络,使用2个卷积层,两个全连接层,卷积层使用的激活函数是relu函数,第一层全连接层使用relu函数进行激活,第二层神经网络使用softmax函数激活。
先把代码贴上来

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist=input_data.read_data_sets("abc",one_hot=True)

X=tf.placeholder(dtype=tf.float32,shape=[None,784])
Y=tf.placeholder(dtype=tf.float32,shape=[None,10])

#Conv1
W_conv1=tf.Variable(tf.truncated_normal(shape=[5, 5, 1, 32],stddev=0.1))
X_image=tf.reshape(X,shape=[-1,28,28,1])

h_conv1=tf.nn.relu(tf.nn.conv2d(X_image,W_conv1,strides=[1, 1, 1, 1],padding="SAME"))
h_pool1=tf.nn.max_pool(h_conv1, ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1], padding='SAME')

#Conv2
W_Conv2=tf.Variable(tf.truncated_normal(shape=[5, 5, 32, 64],stddev=0.1))
h_conv2=tf.nn.relu(tf.nn.conv2d(h_pool1,W_Conv2,strides=[1, 1, 1, 1],padding="SAME"))
h_pool2=tf.nn.max_pool(h_conv2, ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1], padding='SAME')

#DenseLayer1
W_fc1=tf.Variable(tf.truncated_normal(shape=[7 * 7 * 64, 1024],stddev=0.1))
h_pool2=tf.reshape(h_pool2,shape=[-1,7*7*64])
h_fc1=tf.nn.relu(tf.matmul(h_pool2,W_fc1))

#预防过拟合 dropout
keep_drop=tf.placeholder(dtype=tf.float32)
h_fc1_drop=tf.nn.dropout(h_fc1,keep_prob=keep_drop)

#DenseLayer2
W_fc2=tf.Variable(tf.truncated_normal(shape=[1024,10],stddev=0.1))
h_fc2=tf.nn.softmax(tf.matmul(h_fc1_drop,W_fc2))

cross_entropy = -tf.reduce_sum(Y * tf.log(h_fc2))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

correct_prediction = tf.equal(tf.argmax(h_fc2, 1), tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "double"))

init=tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    for i in range(10000):
        batch_xs,batch_ys=mnist.train.next_batch(100)
        sess.run(train_step,feed_dict={X:batch_xs,Y:batch_ys,keep_drop:0.5})
        if i % 100 == 0:
            train_accuracy = sess.run(accuracy,feed_dict={X: batch_xs, Y: batch_ys, keep_drop: 1.0})
            print("step %d, training accuracy %f" % (i, train_accuracy))

数据集
我们使用的还是tensorflow自带的mnist数据集。
损失函数
交叉熵 -y*log(y_)
y代表标签里面的值,y_代表预测的值。
优化器``
使用的AdamOptimizer()优化器
与以往的不同
这次网络中需要知道一些过拟合的知识,以及如何预防过拟合,正则化是什么意思。
主要函数
tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, name=None)

第一个参数input:指需要做卷积的输入图像,它要求是一个Tensor,具有[batch, in_height, in_width, in_channels]这样的shape,具体含义是[训练时一个batch的图片数量, 图片高度, 图片宽度, 图像通道数],注意这是一个4维的Tensor,要求类型为float32和float64其中之一

第二个参数filter:相当于CNN中的卷积核,它要求是一个Tensor,具有[filter_height, filter_width,
in_channels,
out_channels]这样的shape,具体含义是[卷积核的高度,卷积核的宽度,图像通道数,卷积核个数],要求类型与参数input相同,有一个地方需要注意,第三维in_channels,就是参数input的第四维

第三个参数strides:卷积时在图像每一维的步长,这是一个一维的向量,长度4

第四个参数padding:string类型的量,只能是"SAME","VALID"其中之一,这个值决定了不同的卷积方式(后面会介绍)

第五个参数:use_cudnn_on_gpu:bool类型,是否使用cudnn加速,默认为true

结果返回一个Tensor,这个输出,就是我们常说的feature map,shape仍然是[batch, height, width,
channels]这种形式。

padding有两个不同的值,“SAME”,"Vaild”,简单来说,在stride下,图片可能不是那么正好够个整的步伐,SAME就是在添0,使得信息不丢,Vaild就是丢弃部分信息。
在filter的参数里面out_channels代表着你输出多少张feature map,in_channels和上一层的输出有关,比如我的W_conv1我的in_channels就是1,因为我的input就是一个二维的图片,但是我的W_conv2的in_channels就是32,因为我的第一层卷积层输出32张特征图吗,所以我的图片在进过两级卷积层后就是变成64张特征图。
我在定义全连接的第一层的时候我的矩阵维度是[7 * 7 * 64, 1024],代表我是一个拥有1024个神经单元的全连接,它连接的是64张7*7的feature map。。
还有一点,在tf.reshape()中,在某一维度的大小上面我写到-1,其实它的维度并不是-1,这个的意思是指计算得到的大小。
比如x.shape=[1024,1]
y.shape=tf.reshape(x,[-1,512])
这样的话-1就是代表2. y.shape=[2,512]

经过第一层Conv卷积后,输出28x28的feature map 32张。
经过pool层后变成14x14的feature map 32张

经过第二层Conv卷积后,输出14x14的feature map 64张。
经过pool层后变成7x7的feature map 64张

tf.nn.dropout
这个函数是实现正则化的意思,在深度学习中,可能出现过拟合现象,简单来说就是拟合的函数太好了,但是这样拟合的太好的函数不能泛化,可能只能在本数据集中有出色表现,换个数据集就不行了。
所以在我的代码里面,我使用正则化去防止过拟合,简单来说,就是随机消去几个神经元,让全连接网络的参数少点,这样的话变可以预防过拟合。

你可能感兴趣的:(深度学习)