Tensorflow学习——4 手写体识别代码的继续研究

tensorflow这本书呢,后面又写了很多的改进的方法,比如了解下面这个代码,你就需要了解衰减学习率、滑动平均模型了。

1、衰减学习率

随着模型训练,若学习率一直不变,损失值在接近一个极小值时就可能出现左右震荡,这时候适当的减小学习率,就可以解决这个问题。

线性衰减。例如:每过5个epochs学习率减半
指数衰减。例如:每过5个epochs将学习率乘以0.1

指数衰减

learning_rate = tf.train.exponential_decay(
         LEARNING_BATE_BASE,#基础学习率,比如0.6
         global_step,#当前迭代的轮数
         mnist.train.num_examples/BATCH_SIZE,#训练数据集需要迭代的次数
         LEARNING_RATE_DECAY)#学习率的衰减速度 ,如0.9

2、滑动平均模型

目的:滑动平均模型,它可以使得模型在测试数据上更健壮,在使用随机梯度下降算法训练神经网络时,通过滑动平均模型可以在很多的应用中在一定程度上提高最终模型在测试数据上的表现。其实滑动平均模型,主要是通过控制衰减率来控制参数更新前后之间的差距,从而达到减缓参数的变化值(如,参数更新前是5,更新后的值是4,通过滑动平均模型之后,参数的值会在4到5之间),如果参数更新前后的值保持不变,通过滑动平均模型之后,参数的值仍然保持不变

计算方式:shadow_variable = decay * shadow_variable + (1-decay) * variable
其中shadow_variable是影子变量,variable是待更新的变量,decay是衰减率。从公式中可以看到,decay决定了模型更新的速度,decay越大模型越稳定。在实际应用中,decay一般被设置为非常接近1的数(0.99、0.999),为了使得模型在训练前期可以更新的更快,ExponentialMovingAverage提供了num_updates参数来动态设置decay的大小。
例子

import tensorflow as tf

# 32位浮点数的变量,初始值是0.0
v1 =tf.Variable(dtype=tf.float32, initial_value=0.)
# 衰减率0.99
decay = 0.99
# 模拟迭代次数
step= tf.Variable(0, trainable=False)

# 定义滑动平均模型的类,将衰减率decay和step传入。
ema = tf.train.ExponentialMovingAverage(decay, step)

# 定义更新变量列表 每次进行滑动操作都会更新这个列表
mainrain_average_op =  ema.apply([v1])

# Tensorflow会话
with tf.Session() as sess:
    # 初始化全局变量
    sess.run(tf.global_variables_initializer())

    # ema.average(v1)这个是获取滑动平均之后变量的值,
    print(sess.run([v1, ema.average(v1)]))
    # [0.0, 0.0](此时 step= 0 ⇒ decay = .1, ),
    # shadow_variable = variable = 0.

    # 将v1 赋值为5
    sess.run(tf.assign(v1, 5))

    # 调用函数,使用滑动平均模型
    sess.run(mainrain_average_op)

    # 再次输出 step=0 衰减率为min{0.99,(1+step)/(10+step) = 0.1) = 0.1
    # 0.1 *0 + 0.9 *5 = 4.5   v1现在为4.5
    print(sess.run([v1, ema.average(v1)]))


    # step 为10000
    sess.run(tf.assign(step, 10000))
    # 将v1赋值为10
    sess.run(tf.assign(v1, 10))
    # 调用函数,使用滑动平均模型
    sess.run(mainrain_average_op)

    # 输出min{0.99,(1+step)/(10+step) = 0.999) = 0.99
    # 0.99 *4.5 + 0.9 *10 = 4.555  v1现在是10
    print(sess.run([v1, ema.average(v1)]))


    # 再次使用滑动平均模型
    sess.run(mainrain_average_op)
    # 输出 decay = 0.99,shadow_variable = .99*4.555 + .01*10 = 4.609
    print(sess.run([v1, ema.average(v1)]))

3、具体代码



# _*_ encoding=utf8 _*_

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


# minst数据集相关的常数
INPUT_NODE = 784    # 输入层的节点数,等于minst数据集,这个就等于图片的像素
OUTPUT_NODE = 10    # 输出层的节点数,这个等于类别的数目,应为在minst数据集中
                    # 需要区分0-9折10个数字,所以输出层设为10个节点

# 配置神经网络的参数
LAYERL_NODE = 500 # 影藏层的节点数,这里使用只有一个隐藏层层的网络结构作为样例

BATCH_SIZE = 100 # 一个训练batch中训练数据的个数,数字越小时,训练过程越接近
                    # 随机梯度下降,数字越大时,训练越接近梯度下降

LEARNING_BATE_BASE = 0.8 #基础的学习率
LEARNING_RATE_DECAY = 0.9  #学习率的衰减率

