1、滑动模型是用来干嘛的?
在采用随机梯度下降算法训练神经网络时,使用 tf.train.ExponentialMovingAverage 滑动平均操作的意义在于提高模型在测试数据上的健壮性(robustness)。
2、原理
tensorflow 下的 tf.train.ExponentialMovingAverage 需要提供一个衰减率(decay)。该衰减率用于控制模型更新的速度。该衰减率用于控制模型更新的速度,ExponentialMovingAverage 对每一个(待更新训练学习的)变量(variable)都会维护一个影子变量(shadow variable)。影子变量的初始值就是这个变量的初始值,
shadow_variable=decay×shadow_variable+(1−decay)×variable
由上述公式可知, decay 控制着模型更新的速度,越大越趋于稳定。实际运用中,decay 一般会设置为十分接近 1 的常数(0.99或0.999)。为了使得模型在训练的初始阶段更新得更快,ExponentialMovingAverage 还提供了 num_updates 参数来动态设置 decay 的大小:
decay=min{decay,1+num_updates10+num_updates}
3、实现
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Aug 20 11:52:00 2017
@author: xiaolian
"""
import tensorflow as tf
# 用于计算滑动平均
v1 = tf.Variable(0, dtype = tf.float32)
# step 模拟神经网络中迭代的轮数, 可以用于动态控制衰减率
step = tf.Variable(0, trainable = False)
# 定义一个滑动平均的类,初始化时给定了衰减率(0.99)和 控制衰减率的变量 step
ema = tf.train.ExponentialMovingAverage(0.99, step)
# 定义一个更新变量滑动平均的操作,这里需要给定一个列表,每次执行这个操作时,这个列表中的变量都会被更新
maintain_average_op = ema.apply([v1])
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
# 通过ema.average(v1) 获得滑动平均之后变量的取值,在初始化之后变量 v1 的值 和 v1 的滑动平均都为 0
print(sess.run(v1))
# 更新 v1 到 5
sess.run(tf.assign(v1, 5))
# 更新 v1 的滑动平均值,衰减率为 min(0.99, (1 + step) / (10 + step) = 0.1) = 0.1
# 所以 v1 的滑动平均会被更新为 0.1 x 0 + 0.9 x 5 = 4.5
sess.run(maintain_average_op)
print(sess.run(ema.average(v1)))
print(sess.run(v1))
sess.run(tf.assign(step, 10000))
sess.run(tf.assign(v1, 10))
sess.run(maintain_average_op)
print(sess.run(ema.average(v1)))
print(sess.run(v1))
sess.run(maintain_average_op)
print(sess.run(ema.average(v1)))
print(sess.run(v1))
output:
0.0
4.5
5.0
4.555
10.0
4.60945
10.0