TensorFlow学习之MNIST实例

以下展示用两只不同的框架实现mnist手写数字识别

(一)利用cnn架构实现:

#EX02用卷积是实现mnist的例子
# -*- coding: utf-8 -*- 

import tensorflow as tf

#导入input_data用于自动下载和安装MNIST数据集
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

#创建一个交互式Session
sess = tf.InteractiveSession()

#创建两个占位符,x为输入网络的图像,y_为输入网络的图像类别
x = tf.placeholder("float", shape=[None, 784])
y_ = tf.placeholder("float", shape=[None, 10])

#权重初始化函数
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)

#创建卷积op
#x 是一个4维张量,shape为[batch,height,width,channels]
#卷积核移动步长为1。填充类型为SAME,可以不丢弃任何像素点
def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1,1,1,1], padding="SAME")

#创建池化op
#采用最大池化,也就是取窗口中的最大值作为结果
#x 是一个4维张量,shape为[batch,height,width,channels]
#ksize表示pool窗口大小为2x2,也就是高2,宽2
#strides,表示在height和width维度上的步长都为2
def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1,2,2,1],
                          strides=[1,2,2,1], padding="SAME")


#第1层,卷积层
#初始化W为[5,5,1,32]的张量,表示卷积核大小为5*5,第一层网络的输入和输出神经元个数分别为1和32
W_conv1 = weight_variable([5,5,1,32])
#初始化b为[32],即输出大小
b_conv1 = bias_variable([32])

#把输入x(二维张量,shape为[batch, 784])变成4d的x_image,x_image的shape应该是[batch,28,28,1]
#-1表示自动推测这个维度的size
x_image = tf.reshape(x, [-1,28,28,1])

#把x_image和权重进行卷积,加上偏置项,然后应用ReLU激活函数,最后进行max_pooling
#h_pool1的输出即为第一层网络输出,shape为[batch,14,14,1]
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

#第2层,卷积层
#卷积核大小依然是5*5,这层的输入和输出神经元个数为32和64
W_conv2 = weight_variable([5,5,32,64])
b_conv2 = weight_variable([64])

#h_pool2即为第二层网络输出,shape为[batch,7,7,1]
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

#第3层, 全连接层
#这层是拥有1024个神经元的全连接层
#W的第1维size为7*7*64,7*7是h_pool2输出的size,64是第2层输出神经元个数
W_fc1 = weight_variable([7*7*64, 1024])
b_fc1 = bias_variable([1024])

#计算前需要把第2层的输出reshape成[batch, 7*7*64]的张量
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层
#为了减少过拟合,在输出层前加入dropout
keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

#输出层
#最后,添加一个softmax层
#可以理解为另一个全连接层,只不过输出时使用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 = -tf.reduce_sum(y_ * tf.log(y_conv))

#train op, 使用ADAM优化器来做梯度下降。学习率为0.0001
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

#评估模型,tf.argmax能给出某个tensor对象在某一维上数据最大值的索引。
#因为标签是由0,1组成了one-hot vector,返回的索引就是数值为1的位置
correct_predict = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))

#计算正确预测项的比例,因为tf.equal返回的是布尔值,
#使用tf.cast把布尔值转换成浮点数,然后用tf.reduce_mean求平均值
accuracy = tf.reduce_mean(tf.cast(correct_predict, "float"))

#初始化变量
sess.run(tf.initialize_all_variables())

#开始训练模型,循环20000次,每次随机从训练集中抓取50幅图像
for i in range(20000):
    batch = mnist.train.next_batch(50)
    if i%100 == 0:
        #每100次输出一次日志
        train_accuracy = accuracy.eval(feed_dict={
            x:batch[0], y_:batch[1], keep_prob:1.0})
        print ('step %d, training accuracy is %g '% (i, train_accuracy))

    train_step.run(feed_dict={x:batch[0], y_:batch[1], keep_prob:0.5})

print ("test accuracy %g" % accuracy.eval(feed_dict={
x:mnist.test.images, y_:mnist.test.labels, keep_prob:1.0}))

结果为:

Extracting MNIST_data/train-images-idx3-ubyte.gz
Extracting MNIST_data/train-labels-idx1-ubyte.gz
Extracting MNIST_data/t10k-images-idx3-ubyte.gz
Successfully downloaded t10k-labels-idx1-ubyte.gz 4542 bytes.
Extracting MNIST_data/t10k-labels-idx1-ubyte.gz