REGUIARIZATION_RATE = 0.0001  # 描述模型复杂度的正则化项在损失函数中的系数
TRANING_STEPS= 3000 # 训练轮数
MOVEING_AVERAGE_DECAY = 0.99    # 滑动平均衰减率

# 计算神经网络的前项传播结果,在一个通过使用relu激活函数的三层全连接神经网络
# 通过加入隐藏层实现多层网络结构
def inference(input_tensor ,avg_class,weights1, biases1,
                weights2,biases2):
    # 当没有提供滑动平均类时,直接使用参数当前的取值
    if avg_class == None:
        # 计算隐藏层的前项传播结果,这儿使用了Relu激活函数
        layer1 = tf.nn.relu(tf.matmul(input_tensor,weights1) + biases1)
        # 计算输出层的前项传播结果,因为在计算损失函数的时候会一并计算softmax函数
        # 所以这里不需要加入激活函数
        return tf.matmul(layer1, weights2) + biases2

    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)

# 训练模型的过程
def train(mnist):

    x = tf.placeholder(tf.float32, [None, INPUT_NODE], name='x-input')
    y_ = tf.placeholder(tf.float32, [None, OUTPUT_NODE], name='y-input')

    #生成影藏层得到参数
    weights1 = tf.Variable(
        tf.truncated_normal([INPUT_NODE,LAYERL_NODE], stddev = 0.1))


    biases1 = tf.Variable(tf.constant(0.1, shape=[LAYERL_NODE]))
    # 生成输出层的参数
    weights2 = tf.Variable(
        tf.truncated_normal([LAYERL_NODE,OUTPUT_NODE], stddev = 0.1))
    biases2 = tf.Variable(tf.constant(0.1, shape = [OUTPUT_NODE]))


    # 计算当前参数下神经网络前项传播的结果,这里给出用于计算滑动平均的类为None,
    # 所以函数不会使用参数的滑动平均值

    y = inference(x, None, weights1, biases1, weights2, biases2)

    # 定义存储训练次数的变量,这个变量不需要计算滑动平均值,所以这里指定这个变量为
    # 不可训练的变量(trainable = False)
    global_step = tf.Variable(0, trainable = False)

    # 给定滑动平均衰减率和训练轮数的变量,初始化滑动类
    variable_average = tf.train.ExponentialMovingAverage(
        MOVEING_AVERAGE_DECAY, global_step)

    variables_average_op = variable_average.apply(
        tf.trainable_variables())

    average_y = inference(
        x, variable_average, weights1, biases1,weights2, biases2)

    # cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
    cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits = y, labels = tf.argmax(y_,1))

    cross_entropy_mean = tf.reduce_mean(cross_entropy)

    regularizer = tf.contrib.layers.l2_regularizer(REGUIARIZATION_RATE)
    regularization = regularizer(weights1) + regularizer(weights1)

    loss = cross_entropy_mean + regularization

    # 设置指数衰减学习率
    # learning_rate = tf.train.exponential_decay(
    #     LEARNING_BATE_BASE,
    #     global_step,
    #     mnist.train.num_examples/BATCH_SIZE,
    #     LEARNING_RATE_DECAY)

    # 使用优化器来优化损失函数  搭配指数衰减学习率使用
    # train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step = global_step)
    train_step = tf.train.AdamOptimizer(0.001).minimize(loss, global_step = global_step)

    with tf.control_dependencies([train_step, variables_average_op]):
        train_op = tf.no_op(name = 'train')

    correct_prediction = tf.equal(tf.argmax(average_y, 1),tf.argmax(y_,1))

    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}
        ummary_waiter = tf.summary.FileWriter("./log", tf.get_default_graph())
        ummary_waiter.close()
        for i in range(TRANING_STEPS):
            if i % 1000 == 0:
                validate_acc = sess.run(accuracy, feed_dict = validate_feed)
                print("after %d training step(s),validation accuracy "
                    "using average model is %g " % (i, validate_acc))


            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 step(s),test accuracy using average "
            "model is %g" % (TRANING_STEPS, test_acc))

def main(argv=None):
    mnist = input_data.read_data_sets("../data", one_hot = True)
    train(mnist)

if __name__ == '__main__':
    tf.app.run()

运行结果:

Extracting ../data\train-images-idx3-ubyte.gz
Extracting ../data\train-labels-idx1-ubyte.gz
Extracting ../data\t10k-images-idx3-ubyte.gz
Extracting ../data\t10k-labels-idx1-ubyte.gz
2018-08-24 00:26:27.752686: 
after 0 training step(s),validation accuracy using average model is 0.1694 
after 1000 training step(s),validation accuracy using average model is 0.9748 
after 2000 training step(s),validation accuracy using average model is 0.9804 
after 3000 training step(s),test accuracy using average model is 0.9822

但是这个图,真的丑
这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值