Tensorflow学习(6)-神经网络进一步优化(滑动平均模型)

滑动平均模型

TensorFlow中提供了tf.train.ExponentialMovingAverage来实现滑动平均模型。

在初始化ExponentialMovingAverage时,需要提供一个衰减率(decay)。这个衰减率用于控制模型更新的速度。

ExponentialMovingAverage对每一个变量会维护一个影子变量(shadow variable),这个影子变量的初始值就是相应变量的初始值,

而每次运行变量更新时,影子变量的值会更新为:

shadow_variable = decay * shadow_variable + (1-decay) * variable

可见decay决定了模型更新的速度,decay越大模型越稳定。在实际应用中decay一般设置为非常接近1的数。

为了使模型在训练前期可以更新的更快,ExponentialMovingAverage还提供了num_updates(与学习率指数下降一文中说的global_step是一回事)参数来动态设置decay的大小,如果在ExponentialMovingAverage初始化时提供了num_updates参数,那么每次使用的衰减率将是

min(decay , (1+num_updates) / (10+num_updates)) # 随着num_updates增大,右面这个也增大,在某个时刻就会选择左方的值。

使用这个的初衷是为了训练前期模型更新的更快。所以前期的衰减率就比较小,更新的幅度就大

下面通过一段代码来解释 ExponentialMovingAverage是如何被使用的(只给出简单样例,具体的使用以后再补)

ema.apply([ ]):更新列表里元素的滑动平均值

ema.average( ): 取某元素的滑动平均值

import tensorflow as tf

# 定义一个变量用于计算滑动平均,这个变量初始值为0.
# 需要手动指定类型为tf.float32,因为所有需要计算滑动平均的变量必须是实数型
v1 = tf.Variable(0, dtype=tf.float32)
v2 = tf.Variable(0.5, dtype=tf.float32)
# 这里的step变量模拟神经网络迭代的轮数,用于动态控制衰减率
step = tf.Variable(0, trainable=False)

# 定义一个滑动平均的类。初始化是给定衰减率(0.99)和控制衰减率的变量step。
ema = tf.train.ExponentialMovingAverage(0.99, step)
# 定义一个更新变量滑动平均的操作,需要给定一个列表。
# 每次执行这个操作这个列表的变量都会更新,之后用列表里对应元素的名字,
# ema.average(name)可以取出滑动平均值
maintain_averages = ema.apply([v1, v2])
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    # 输出初始化之后的值
    print(sess.run([v1, ema.average(v1)]))
    print(sess.run([v2, ema.average(v2)]))
    # 更新变量v1的值到5
    sess.run(v1.assign(5))
    # 更新滑动平均值
    sess.run(maintain_averages)  # 衰减率选择为右边的
    print(sess.run([v1, ema.average(v1)]))
    # 输出[5,4.5]
    # 更新step值为10000
    sess.run(step.assign(10000))
    # 更新v1值为10
    sess.run(v1.assign(10))
    # 更新滑动平均值
    sess.run(maintain_averages)  # step高了之后衰减率选择左边
    print(sess.run([v1, ema.average(v1)]))
    # 输出[10.0, 4.555]
    # 再次更新
    sess.run(maintain_averages)
    print(sess.run([v1, ema.average(v1)]))
    # 输出[10.0, 4.60945]

通过<Tensorflow学习(7)-通过MNIST数字识别问题学习(1)>,进一步认识了滑动平均模型。

一直有个疑问困扰就是这个滑动平均模型的影子变量如何去影响本来的权值,查了好多资料然后分析代码发现:

它根本不需要影响权值,他就是相当于一个很重的石头,往它的右边拉它往右动一点,往它的左边拉它往左动一点。就相当于最后产生了两组权值,影子变量那组更鲁棒。(暂时是这么理解的。。hh)这样可以就保证了训练过程的鲁棒性,至少可以去除一些噪音数据的影响。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值