滑动平均模型原理

滑动平均算法的原理

滑动平均模型又称为指数加权平均算法,是一种对数据的估测方式,它的好处是可以使数据更加平滑,数据噪声更少,不会出现异常值。
在这里插入图片描述
举例来说,这是来自吴恩达老师的深度学习课程中的一个例子,上图表示了一年365天的温度散点图,以天数为横坐标,温度为纵坐标,大致看来图中的点遵循一定的曲线规律,但不明显。
为了使温度变化的趋势更加明显,需要用到滑动平均模型,具体的计算方式如下:

  • 首先给定一个初始值 V0,
  • 然后对于图中每一天的温度,记为a1,a2,a3…
  • 接着计算 V1,V2,V3…来代替每一天的温度
  • 计算方法为:V1 = V0 * 0.9 + (1 - 0.9) * a1,V2 = V1 * 0.9 + (1 - 0.9) * a2,V3 = V2 * 0.9 + (1 - 0.9) * a3…
  • 计算得到所有的 V 值,然后画图,如图所示,红线就是对应的 V 的曲线,它很好地把温度变化曲线拟合了出来
    在这里插入图片描述
    滑动平均模型对应的计算公式如下,上面的计算过程就是取 β = 0.9,而 β 指的就是滑动平均模型的衰减率,衰减率可以用来控制模型的更新速度,衰减率越大模型越稳定,所以一般 β 取接近 1 的数(0.99 或 0.999)
    在这里插入图片描述
    另外,Vt 的值实际上可以代表 1 / (1-β) 天的平均值,例如当 β = 0.9,就是对应前十天的平均值,β = 0.98,对应前50天的平均值,对应的绿色曲线如下,很明显绿线的变化更加缓慢,但由于 β 值过大容易使曲线右移,降低对原数据的拟合度,因此需要不断尝试得出一个合适的 β 值,既能拟合数据集,又可以减少噪声
    在这里插入图片描述
    当 β 取值为 0.5,对应前两天的平均值,得到如下的黄色曲线,明显黄线变化很不稳定
    在这里插入图片描述

误差修正

在上面的例子中,在初始阶段定义 V0 = 0,β = 0.98,,但一开始并没有前50天的数据,这使得 Vt 偏小,因此实际得到的拟合曲线应该是下图中的紫色曲线
在这里插入图片描述
通常会使用 Vt / (1 - β^t)的方法修正,即 V2 改为 V2 / (1 - 0.9^2)
也可以使用
在这里插入图片描述
使用 num_updates(即更新次数) 来动态设置衰减率 β 的大小,在前期数据量比较小时会使用 (1+num_updates) / (10+num_updates) 作为衰减率,如第五天,β=0.98,(1+num_updates) / (10+num_updates) = (1 + 5) / (10 + 5) = 6 / 15 = 0.4,相当于最近1.6天的平均温度。

在 Tensorflow 中实现滑动平均算法

首先明确一点,TensorFlow 中的 ExponentialMovingAverage() 是针对权重weight和偏差bias的,而不是针对训练集的。
为什么要对w和b使用滑动平均模型呢?
因为在神经网络中, 更新的参数时候不能太大也不能太小,更新的参数跟你之前的参数有联系,不能发生突变。一旦训练的时候遇到个“疯狂”的参数,有了滑动平均模型,疯狂的参数就会被抑制下来,回到正常的队伍里。这种对于突变参数的抑制作用,用专业术语讲叫鲁棒性,鲁棒性就是对突变的抵抗能力,鲁棒性越好,这个模型对恶性参数的抵抗能力就越强。
在TensorFlow中,ExponentialMovingAverage()可以传入两个参数:衰减率(decay)和数据的迭代次数(step),这里的decay和step分别对应我们的β和num_updates,代码实现如下:

import tensorflow as tf

v1 = tf.Variable(0, dtype=tf.float32)

step = tf.Variable(0, trainable=False)
#定义滑动平均类
ema = tf.train.ExponentialMovingAverage(0.99, step)
#定义一个更新变量滑动平均的操作。这里需要给定一个列表
maintain_average_op = ema.apply([v1])

with tf.Session() as sess:
    tf.global_variables_initializer().run()
    # 通过ema.average(v1)获取滑动平均之后变量的取值
    print(sess.run([v1, ema.average(v1)]))  # [0.0, 0.0]
    # 更新v1的值到5
    sess.run(tf.assign(v1, 5))
    sess.run(maintain_average_op)
    print(sess.run([v1, ema.average(v1)]))  # [5.0, 4.5]
    
    #更新step的值为10000
    sess.run(tf.assign(step, 10000))
    sess.run(tf.assign(v1, 10))
    sess.run(maintain_average_op)
    print(sess.run([v1, ema.average(v1)]))  # [10.0, 4.555]
    
    sess.run(maintain_average_op)
    print(sess.run([v1, ema.average(v1)]))  # [10.0, 4.60945]

补充

滑动平均实际上就是对前 n 个数据进行加和并平均,假设有100天的温度数据,则
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值