step 0, training accuracy is 0.18 
step 100, training accuracy is 0.84 
step 200, training accuracy is 0.94 
step 300, training accuracy is 0.94 
step 400, training accuracy is 0.96 
step 500, training accuracy is 0.94 
step 600, training accuracy is 0.96 
step 700, training accuracy is 0.94 
step 800, training accuracy is 0.98 
step 900, training accuracy is 0.98 
step 1000, training accuracy is 0.94 
step 1100, training accuracy is 0.98 
step 1200, training accuracy is 1 
step 1300, training accuracy is 0.96 
step 1400, training accuracy is 0.92 
step 1500, training accuracy is 0.96 
step 1600, training accuracy is 0.98 
step 1700, training accuracy is 1 
step 1800, training accuracy is 1 
step 1900, training accuracy is 0.98 
step 2000, training accuracy is 1 
step 2100, training accuracy is 0.96 
step 2200, training accuracy is 0.96 
step 2300, training accuracy is 0.98 
step 2400, training accuracy is 1 
step 2500, training accuracy is 0.94 
step 2600, training accuracy is 1 
step 2700, training accuracy is 0.98 
step 2800, training accuracy is 0.98 
step 2900, training accuracy is 0.98 
step 3000, training accuracy is 0.92 
……

利用cnn架构实现,效果非常好,在此过程中,甚至有些训练结果能达到准确率为1.但是由于时间问题,我在中间手动停止了该程序的运行。crtl+c:停止运行当前程序。

(二)该程序为一个基础的神经网络架构,没有利用cnn结构,只是在此加入了学习率、正则化项、滑动平均模型等进行优化。

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
#step1 定义相关常数的值
#minst数据集相关常数
INPUT_NODE=784 #输入节点数,即输入vector的维数(28*28=784)
OUTPUT_NODE=10 #输出节点数,手写数字识别,结果为0-9的数字,即为10维的vector,每维上的值为0或者1
LAYER1_NODE=500 #隐藏层的units数
BATCH_SIZE=100  #每100个样本进行batch处理
LEARNING_RATE_BASE=0.8 #初始学习率
LEARNING_RATE_DEACY=0.99 #学习率的衰减率
REGULARIZATION_RATE=0.0001 #损失函数中加入正则项时其前面的系数
TRAINING_STEPS=3000    #训练轮数,共训练30000次
MOVING_AVERAGE_DEACY=0.99 #滑动平均模型中的衰减率

#step2 设置辅助函数(前向传播)
#以下定义一个辅助函数,需输入相应参数,在此部分定义神经网络的前向传播过程,并返回结果
#在此部分,引入一个判断是否运用滑动平均模型的条件语句
def inference(input_tensor,avg_class,weights1,biases1,weights2,biases2):
    if avg_class==None:  #当没有提供滑动平均类时,直接使用当前的参数
        layer1=tf.nn.relu(tf.matmul(input_tensor,weights1)+biases1)
        return tf.matmul(layer1,weights2)+biases2#在此不需要激活函数,并且不加入softmax函数也不会影响最终的结果
    else:
        layer1=tf.nn.relu(tf.matmul(input_tensor,avg_class.average(weights1))+avg_class.average(biases1))
        return tf.matmul(layer1,avg_class.average(weights2))+avg_class.average(biases2)
        #在此使用avg_class.average()函数来计算得出变量的滑动平均值

