滑动平均(影子值)

一、定义

滑动平均(影子值)

滑动平均(影子值):记录了每个参数一段时间内过往值得平均,增加了模型得泛化性。针对所有参数w和b(像是给参数加了影子,参数变化,影子慢慢追随)

796272-20190107133939933-1952639914.png

二、Tesnsorflow 函数表示

语句一

ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)

其中,MOVING_AVERAGE_DECAY 表示滑动平均衰减率,一般会赋接近 1 的值,global_step 表示当前训练了多少轮。

语句二

ema_op = ema.apply(tf.trainable_variables())

其中,ema.apply()函数实现对括号内参数求滑动平均,tf.trainable_variables()函数实现把所有待训练参数汇总为列表。

语句三

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

其中,该函数实现将滑动平均和训练过程同步运行。

查看模型中参数的平均值,可以用 ema.average()函数。

举例说明:

在神经网络模型中,将 MOVING_AVERAGE_DECAY 设置为 0.99,参数 w1 设置为 0,w1 的滑动平均值设置为 0。

(1)开始时,轮数 global_step 设置为 0,参数 w1 更新为 1,则 w1 的滑动平均值为:

w1 滑动平均值=min(0.99,1/10)*0+(1– min(0.99,1/10)*1 = 0.9

(2)当轮数 global_step 设置为 100 时,参数 w1 更新为 10,以下代码 global_step 保持为 100,每次执行滑动平均操作影子值更新,则滑动平均值变为:

w1 滑动平均值=min(0.99,101/110)*0.9+(1– min(0.99,101/110)*10 = 0.826+0.818=1.644

(3)再次运行,参数 w1 更新为 1.644,则滑动平均值变为:

w1 滑动平均值=min(0.99,101/110)*1.644+(1– min(0.99,101/110)*10 = 2.328

(4)再次运行,参数 w1 更新为 2.328,则滑动平均值:

w1 滑动平均值=2.956

完整的代码实现:

import tensorflow as tf

# 1. 定义变量及滑动平均类
# 定义一个32位的浮点变量,初始值为0
# 这个代码就是不断更新w1参数,优化w1参数,滑动平均做了w1的影子
w1 = tf.Variable(0, dtype=tf.float32)
# 定义num_updates (NN的迭代轮数),初始值为0,不可能被优化(训练),这个参数不训练
# 当前轮数
global_step = tf.Variable(0, trainable=False)

# 实例化滑动平均类,给删减率为0.99,当前轮数global_step
MOVING_AVERAGE_DECAY = 0.99

ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)

# ema.apply后面的括号里是更新列表,每次运行sess.run(ema_op)时,对更新列表中的元素求滑动平均值
# 在实际应用中会使用tf.trainable_variables()自动将所有待训练的参数汇总为列表
ema_op = ema.apply(tf.trainable_variables())

# 2. 查看不同迭代变量取值的变化
with tf.Session() as sess:
    # 初始化
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    # 用ema.average(w1)获取w1滑动平均值(要运行多个节点,作为列表中的元素列出,写在sess.run()中)
    # 打印出当前参数w1和w1的滑动平均
    print(sess.run([w1, ema.average(w1)]))

    # 参数w1的值赋值为1
    sess.run(tf.assign(w1, 1))
    sess.run(ema_op)
    print(sess.run([w1, ema.average(w1)]))

    # 更新step和w1的值,模拟出100轮迭代后,参数w1变为10
    sess.run(tf.assign(global_step, 100))
    sess.run(tf.assign(w1, 10))
    sess.run(ema_op)
    print(sess.run([w1, ema.average(w1)]))

    # 每次sess.run()都会更新一次w1的滑动平均值
    sess.run(ema_op)
    print(sess.run([w1, ema.average(w1)]))

    sess.run(ema_op)
    print(sess.run([w1, ema.average(w1)]))

    sess.run(ema_op)
    print(sess.run([w1, ema.average(w1)]))

    sess.run(ema_op)
    print(sess.run([w1, ema.average(w1)]))

输出结果:

[0.0, 0.0]
[1.0, 0.9]
[10.0, 1.6445453]
[10.0, 2.3281732]
[10.0, 2.955868]
[10.0, 3.532206]
[10.0, 4.061389]

从运行结果可知,最初参数 w1 和滑动平均值都是 0;参数 w1 设定为 1 后,滑动平均值变为 0.9;当迭代轮数更新为 100 轮时,参数 w1 更新为 10 后,滑动平均值变为 1.644。随后每执行一次,参数w1 的滑动平均值都向参数 w1 靠近。可见,滑动平均追随参数的变化而变化。

转载于:https://www.cnblogs.com/ch-forever/p/10232768.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值