首先书写如下的代码
代码有详细的注释,这里就不一一解释了
#coding=utf-8
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
#引入数据集
mnist=input_data.read_data_sets('MNIST_data',one_hot=True)
#用于输出准确度的函数
def compute_accuary(v_xs,v_ys):
global prediction
y_pre=sess.run(prediction,feed_dict={xs:v_xs,keep_prob:1}) #这里会带入要预测的x_xs参数,使用run方法带动整个由输入到输出的过程,产生预测softmax输出y_pre(都是概率值)
correct_prediction=tf.equal(tf.argmax(y_pre,1),tf.argmax(v_ys,1))#这里每次会获得y_pre和v_ys最大项的索引看是不是相同,相同的话cooe--矩阵对应位置为1
#print 'correct_prediction:'+correct_prediction
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))#根据矩阵中1的比例得到准确率
results=sess.run(accuracy,feed_dict={xs:v_xs,ys:v_ys,keep_prob:1})#用于启动上面的计算过程
return results
#初始化权重量
def weight_variable(shape):
#truncated_normal用于从截断的正太分布中输出随机值 stddev是标准差 shape是一维的张量
initial=tf.truncated_normal(shape,stddev=0.1)
return tf.Variable(initial)
def bias_variable(shape):
#如前面定义一般神经网络中初始一个值
initial=tf.constant(0.1,shape=shape)
return tf.Variable(initial)
def conv2d(x,W):
#定义一个卷积操作 莫烦这里进行卷积操作时层大小是不发生变化的,估计是因为设置了SAME的原因
#第一个参数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, 每步这里水平,竖直都是夸的1步
# 第四个参数padding:string类型的量,只能是"SAME", "VALID" 其中之一,这个值决定了不同的卷积方式 VALID是小于等于方式的抽取,SAME是大于等于抽取,不足的地方用0进行填充,能保留更多信息
return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME')
def max_pool_2x2(x):
#一个池化操作
# 第一个参数value:需要池化的输入,一般池化层接在卷积层后面,所以输入通常是feature map,依然是[batch, height,width, channels]这样的shape
# 第二个参数ksize:池化窗口的大小,取一个四维向量,一般是[1, height, width, 1],因为我们不想在batch(批)和channels(通道)上做池化,所以这两个维度设为了1
# 第三个参数strides:和卷积类似,窗口在每一个维度上滑动的步长,一般也是[1, stride, stride, 1]
# 第四个参数padding:和卷积类似,可以取'VALID'或者'SAME'返回一个Tensor,类型不变,shape仍然是[batch, height,width, channels]这种形式
return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
#定义用于保存数据的占位符placeholder None是指维度 默认是一维
xs=tf.placeholder(tf.float32,[None,784])#28*28 这是单通道上的
ys=tf.placeholder(tf.float32,[None,10])
keep_prob=tf.placeholder(tf.float32) #这里定义占位符是后面 进行dropout时的比例
x_image=tf.reshape(xs,[-1,28,28,1])# 指定图像信息的形式 -1是指指定先不管图像维度n_samples, 1是channel因为这是黑白的指定1就行了
##############################定义图结构 图像->卷积层->池化层->卷积层->池化层->全连接层->全连接层#####################
#定义第一个小结构 先卷积再池化
W_conv1=weight_variable([5,5,1,32]) #定义第一个连线上的W,patch大小为5*5,线W的总数很大,输入厚度是1(图像是是1维的),输出是32维对应是32张平铺的图
b_conv1=bias_variable([32])#每个池化层feature map对应一个b偏差值
h_conv1=tf.nn.relu(conv2d(x_image,W_conv1)+b_conv1)#传入参数进行卷积运算 并进行非线性转换 池化层神经元数量:28*28*32
h_pool1=max_pool_2x2(h_conv1)#一次指定窗口的池化 变成14*14*32
#定义第二个小结构 先卷积再池化
W_conv2=weight_variable([5,5,32,64]) #定义第一个连线上的W,patch大小为5*5,线W的总数很大,输入厚度是1(图像是是1维的
b_conv2=bias_variable([64])#每个池化层feature map对应一个b偏差值
h_conv2=tf.nn.relu(conv2d(h_pool1,W_conv2)+b_conv2)#传入参数进行卷积运算 并进行非线性转换 池化层神经元数量:14*14*64
h_pool2=max_pool_2x2(h_conv2)#一次指定窗口的池化 变成7*7*64
#定义第一个全连接层 全连接的方式会先对讲pool结果进行格式重置 之后使用一般的乘法得到目标矩阵
W_fc1=weight_variable([7*7*64,1024]) #因为这是一种全连接的方式,因此这里可以 可以用入神经元数 出神经数这样的方式指定,毕竟最后要构建的W数量是7*7*64*1024
b_fc1=bias_variable([1024])
h_pool2_flat=tf.reshape(h_pool2,[-1,7*7*64]) #先对h_pool进行转换成一维度simple 由64维变成1维 大小7*7*64
h_fc1=tf.nn.relu(tf.matmul(h_pool2_flat,W_fc1)+b_fc1) #矩阵相乘
h_fc1_drop=tf.nn.dropout(h_fc1,keep_prob)
#第二个全连接层
W_fc2=weight_variable([1024,10]) #因为这是一种全连接的方式,因此这里可以 可以用入神经元数 出神经数这样的方式指定,毕竟最后要构建的W数量是7*7*64*1024
b_fc2=bias_variable([10])
prediction=tf.nn.softmax(tf.matmul(h_fc1_drop,W_fc2)+b_fc2) # 使用softmax正好能够转化得到概率
############################################################################################################
#定义损失函数和训练方式
cross_entropy=tf.reduce_mean(-tf.reduce_sum(ys*tf.log(prediction),reduction_indices=[1]))# 定义交叉商reduction_indices指定维度
train_step=tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
sess=tf.Session()
sess.run(tf.global_variables_initializer())
for i in range(1,1000):
print('i:',i)
batch_xs,batch_ys=mnist.train.next_batch(100)
#print 'i:',batch_xs,' ',batch_ys
sess.run(train_step,feed_dict={xs:batch_xs,ys:batch_ys,keep_prob:0.5})
if i%10==0:
print(compute_accuary(mnist.test.images[:1000], mnist.test.labels[:1000]))
可以如下发现伴随着训练的进行,模型在测试机上的准确率如下:
最后模型在训练100000次后结束,最后得分在0.95左右。