加权平均:
我们常用的算术平均属于加权平均的特殊形式,只不过算术平均各项权重都相等。
加权滑动平均:
原理与加权平均类似,但重点在“滑动”一词,即该平均过程就好似从第一个值依次向后滑动,直到滑动到最后一个值,言外之意就是,第n个值取决于第n-1个值。
滑动平均递推公式:
一般设
v
0
v_0
v0=0,由上述公式可知:
通过数学归纳法可知:
最终所要求得的加权滑动平均值即为
v
t
v_t
vt。但是问题又随之出现了,前几个
v
t
v_t
vt(通过递推公式得到的)与它们各自的原始值偏差很大,由于
v
0
v_0
v0=0,而
β
\beta
β(又称为衰减率)的值在区间[0,1)内,所以通过递推公式得到的
v
1
v_1
v1的值会远远小于原始值
θ
1
\theta_1
θ1,
v
2
v_2
v2和
v
3
v_3
v3的值也会较
θ
2
\theta_2
θ2和
θ
3
\theta_3
θ3有所偏差。为此在上述公式的基础之上做了改进,即
该式即为指数加权滑动平均的公式。
当t=1时,对应
v
t
v_t
vt=
v
1
v_1
v1,1-
β
t
\beta^t
βt=1-
β
\beta
β,通过递推公式我们发现此时
v
1
v_1
v1=
θ
1
\theta_1
θ1,很好地解决了偏差较大的问题。而且由于
β
\beta
β在区间[0,1)内,所以随着t的增大,指数加权滑动平均公式的分母越来越趋近于1,对于偏差很小的数又减弱了该指数项的影响。
import numpy as np
import matplotlib.pyplot as plt
import math
theta = [0, 10, 20, 10, 0, 10, 20, 30, 5, 0, 10, 20, 10, 0, 10, 20,
30, 5, 0, 10, 20, 10, 0, 10, 20, 30, 5, 0, 10, 20, 10, 0,
10, 20, 30, 5]
def moving_ave(theta, beta):
theta = np.array(theta).reshape((-1, 1))
m, n = theta.shape
v = np.zeros((m, 1))
for i in range(1, m):
v[i, :] = beta * v[i-1, :] + (1 - beta) * theta[i, :]
return v
def exp_moving_ave(theta, beta):
theta = np.array(theta).reshape((-1, 1))
m, n = theta.shape
v = np.zeros((m, 1))
for i in range(1, m):
v[i, :] = (beta * v[i-1, :] + (1 - beta) * theta[i, :])
for i in range(1, m):
v[i, :] /= (1 - beta**i)
return v
v = moving_ave(theta, 0.9)
v_exp = exp_moving_ave(theta, 0.9)
plt.plot(theta, lw=2, marker='*', label=r'$v_t$=$\theta_t$')
plt.plot(v[:, 0], lw=2, color='darkorange', marker='*', label=r'$v_t$=$\beta$$v_{t-1}$+(1-$\beta$)$\theta_t$')
plt.plot(v_exp[:, 0], lw=2, color='green', marker='*', label=r'$v_t$=$v_t$/(1-$\beta^t$)')
plt.legend()
plt.show()
通过上图可以明显地看出加权滑动平均和指数加权滑动平均之间的差别。
keras
的BatchNormalization
函数(批次归一化)中的momentum
参数即为加权滑动平均的
β
\beta
β(初始值为0.99)。
β
\beta
β的值越接近1,前几个数值的权重越高,滑动平均的结果越取决于前t个值。若
β
\beta
β的值越接近0,前几个数值权重越低,滑动平均的结果越取决于距离
v
t
v_t
vt最近的几个数值。
tf.keras.layers.BatchNormalization(
axis=-1,
momentum=0.99,
epsilon=0.001,
center=True,
scale=True,
beta_initializer="zeros",
gamma_initializer="ones",
moving_mean_initializer="zeros",
moving_variance_initializer="ones",
beta_regularizer=None,
gamma_regularizer=None,
beta_constraint=None,
gamma_constraint=None,
renorm=False,
renorm_clipping=None,
renorm_momentum=0.99,
fused=None,
trainable=True,
virtual_batch_size=None,
adjustment=None,
name=None,
**kwargs
)
使用指数加权滑动平均可以有效避免数据抖动,使得数据更加平稳、平滑,使得测试过程更加鲁棒。