您的位置:首页 > 其它

tensorflow ExponentialMovingAverage

2017-07-07 11:29 525 查看

作用

假如我们训练模型迭代了100K,每2K步保存一个snapshot。在evaluation时, 我们可以只使用最后得到的model-100K,也可以通过cross validation选出一最佳的model,如model-98K。 但Googlers发现(https://www.tensorflow.org/versions/r1.0/api_docs/python/tf/train/ExponentialMovingAverage):

When training a model, it is often beneficial to maintain moving averages of the trained parameters. Evaluations that use averaged parameters sometimes produce significantly better results than the final trained values.

大概意思是对模型参数进行平均得到的模型往往比单个模型的结果要好很多,注意,他们使用了
significantly better
这个修饰, 虽然前边还有个
sometimes
.

于是, tensorflow里就有了
tf.train.ExponentialMovingAverage
这个接口。

在training时使用

文档中的例子:

# Create variables.
var0 = tf.Variable(...)
var1 = tf.Variable(...)
# ... use the variables to build a training model...

# Create an op that applies the optimizer.  This is what we usually
# would use as a training op.
opt_op = opt.minimize(my_loss, [var0, var1])

# Create an ExponentialMovingAverage object
ema = tf.train.ExponentialMovingAverage(decay=0.9999)

# Create the shadow variables, and add ops to maintain moving averages of var0 and var1.
maintain_averages_op = ema.apply([var0, var1])

# Create an op that will update the moving averages after each training step.  This is what we will use in place of the usual training op.
with tf.control_dependencies([opt_op]):
training_op = tf.group(maintain_averages_op)

#...train the model by running training_op...


这个例子体现出使用MovingAverage的三个要素。

1. 指定
decay
参数创建实例:

ema = tf.train.ExponentialMovingAverage(decay=0.9999)


2. 对模型变量使用
apply
方法:

maintain_averages_op = ema.apply([var0, var1])


3. 在优化方法使用梯度更新模型参数后执行MovingAverage:

with tf.control_dependencies([opt_op]):
training_op = tf.group(maintain_averages_op)


其中,
tf.group
将传入的操作捆绑成一个操作,详细可参考文档

原理:影子变量与decay

apply
方法会为每个变量(也可以指定特定变量)创建各自的
shadow variable
, 即影子变量。之所以叫影子变量,是因为它会全程跟随训练中的模型变量。影子变量会被初始化为模型变量的值,然后,每训练一个step,就更新一次。更新的方式为:

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


decay
的值一般很接近于1,例如
0.999, 0.9999
。很明显, 这个操作会增加模型在训练过程中的稳定性。

还有一点值得指出——创建
tf.train.ExponentialMovingAverage
实例时还可以传入
num_updates
参数,一般使用
global_step
的值:

ema = tf.train.ExponentialMovingAverage(decay=0.9999, num_updates = tf_global_step)


它的作用让
decay
变成动态的,训练前期的值小,后期的值大。因为这时真实decay的计算方式为:

decay = min(decay, (1 + num_updates) / (10 + num_updates))


Restore from checkpoint

训练时若使用了
ExponentialMovingAverage
,在保存checkpoint时,不仅仅会保存模型参数,优化器参数(如Momentum), 还会保存
ExponentialMovingAverage
shadow variable


之前,我们可以直接使用以下代码restore模型参数, 但不会利用
ExponentialMovingAverage
的结果:

saver = tf.Saver()
saver.restore(sess, save_path)


若要使用
ExponentialMovingAverage
保存的参数:

variables_to_restore = ema.variables_to_restore()
saver = tf.train.Saver(variables_to_restore)
saver.restore(sess, save_path)


当然,还有其他方式可以实现同样的效果。

写了一个完整的可运行demo, tensorflow r1.1.0。

看看它的输出就一目了然了(字符串是变量名,数字是对应的变量值),两者加载的变量值是不同的:

variables in checkpoint:
bias/ExponentialMovingAverage 0.664593
bias/Momentum 4.12663
weight [[ 0.01567289]
[ 0.17180483]]
weight/ExponentialMovingAverage [[ 0.10421171]
[ 0.26470858]]
weight/Momentum [[ 5.95625305]
[ 6.24084663]]
bias 0.602739

==============================================
variables restored not from ExponentialMovingAverage:
weight:0 [[ 0.01567289]
[ 0.17180483]]
bias:0 0.602739

==============================================
variables restored from ExponentialMovingAverage:
weight:0 [[ 0.10421171]
[ 0.26470858]]
bias:0 0.664593
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  tensorflow