# -*- coding:utf-8 -*- 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) # x: 任意数量的MNIST图像,每一张图展平成784维的向量。我们用2维的浮点数张量来表示这些 # 图,这个张量的形状是[None,784 ]。(这里的None表示此张量的第一个维度可以是任何 # 长度 batch取批量的大小 x图片的数量。) # x = tf.placeholder("float",shape=[None,784]) # # """ # placeholder,shape # 参数是可选的,但有了它,TensorFlow能够自动捕捉因数据维度不一致导致的错误。 # # # 图片设为“xs”,把这些标签设为“ys” # # softmax模型可以用来给不同的对象分配概率 # """ # W = tf.Variable(tf.zeros([784,10])) #28*28,0-9 # b = tf.Variable(tf.zeros([10])) #0-9 # # #构建模型 # y = tf.nn.softmax(tf.matmul(x,W)+b) #y的概率 # # # 训练构建的模型 # # 先定义指标评估模型好坏(指标称为 成本cost,损失loss。小化这个指标) # # 成本函数“交叉熵”cross-entropy。 # # 计算交叉熵 需要添加新的占位符 y_: 实际分布one-hot [1,0,0,0,0,0,0,0,0,0] ?? # # y_ = tf.placeholder("float",[None,10]) # # #交叉熵 # cross_entropy = -tf.reduce_sum(y_*tf.log(y)) # # # tf的优化算法,根据交叉熵降低指标(成本,损失) # # 梯度算法,0.01的学习率不断地最小化交叉熵(指标) # trian_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy) # # #运行模型前,初始化变量 # init = tf.global_variables_initializer() # # #启动init,Session # sess = tf.Session() # sess.run(init) # # # 训练模型,运行1000次,每次随机抽取100个 # for i in range(1,1000): # batch_xs,batch_ys = mnist.train.next_batch(100) # sess.run(trian_step,feed_dict={x:batch_xs,y_:batch_ys}) # # #验证正确率 # correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(y_,1)) # accuracy = tf.reduce_mean(tf.cast(correct_prediction,'float')) # print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})) # sess = tf.InteractiveSession() """ 接下来要实现这个卷积神经网络的权重和偏置,要先定义好初始化函数以便复用。 需要给权重制造一些随机的噪声来打破完全对称,比如:截断的正态分布噪声,标准差为0.1, 使用ReLU,也给偏置增加一些小的正值(0.1)用来避免死亡节点。 """ def weight_variable(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) """ 卷积层和池化层也是要复用的,因此要创建函数。 tf.nn.conv2d是TF的2维卷积函数,x是输入,W是卷积参数。 [5,5,1,32],5表示卷积核的尺寸,1代表有多个通道channel,因为是灰色所以是1,彩色的事3. 32代表卷积核的数量,也就是这个卷积层会提取多少类的特征。Strides代表卷积模板移动的步长, 都是1代表会不遗漏地划过图片每一个点。Padding代表边界的处理方式,SAME代表给边界加上 Padding让卷积的输出和输入保持同样的SAME的尺寸。 tf.nn.max_pool是TF的最大池化函数,使用2*2的最大池化,即将一个2*2的像素块降维1*1的像素。 因为希望缩小图片尺寸,所以横竖两个方向的步长为2,如果是1的话,会得到一个尺寸不变的图片。 """ def conv2d(x,W): return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME') def max_pool_2x2(x): return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME') """ 在正式设计卷积神经网络的结构之前,先定义输入的placeholder,x是特征,y_是真是的label。 """ x = tf.placeholder(tf.float32,[None,784]) y_ = tf.placeholder(tf.float32,[None,10]) x_image = tf.reshape(x,[-1,28,28,1]) """ 定义第一层卷积层,先使用前面写好的函数进行参数初始化,然后卷积函数,池化函数 """ W_conv1 = weight_variable([5,5,1,32]) b_conv1 = bias_variable([32]) h_conv1 = tf.nn.relu(conv2d(x_image,W_conv1)+b_conv1) h_pool1 = max_pool_2x2(h_conv1) """ 现在定义第二层,与第一次一样,只是卷积核变成64,也就是这一层会提取64种特征。 """ W_conv2 = weight_variable([5,5,32,64]) b_conv2 = bias_variable([64]) h_conv2 = tf.nn.relu(conv2d(h_pool1,W_conv2)+b_conv2) h_pool2 = max_pool_2x2(h_conv2) """ 前面经历了两次步长为2x2的最大池化,所以边长已经只有1/4,图片尺寸由28x28变成7x7. 而第二个卷积层的卷积核数量是64,其输出的tensor尺寸是7x7x64. 使用tf.reshape函数对第二个卷积层的输出Tensor进行变形,将其准换成1D的向量。。。 然后连接一个全连接层,隐含节点为1024,使用ReLU做激活函数。 """ W_fc1 = weight_variable([7*7*64,1024]) b_fc1 = bias_variable([1024]) h_pool2_flat = tf.reshape(h_pool2,[-1,7*7*64]) h_fc1= tf.nn.relu(tf.matmul(h_pool2_flat,W_fc1)+b_fc1) """ 为了减轻过拟合,使用dropout层,通过一个placeholder传入keep_pro比率来控制,在训练的时候, 随机丢弃一部分节点的数据来减轻过拟合,预测的时候则保留全部数据来追求最好的预测性能。 """ keep_pro = tf.placeholder(tf.float32) h_fc1_drop = tf.nn.dropout(h_fc1,keep_pro) """ 将dropout层的输出连接一个softmax层,得到最后的概率输出。 """ W_fc2 = weight_variable([1024,10]) b_fc2 = bias_variable([10]) y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop,W_fc2)+b_fc2) """ 定义一个损失函数cross entropy ,优化器使用Adam,并使用一个比较小的学习速率1e-4 """ cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y_conv),reduction_indices=[1])) train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy) """ 继续定义评测准确率的操作 """ correct_prediction = tf.equal(tf.argmax(y_conv,1),tf.argmax(y_,1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32)) """ 下面开始训练。首先初始化所以参数,设置训练是的dropout的keep_pro比率为0.5。然后使用大小为50的mini-batch, 共进行20000次训练迭代,参与的训练样本数量共100万。其中每100次训练,会对准备率进行一次;名册 用以实时监测模型的性能。 """ tf.global_variables_initializer().run() for i in range(20000): batch = mnist.train.next_batch(50) if i%100==0: train_accuriacy=accuracy.eval(feed_dict={x:batch[0],y_:batch[1],keep_pro:1.0}) print("step%d,training accuracy %g"%(i,train_accuriacy)) train_step.run(feed_dict={x:batch[0],y_:batch[1],keep_pro:0.5}) """ 全部训练完成后,最好的测试集进行全面的测试,得到整体的分类准确率。 """ print("test accuracy %g"%accuracy.eval(feed_dict={x:mnist.test.images,y_:mnist.test.labels,keep_pro:1.0}))
最后的结果准确率达到99%.