实战谷歌深度学习框架第二版——第五章5.3变量管理完整代码

将5.2.1节的inference函数重构,在原来的程序里使用变量管理的方式。

from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
from matplotlib.pyplot import plot ,show

#定义输入输出节点数,即与数据集相关的常数
INPUT_NODE = 784  #28*28像素展开为向量
OUTPUT_NODE = 10 #类别总数

#配置神经网络参数
LAYERS1_NODE = 500

BATCH_SIZE = 100
LEARNING_RATE_BASE = 0.8 #初始学习率
LEARNING_RATE_DECAY = 0.99 #学习率的衰减率
REGULARIZATION_RATE = 0.0001 #正则化系数
TRAINING_STEPS = 10000 #训练轮数 epoch
MOVING_AVERAGE_DECAY = 0.99 #滑动平均衰减率

#5.2.1节 原本的inference函数
#定义一个辅助函数,使用Relu激活函数,计算前向传播结果,选择是否使用滑动平均,三层(加上输入层)全连接网络结构
# def inference(input_tensor,avg_class,weights1,biases1,weights2,biases2):
#     if avg_class == None:
#         layer1 = tf.nn.relu(tf.matmul(input_tensor,weights1)+biases1)
#         #这里可以不用softmax层,在计算loss的时候会计算,不影响预测结果,因为相对大小经过softmax后不变。
#         return tf.matmul(layer1,weights2)+biases2
#     else:
#         #首先使用avg_class.average函数计算得出变量的滑动平均然后计算前向传播结果
#         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)

#5.3节改进的inference函数,通过变量管理方式,加上滑动平均类
def inference(input_tensor,avg_class,reuse=False):
    #定义第一层神经网络变量和前向传播
    with tf.variable_scope('layer1',reuse=reuse):
        weights = tf.get_variable("weights",[INPUT_NODE,LAYERS1_NODE],initializer=tf.truncated_normal_initializer(stddev=0.1))
        biases = tf.get_variable('biases',[LAYERS1_NODE],initializer=tf.constant_initializer(0.0))
        if avg_class == None:
            layer1 = tf.nn.relu(tf.matmul(input_tensor,weights)+biases)
        else:
            layer1 = tf.nn.relu(tf.matmul(input_tensor, avg_class.average(weights)) + avg_class.average(biases))
    #定义第二层变量和前向传播
    with tf.variable_scope('layer2',reuse=reuse):
            weights = tf.get_variable('weights',[LAYERS1_NODE,OUTPUT_NODE],initializer=tf.truncated_normal_initializer(stddev=0.1))
            biases = tf.get_variable('biases',[OUTPUT_NODE],initializer=tf.constant_initializer(0.0))
            if avg_class == None:
                 layer2 = tf.matmul(layer1,weights)+biases
            else:
                 layer2 =tf.matmul(layer1, avg_class.average(weights)) + avg_class.average(biases)
    return layer2
#训练模型过程

