本文主要是介绍浅谈指数移动平均(ema),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
经常在各种代码中看到指数移动平均(比如我专注的网络传输领域),但却不曾想到它就是诠释世界的方法,我们每个人都在被这种方式 “平均”…
今天说说指数移动平均(或移动指数平均,Exponential Moving Average)。
能查到的资料都侧重于其数学形式和实现,比如卷积和 python,这一点不再赘述,所以要写点内涵,物理意义和哲学。
指数移动平均在我们遇到的很多时间序采样中应用甚广,比如 tcp 的 srtt,它在形式上如下:
V n = ( 1 − β ) ∗ V n − 1 + β ∗ C V_n=(1-\beta)*V_{n-1}+\beta*C Vn=(1−β)∗Vn−1+β∗C
其中 C 为当前采样值,而 Vn 就是该采样序列的指数移动平均。
ema 的形式极端简洁,它只需要拿当前采用进行增量计算,不需要保存任何历史采样,其形式中,beta 为当下值权重,1 - beta 则留给过往,这非常符合我们的思维习惯。
我们认识的每一件事物,其本质都在采样,我们将当前采用叠加在对该采用的历史记忆之上,一杯敬当下,一杯敬过往,形成对世界的理解,形成我们的观点,我们的整个世界每时每刻对每件事物都在做指数移动平均。
将形式展开,我们将发现我们理解世界的过程:
V n = β ∗ C + ( 1 − β ) ∗ V n − 1 V_n=\beta*C+(1-\beta)*V_{n-1} Vn=β∗C+(1−β)∗Vn−1
V n = β ∗ C n + ( 1 − β ) ∗ ( β ∗ C n − 1 + ( 1 − β ) ∗ V n − 2 ) V_n=\beta*C_n+(1-\beta)*(\beta*C_{n-1}+(1-\beta)*V_{n-2}) Vn=β∗Cn+(1−β)∗(β∗Cn−1+(1−β)∗Vn−2)
…
V n = β ∗ ( 1 − β ) 0 ∗ C n + β ∗ ( 1 − β ) 1 ∗ C n − 1 + β ∗ ( 1 − β ) 2 ∗ C n − 2 + β ∗ ( 1 − β ) 3 ∗ C n − 3 + . . . β ∗ ( 1 − β ) n ∗ C 0 = Σ m = 0 n ( 1 − β ) m ∗ β C n − m V_n=\beta*(1-\beta)^0*C_n+\beta*(1-\beta)^1*C_{n-1}+\beta*(1-\beta)^2*C_{n-2}+\beta*(1-\beta)^3*C_{n-3}+...\beta*(1-\beta)^n*C_0=\Sigma_{m=0}^{n}{(1-\beta)^m*\beta C_{n-m}} Vn=β∗(1−β)0∗Cn+β∗(1−β)1∗Cn−1+β∗(1−β)2∗Cn−2+β∗(1−β)3∗Cn−3+...β∗(1−β)n∗C0=Σm=0n(1−β)m∗βCn−m
这里不讲卷积的形式,只从物理意义上理解 Vn 的每一项都是一个采样值 Cx 和一个 1 - beta 次幂的乘积的原因。下面开始。
假设我们的大脑能无差别均匀等价记忆所有采样值,我们的记忆是:
M = { C n , C n − 1 , C n − 2 , C n − 3 , . . . } M=\{C_{n},C_{n-1},C_{n-2},C_{n-3},...\} M={Cn,Cn−1,Cn−2,Cn−3,...}
然而我们不可能无差别记住所有采样,我们记忆容量有限,我们倾向于逐渐忘掉过往。由于历史记忆存在,当前采样仅能占据一部分记忆空间,这就是 β ∗ C \beta*C β∗C,那么 1 − β 1-\beta 1−β 的份额将留给过往,所有的过往将共享这 1 − β 1-\beta 1−β 的份额,这意味着随着新采样的不断进入,每一个历史采样必须衰减,历史越久的样本衰减越厉害,即 “逐渐忘掉过往” 。
M 集合按照历史时间序排序采样值 C,由于它进入记忆时均以 beta 份额压缩,事实上的 M 为:
M = { β ∗ C n , β ∗ C n − 1 , β ∗ C n − 2 , β ∗ C n − 3 , . . . } M=\{\beta*C_{n},\beta*C_{n-1},\beta*C_{n-2},\beta*C_{n-3},...\} M={β∗Cn,β∗Cn−1,β∗Cn−2,β∗Cn−3,...}
它的每一项被一个同样的按历史时间序加速衰减的集合过滤:
F = { ( 1 − β ) 0 , ( 1 − β ) 1 , ( 1 − β ) 2 , ( 1 − β ) 3 , . . . } F=\{(1-\beta)^0,(1-\beta)^1,(1-\beta)^2,(1-\beta)^3,...\} F={(1−β)0,(1−β)1,(1−β)2,(1−β)3,...}
把集合 M 往下漏被集合 F 阻隔过滤,就形成了新的集合 V:
V = { β ∗ C n ∗ ( 1 − β ) 0 , β ∗ C n − 1 ∗ ( 1 − β ) 1 , β ∗ C n − 2 ∗ ( 1 − β ) 2 , β ∗ C n − 3 ∗ ( 1 − β ) 3 , . . . } V=\{\beta*C_n*(1-\beta)^0,\beta*C_{n-1}*(1-\beta)^1,\beta*C_{n-2}*(1-\beta)^2,\beta*C_{n-3}*(1-\beta)^3,...\} V={β∗Cn∗(1−β)0,β∗Cn−1∗(1−β)1,β∗Cn−2∗(1−β)2,β∗Cn−3∗(1−β)3,...}
这就是指数移动平均的各项,看这相乘的形式当然可以把它理解成某种加权,但名称不重要。而它恰好可以被规整为一种简洁的递推式:
V n = ( 1 − β ) ∗ V n − 1 + β ∗ C V_n=(1-\beta)*V_{n-1}+\beta*C Vn=(1−β)∗Vn−1+β∗C
这就是历史记忆的运转方式。指数移动平均的本质在于一个样本的影响力以何种程度衰减到微不足道的地步,毕竟我们没人在乎自己 1 万年前的祖先是吃肉还是喝粥。
每个时代都认为自己的时代最特殊,最重要,但很快就被下个时代取而代之,淹没在历史长河。谁都逃不过指数移动被平均,过不了 100 年,人人乐道的改变世界的信息时代也将不过是一场平凡的技术革新罢了。
beta 如何选择取决于你想保存多久的记忆,或者说你容忍多久以前的采样可以忽略不计。
如果你希望的记忆周期为 100,在上述集合 V 中,数到第 100 个元素,它的衰减系数是集合 F 的第 100 项 (1 - beta)^99,只要它足够小,它后面的就相当于被彻底遗忘忽略不计了。
多小算足够小呢?取决于你自己。比如你认为 0.2 就足够小了,那就求解 (1 - beta)^99 > 0.2,选择一个 beta 即可。
前几天我论述的 dctcp,alpha 的系数 g 如何算呢:
α = ( 1 − g ) ∗ α + g ∗ F \alpha=(1-g)*\alpha+g*F α=(1−g)∗α+g∗F
一个 F 需要延展到整个拥塞周期,在该周期内它均需要表现出影响力,设一个拥塞周期为 T,选定一个足够小到不被在乎的数 Q,只要在满足 ( 1 − g ) T > Q (1-g)^T>Q (1−g)T>Q的 g 调得一手好参数即可。
如果既不知道什么是足够小,也不知道采样值的影响力周期,那就选择 1 / e 好了,因为 ( 1 − r ) 1 r (1-r)^{\frac{1}{r}} (1−r)r1 的极限就是 1 / e,此时就求 ( 1 − β ) 1 β = 1 e (1-\beta)^{\frac{1}{\beta}}=\dfrac{1}{e} (1−β)β1=e1 或 β 1 1 − β = 1 e \beta^{\frac{1}{1-\beta}}=\dfrac{1}{e} β1−β1=e1就好,取决于你偏好当前还是偏好过往。
浙江温州皮鞋湿,下雨进水不会胖。
这篇关于浅谈指数移动平均(ema)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!