神经网络的优化(2)---- 滑动平均 ema
这一节分享另一个优化方法:滑动平均。有些书里把它叫做“影子值”。滑动平均记录了每个参数一段时间内过往值的平均。由于滑动平均值不仅表现了当前值,还表现了过去一段时间内的平均值,这样可以增加模型的泛化性。 滑动平均通常针对所有参数进行优化,包括所有的w和b。 滑动平均的感觉就好比给参数加了个影子,参数变化,影子缓慢追随。
滑动平均值是这样计算的: 影子等于衰减率乘以影子,加上(1-衰减率)乘以参数。衰减率等于MOVING_AVERAGE_DECAY与(1+轮数)/(10+轮数)中小的那一个。 其中滑动平均衰减率MOVING_AVERAGE_DECAY是一个超参数。影子的初值等于参数的初值。
我们来看这个例子:
衰减率的第一个参数MOVING_AVERAGE_DECAY是个超参数,一般会给一个比较大的值,比如0.99。参数w1在初始化时赋值为0。轮数global_step定义为0。由于影子的初值等于参数初值,所以w1的滑动平均值初值也为0。 当参数w1被更新时,比如更新为1时,影子会慢慢追随。通过计算,w1的滑动平均值=min{0.99,(1+0)/(10+0)} * 0 + (1-min{0.99,(1+0)/(10+0)})*1=0.1*0 + 0.9*1 = 0.9 当100轮,参数更新为10时。w1的滑动平均值=1.644 再次运行时,w1的滑动平均值为2.328 再次运行时,为2.956
可见,滑动平均像影子一样,缓慢追随者参数变化。
在TensorFlow里,我们用这样三句话描述滑动平均:
第一句话:ema=tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)。有两个参数,第一个参数是滑动平均衰减率,是个超参数,一般会给一个比较大的值。第二个参数是当前轮数,和其他程序公用一个轮数计数器global_step。 第二句话:ema.apply([]) 定义了对括号里列出的参数求滑动平均。我们在实际应用中,会写ema.apply(tf.trainable_variables())。用tf.trainable_variable()函数可以自动把所有待训练的参数汇总成列表。 第三句话是 :with...这句话。在工程应用中,我们常把计算滑动平均ema_op和训练过程train_step绑定在一起运行,使他们合成一个训练节点。用train_op = tf.no_op(name='train') 这句话实现。我们在下节手写识别的应用中,会用到这个功能。
用ema.average()可以返回某些参数的滑动平均值。
我们通过代码实现一下:
运行结果: [0.0, 0.0] #刚开始时的值。
可以看到滑动平均值追随参数变化的过程。
|