用TensorFlow搭建卷积神经网络识别数字图片

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

data_from_file=input_data.read_data_sets('MNIST_data',one_hot=True)

batch_size=100
n_batch=data_from_file.train.num_examples//batch_size

def weight_init(shape_value):
    '''
    tf.truncated_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None)
    shape: 输出数据的shape
    mean: 正态分布的均值
    stddev: 正态分布的标准差
    dtype: 输出数据的类型
    seed: 一个整数,当赋值后,每次生成的随机数相同
    name: 赋予该操作一个名字
    '''
    return tf.Variable(tf.truncated_normal(shape_value,stddev=0.1))

def bias_init(shape_value):
    return tf.constant(0,shape=shape_value,dtype=tf.float32)#注意是先赋值再指定shape

def conv2d_func(X,W):
    '''
    tf.nn.con2d(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: 是否使用cudnn加速,默认为True, NVIDIA cuDNN是一个GPU加速深层神经网络原语库。
    name: 指定该操作的名称
    via: http://www.cnblogs.com/welhzh/p/6607581.html
    '''
    return tf.nn.conv2d(X,W,strides=[1,1,1,1],padding='SAME')

def max_pool_func(X):
    '''
    tf.nn.max_pool(value, ksize, strides, padding, name=None)
    value: 需要池化的输入,一般池化层接在卷积层后面,所以输入通常是feature map,依然是[batch, height, width, channels]这样的shape
    ksize: 池化窗口的大小,取一个四维向量,一般是[1, height, width, 1],因为我们不想在batch和channels上做池化,所以这两个维度设为了1 ([1,x,y,1])
    strides: 和卷积类似,窗口在每一个维度上滑动的步长,一般也是[1, stride,stride, 1]
    padding: 和卷积类似,可以取'VALID' 或者'SAME'
    name: 指定该操作的名称
    via: https://blog.csdn.net/coder_xiaohui/article/details/78025379
    '''
    return tf.nn.max_pool(X,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')

X=tf.placeholder(tf.float32,[None,784])
y=tf.placeholder(tf.float32,[None,10])

X_4d=tf.reshape(X,[-1,28,28,1])

W_conv1=weight_init([5,5,1,32])#采样窗口是5*5的,32个卷积核从1个平面抽取特征
b_conv1=bias_init([32])#每一个卷积核一个偏置值

h_conv1=tf.nn.relu(conv2d_func(X_4d,W_conv1)+b_conv1)
h_pool1=max_pool_func(h_conv1)

W_conv2=weight_init([5,5,32,64])#采样窗口是5*5的,64个卷积核从32个平面抽取特征
b_conv2=bias_init([64])

h_conv2=tf.nn.relu(conv2d_func(h_pool1,W_conv2)+b_conv2)
h_pool2=max_pool_func(h_conv2)

'''
28*28的图片第1次卷积时还是28*28
第1次池化时变为14*14
第2次卷积时还是14*14
第2次池化时变为7*7
'''
W_full1=weight_init([7*7*64,1024])
b_full1=bias_init([1024])

h_flat=tf.reshape(h_pool2,[-1,7*7*64])
h_full1=tf.nn.relu(tf.matmul(h_flat,W_full1)+b_full1)

keep_prob=tf.placeholder(tf.float32)
'''
tf.nn.dropout(x, keep_prob, noise_shape=None, seed=None, name=None)
x: 指输入的数据
keep_prob: drop的概率,没有被drop掉的数将会是原来的1/keep_pred倍
noise_shape: 默认情况下noise_shape与x的shape相同,就是普通的drop,没有约束,即对于每个样本而言被drop的几率时等同的;而当noise_shape某一个轴值为1时,代表按照这一轴来drop,例如如果(3,4,5)是代表(句子数,每个句子的词数,每个词向量的维度),那么(3,4,1)就表示按照词向量来dropout(可以理解为随机跳过某些词)。
seed: 随机种子,数字相同时产生的一组随机数相同,即所有的随机数按照相同的算法生成
name: 指定该操作的名称
via: 关于noise_shape的讲解参考https://spaces.ac.cn/archives/4521
'''
h_drop=tf.nn.dropout(h_full1,keep_prob)

W_full2=weight_init([1024,10])
b_full2=bias_init([10])

prediction=tf.nn.softmax(tf.matmul(h_drop,W_full2)+b_full2)

loss_cross_entropy=tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=y,logits=prediction))#之前总是报错:InvalidArgumentError: Incompatible shapes: [400,10] vs. [100,10]。原因是在第二次卷积时h_pool1写成了h_conv1

train=tf.train.AdamOptimizer(1e-4).minimize(loss_cross_entropy)

accuracy=tf.reduce_mean(tf.cast(tf.equal(tf.argmax(prediction,1),tf.argmax(y,1)),tf.float32))

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for epoch in range(21):
        for batch in range(n_batch):
            X_batch, y_batch=data_from_file.train.next_batch(batch_size)
            sess.run(train,feed_dict={X:X_batch,y:y_batch,keep_prob:0.7})
        acc=sess.run(accuracy,feed_dict={X:data_from_file.test.images,y:data_from_file.test.labels,keep_prob:1.0})
        print('Iteration '+str(epoch)+', accuracy = '+str(acc))

你可能感兴趣的:(用TensorFlow搭建卷积神经网络识别数字图片)