#step3 定义训练模型的过程
#(包括先设置变量和初始参数,再执行前向传播和反向传播-交叉熵、正则化、学习率、优化算法)
def scope():
    def train(mnist):
        global x
        x=tf.placeholder(tf.float32,[None,INPUT_NODE],name='x-input')
        global y_
        y_=tf.placeholder(tf.float32,[None,OUTPUT_NODE],name='y-input')
        #生成隐藏层的参数
        weights1=tf.Variable(tf.truncated_normal([INPUT_NODE,OUTPUT_NODE],stddev=0.1))#给权重w1初试化一个随机生成的正太分布值,其均值为0,方差为0.1
        biases1=tf.Variable(tf.constant(0.1,shape=[OUTPUT_NODE]))
        #生成输出层的参数
        weights2=tf.Variable(tf.truncated_normal([INPUT_NODE,LAYER1_NODE],stddev=0.1))#给权重w1初试化一个随机生成的正太分布值,其均值为0,方差为0.1
        biases2=tf.Variable(tf.constant(0.1,shape=[LAYER1_NODE]))
    
        #计算当前参数下的神经网络前向传播的结果,在此定义不提供滑动平均模型
        y=inference(x,None,weights1,biases1,weights2,biases2)
        #定义存储训练轮数的变量
        global global_step
        global_step=tf.Variable(0,trainable=False)
    
        #在此部分给定滑动平均衰减率和训练轮数的变量,初始化滑动平均类;给定训练轮数的变量可以加快训练早期变量的更新速度
        variable_averages=tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DEACY,global_step)
        #在所有代表神经网络参数的变量上使用滑动平均,
        global variables_averages_op
        variables_averages_op=variable_averages.apply(tf.trainable_variables())
        #在此区别于前面没有使用滑动平均模型,自此计算的是利用了滑动平均过后的前向传播结果
        global average_y
        average_y=inference(x,variable_averages,weights1,biases1,weights2,biases2)
    
       #计算交叉熵 作为刻画预测值和真实值之间的差距的损失函数,这里使用tensorflow中提到的
       #sparse_softmax_cross_entropy_with_logits函数计算交叉熵。当分类问题中仅有一个
       #正确答案时,可以使用这个函数来加速交叉熵的计算。MNIST问题的图片中只包含0-9中的一个数字,所以可以使用
       #这个函数来计算交叉熵损失函数。
       #该函数的第一个参数是神经网络不包括softmax层的前向传播结果,第二个参数是训练数据的正确答案。因为标准答案是一个长度为10的一维数组,
       #而该函数需要提供一个正确答案的数字,则使用tf.argmax函数来得到正确答案的类别编号。
        cross_entropy=tf.nn.sparse_softmax_cross_entropy_with_logits(y,tf.argmax(y_,1))
       #计算在当前batch中所有样例的交叉熵平均值
        cross_entropy_mean=tf.reduce_mean(cross_entropy)
       #计算L2正则化
        regularizer=tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)
        regularization=regularizer(weights1)+regularizer(weights2)#神经网络中的正则化只针对于权重的正则化,偏置项不需要进行正则化
      #总损失等于交叉熵损失和正则化损失的和
        global loss
        loss=cross_entropy_mean+regularization
    
      #设置指数税案件的学习率
        global learning_rate
        learning_rate=tf.train.exponential_deacy(LEARNING_RATE_BASE,#初始学习率,更新变量时在此基础上递减
                                             global_step,       #当前迭代伦次
                                             mnist.train.num_examples/BATCH_SIZE,#过完所有训练样本需要的迭代次数
                                             LEARNING_RATE_DEACY)  #学习率衰减速度
    
#利用优化算法来优化损失函数(此处损失函数包括交叉熵和L2正则化)
train_step=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=global_step)
    
#在训练神经网络模型时,每过一遍数据既需要通过反向传播来更新神经网络中的参数,又要更新每一个参数的滑动平均值,为此,利用以下机制实现一次完成多个操作。
#下面程序和以下等价:train_op=tf.group(train_step,variables_averages_op)
with tf.control_dependencies([train_step,variables_averages_op]):
    train_op=tf.no_op(name='tarin')

#检验使用了滑动平均模型的神经网络前向传播结果是否正确。
correct_prediction=tf.equal(tf.argmax(average_y,1),tf.argmax(y_,1)) #tf.equal()用于判断两个 张量是否相等,其中average_y是预测值,y_是真实值
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))#正确率

                       
#step4 定义完所有的框架后,开始初始化会话,并开始训练。
with tf.Session() as sess:
    tf.initialize_all_variables().run()
    validate_feed={x:mnist.validation.images,y_:mnist.validation.labels}
    test_feed={x:mnist.test.images,y_:mnist.test.labels}
    #开始迭代训练神经网络
    for i in range(TRAINING_STEPS):
        if i%1000==0:#每1000轮输出一次在验证集上的测试结果
            validate_acc=sess.run(accuracy,feed_dict=validate_feed)
            print('After %d training steps,validate accuracy'
                  'using average model is %g' %(i,validate_acc))
            
        #产生这一轮使用的一个batch的训练数据,并运行训练结果
        xs,ys=mnist.train.next_batch(BATCH_SIZE)
        sess.run(train_op,feed_dict={x:xs,y_:ys})
    #在训练结束后,在测试数据集上检测神经网络模型的最终准确率。
    test_acc=sess.run(accuracy,feed_dict=test_feed)
    print('After %d training steps,test accuracy using average'
          'model is %g' % (TRAINING_STEPS,test_acc))
    
#step5 主程序入口
def main(argv=None):
    mnist=input_data.read_data_sets('/tmp/data',one_hot=True)
    train(mnist)
    
#tensorflow提供的一个主程序入口,tf.app.run会调用上面定义的main函数
main(argv=None)

在运行时出现了以下bug:

(1)ModuleNotFoundError: No module named 'tensorflow.examples.tutorials.minst'

将原程序中的开头部分改成如下即可

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) #在此最大的区别是mnist、等号、后面的三者间用一个空格隔开;不知道这样理解,有没有问题,但我发现的不同之处在于此。
(2)  
  train_step=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=global_step)
NameError: name 'learning_rate' is not define
该错误是因为我定义的某个局部变量在某个函数中,但又想在该函数的外部使用它,即想把它转成全局变量使用(局部变量转全局变量)

解决方案链接:https://www.zhihu.com/question/68459368

                       http://www.cnblogs.com/snake-hand/archive/2013/06/16/3138866.html

                       https://blog.csdn.net/sxb0841901116/article/details/23400249

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值