def train(mnist):
    x = tf.placeholder(tf.float32, shape=[None, INPUT_NODE], name='x-input')
    y_ = tf.placeholder(tf.float32,shape=[None,OUTPUT_NODE],name='y-input')
    
    ##原始变量定义
    #生成隐藏层参数
    #weights1 = tf.Variable(tf.truncated_normal([INPUT_NODE,LAYERS1_NODE],stddev=0.1))
    #biases1 = tf.Variable(tf.constant(0.1,shape=[LAYERS1_NODE]))
    #生成输出层的参数
    #weights2 = tf.Variable(tf.truncated_normal([LAYERS1_NODE,OUTPUT_NODE],stddev=0.1))
    #biases2 = tf.Variable(tf.constant(0.1,shape=[OUTPUT_NODE]))
    
    #计算当前参数下的神经网络前向传播结果,avg_class为None 不会使用滑动平均
    #y = inference(x,None,weights1,biases1,weights2,biases2)
    y = inference(x,avg_class=None)
    #定义存储训练轮数的变量,该变量不需要滑动平均,所以指定该变量为不可训练的变量(trainable=False)
    global_step = tf.Variable(0,trainable=False)
    #给定滑动平均衰减率和训练轮数变量,初始化滑动平均类。在第四章中介绍过给定训练轮数的变量可以加快训练早起的更新速度
    variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step)
    #在所有代表神经网络参数的变量上(即未使用trainable=False的参数)使用滑动平均
    variable_averages_op = variable_averages.apply(tf.trainable_variables())
    #计算使用滑动平均之后的前向传播结果
    #average_y = inference(x,variable_averages,weights1,biases1,weights2,biases2)
    average_y = inference(x, avg_class=variable_averages,reuse=True)
    #计算loss
    cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y,labels=tf.argmax(y_,1))
    #计算在当前batch中所有样例的交叉熵平均值
    cross_entropy_mean = tf.reduce_mean(cross_entropy)
    #计算L2正则化损失函数
    regularizer = tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)
    #计算模型的正则化损失,一般只计算神经网络边上权重的正则化损失,不适用偏置项
    ##这块暂时这么解决了,应该还有更好的方法,如果知道的朋友欢迎留言交流
    with tf.variable_scope('layer1',reuse=True):
        regularization1 = regularizer(tf.get_variable("weights"))
    with tf.variable_scope('layer2', reuse=True):
        regularization2 = regularizer(tf.get_variable("weights"))
    #计算总损失
    loss = cross_entropy_mean+regularization1+regularization2
    #设置指数衰减学习率
    learning_rate = tf.train.exponential_decay(
        LEARNING_RATE_BASE, #基础的学习率,随着迭代的进行,更新变量使用的学习率在此基础上递减
        global_step,#当前迭代轮数,喂入一次 BACTH_SIZE 计为一次 global_step
        mnist.train.num_examples/BATCH_SIZE,#全部训练数据计算一遍需要的迭代次数
        LEARNING_RATE_DECAY)  #学习率衰减
    train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=global_step)
    #optimizer.minimize(loss,global_step=global_step)每次打开tf.Session()并运行该方法时,系统会自动为传入的global_step参数+1。
    #每过一遍数据需要通过反向传播更新神经网络中的参数,又要更新每一个参数的滑动平均,为了一次完成多个操作,tf提供两种机制
    #train_op = tf.group(train_step,variables_average_op)
    with tf.control_dependencies([train_step,variable_averages_op]):
         train_op = tf.no_op(name='train')
    #检验使用滑动平均的前向传播结果是否正确 ,返回为true或false
    correct_prediction = tf.equal(tf.argmax(average_y,1),tf.argmax(y_,1)) #y_为实际的正确结果标签
    #以下操作先把布尔型的数值转为实数型,计算平均值即模型在这一组数据上的正确率
    accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

    #初始化会话并开始训练过程。
    with tf.Session() as sess:
        tf.global_variables_initializer().run()
    #准备验证数据
        validate_feed = {x:mnist.validation.images,y_:mnist.validation.labels}
    #准备测试数据
        test_feed = {x:mnist.test.images,y_:mnist.test.labels}
        validate_accs = []
        test_accs = []
        for i in range(TRAINING_STEPS):
            if i%1000 == 0:
                validate_acc = sess.run(accuracy,feed_dict=validate_feed)
                test_acc = sess.run(accuracy,feed_dict=test_feed)
                validate_accs.append(validate_acc)
                test_accs.append(test_acc)
                print("After %d training setps,validation accuracy using average model is %g,"
                      "test accuracy using average model is %g" %(i,validate_acc,test_acc))
            #产生本轮训练所用数据,并运行训练过程
            xs,ys = mnist.train.next_batch(BATCH_SIZE)
            sess.run(train_op,feed_dict={x:xs,y_:ys}) #每次执行一次train_op,global_step参数自动加1
        #训练结束后,在测试数据上检测正确率
        test_acc = sess.run(accuracy,feed_dict=test_feed)
        print("After %d training setps,test accuracy using average model is %g" %(TRAINING_STEPS,test_acc))
        plot(validate_accs)
        show()




#主程序入口
#读取训练,验证,测试数据,自动分类55000+5000+10000
def main(argv=None):
    mnist = input_data.read_data_sets("/tf",one_hot=True)
    train(mnist)

#tf提供的一个主程序入口,tf.app.run会调用上面定义的main函数
if __name__ =='__main__':
    tf.app.run()


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值