在不同时间采样的指数移动平均线

Posted

技术标签:

【中文标题】在不同时间采样的指数移动平均线【英文标题】:Exponential Moving Average Sampled at Varying Times 【发布时间】:2010-11-04 15:54:54 【问题描述】:

我有一个连续值,我想计算一个exponential moving average。通常我会为此使用标准公式:

Sn = αY + (1-α)Sn-1

其中 Sn 是新的平均值,α 是 alpha,Y 是样本,Sn-1 是之前的平均值。

很遗憾,由于各种问题,我没有一致的采样时间。我可能知道我最多可以采样一次,例如每毫秒一次,但由于我无法控制的因素,我可能无法一次采样几毫秒。然而,一个可能更常见的情况是,我稍微早一点或晚一点地进行简单采样:而不是在 0、1 和 2 毫秒进行采样。我在 0、0.9 和 2.1 ms 采样。我确实预计,无论延迟如何,我的采样频率都会远远高于奈奎斯特极限,因此我不必担心混叠。

我认为我可以通过根据自上次采样以来的时间长度适当地改变 alpha 以或多或少合理的方式处理此问题。

我认为这会起作用的部分原因是 EMA 在前一个数据点和当前数据点之间“线性插值”。如果我们考虑以间隔 t 计算以下样本列表的 EMA:[0,1,2,3,4]。如果我们使用区间 2t,我们应该得到相同的结果,其中输入变为 [0,2,4],对吧?如果 EMA 假设,在 t2,自 t0 以来的值一直是 2,这将与在 [0,2, 2,4,4],它没有这样做。还是说这有道理?

有人能告诉我如何适当地改变 alpha 吗? “请展示你的作品。”即,向我展示证明您的方法确实在做正确事情的数学。

【问题讨论】:

您不应该为不同的输入获得相同的 EMA。将 EMA 视为一个过滤器,以 2t 采样相当于下采样,过滤器将给出不同的输出。这对我来说很清楚,因为 [0,2,4] 包含比 [0,1,2,3,4] 更高的频率分量。除非问题是,我如何动态更改过滤器以使其提供相同的输出。也许我错过了什么? 但输入并没有什么不同,只是采样频率较低。间隔 2t 的 [0,2,4] 就像间隔 t 的 [0,,2,,4] ,其中 _ 表示样本被忽略 【参考方案1】:

这个答案基于我对低通滤波器的良好理解(“指数移动平均线”实际上只是一个单极点低通滤波器),但我对您正在寻找的东西的理解模糊。我认为以下是您想要的:

首先,您可以稍微简化一下方程式(看起来更复杂,但在代码中更容易)。我将使用“Y”作为输出,“X”作为输入(而不是 S 作为输出,Y 作为输入,就像你所做的那样)。

Yn = αX + (1-α)Yn-1 → Yn = Yn-1 + α(X - Yn-1)

哪些代码:

 Y += alpha * (X-Y);

其次,这里的α值“等于”1-e-Δt/τ 其中Δt是样本之间的时间,τ是低通滤波器的时间常数。我用引号说“相等”,因为当 Δt/τ 小于 1 并且 α = 1-e-Δt/τ ≈ Δt/τ 时,这很有效。 (但不会太小:您会遇到量化问题,除非您采用一些奇特的技术,否则您通常需要在状态变量 S 中额外增加 N 位分辨率,其中 N = -log2 (α)。) 对于较大的 Δt/τ 值,过滤效果开始消失,直到达到 α 接近 1 的点,并且您基本上只是将输入分配给输出。

这应该适用于不同的 Δt 值(只要 alpha 很小,Δt 的变化并不是很重要,否则您会遇到一些相当奇怪的 Nyquist 问题/混叠/等),如果您正在工作在乘法比除法便宜或定点问题很重要的处理器上,预先计算 ω = 1/τ,并考虑尝试逼近 α 的公式。

如果你真的想知道如何推导出公式

α = 1-e-Δt/τ

然后考虑它的微分方程来源:

Y + τ dY/dt = X

当 X 为单位阶跃函数时,其解 Y = 1 - e-t/τ。对于较小的 Δt 值,导数可以近似为 ΔY/Δt,得到

Y + τ ΔY/Δt = X

ΔY/Δt = (X-Y)/τ

ΔY = (X-Y)(Δt/τ) = α(X-Y)

而 α = 1-e-Δt/τ 的“外推”来自于尝试将行为与单位阶跃函数情况相匹配。

【讨论】:

是的,这正好解决了我的问题,基本上是在方程中引入 delta-t。我也非常感谢额外的实现提示,以及简洁的替代描述,“单极低通滤波器”。 您能否详细说明“尝试匹配行为”部分?我了解您的连续时间解决方案Y = 1 - exp(-t/τ) 及其对幅度为x 和初始条件y(0) 的缩放阶跃函数的推广,但我不知道如何将这些想法结合在一起以实现您的结果。 在 t = (delta t) = 第一个离散时间步计算连续和离散版本,并计算 alpha 以使连续和离散结果具有相同的值 如果 Δt 变为 0,则 α 也变为 0 - 所以 Y 不变。仅当 Y 已经代表大量事件时,这似乎才是正确的。例如,如果只有两个事件是同时发生的,那么“正确”答案不应该是两者的平均值吗?【参考方案2】:

看看这里:http://www.eckner.com/research.html

请看第二个链接:《不均匀时间序列的算法:移动平均线和其他滚动运算符》

我认为该文档准确地描述了您需要的编程算法。

【讨论】:

鼓励链接到外部资源,但请在链接周围添加上下文,以便您的其他用户了解它是什么以及为什么存在。始终引用重要链接中最相关的部分,以防目标站点无法访问或永久离线。【参考方案3】:

这不是一个完整的答案,但可能是一个开始。这是我在一个小时左右的比赛中得到的。我将其发布为我正在寻找的一个示例,并可能对解决此问题的其他人有所启发。

我从 S0 开始,它是前一个平均值 S-1 和在 t 时取的样本 Y0 的平均值0。 (t1 - t0) 是我的采样间隔,α 设置为适合该采样间隔和我希望平均的时间段的任何值。

我考虑过如果我错过了 t1 时的样本会发生什么,而不得不处理在 t2 时采集的样本 Y2 >?好吧,我们可以先扩展等式,看看如果我们有 Y1 会发生什么:

S2 = αY2 + (1-α)S1,其中 S1 = αY 1 + (1-α)S0

代入:

S2 = αY2 + (1-α)(αY1 + (1-α)S0) S2 = αY2 + (1-α)αY1 + (1-α)(1-α)S0 S2 = αY2 + (1-α)αY1 + (1-α)2S0

我注意到这个数列似乎以这种方式无限延伸,因为我们可以无限期地替换右侧的 Sn

S2 = αY2 + (1-α)αY1 + (1-α)2(αY0 + (1-α)S-1) S2 = αY2 + (1-α)αY1 + (1-α)2αY0 + (1-α)3S-1

好的,所以它不是一个真正的多项式(我真傻),但是如果我们将初始项乘以 1,我们就会看到一个模式:

S2 = (1-α)0αY2 + (1-α)αY1 + (1-α)2αY0 + (1-α)3S-1

嗯:这是一个指数级数。 Quelle 惊喜! 想象一下,从等式中得出指数移动平均线!

所以无论如何,我有这个 x0 + x1 + x2 + x3 + 。 .. 事情进展顺利,我敢肯定我闻到了e 或自然对数的味道,但我不记得在没时间之前我接下来要去哪里。

【讨论】:

【参考方案4】:

此问题的任何答案,或此类答案正确性的任何证明,很大程度上取决于您测量的数据。

如果您的样本是在 t0=0ms 、t1=0.9ms 和 t2=2.1ms 采集的,但您可以选择的 α 基于 1-ms 间隔,因此您需要一个局部调整的 αn ,选择正确性的证明意味着知道 t=1ms 和 t=2ms 的样本值。

这就引出了一个问题:您能否合理地插值您的数据,以合理猜测中间值可能是什么?或者您甚至可以对平均值本身进行插值吗?

如果这些都不可能,那么据我所知,中间值 Y(t) 的逻辑选择是最近计算的平均值,即 Y(t) ≈ Sn 其中 n 是最大值使得 tn

这个选择有一个简单的结果:不管时间差是多少,不要管 α。

另一方面,如果可以对您的值进行插值,那么这将为您提供平均的恒定间隔样本。最后,如果甚至可以对平均值本身进行插值,那会使这个问题变得毫无意义。

【讨论】:

我认为我可以对我的数据进行插值:鉴于我以离散间隔对其进行采样,我已经使用标准 EMA 这样做了!无论如何,假设我需要一个“证明”来证明它与标准 EMA 一样有效,如果值在采样周期之间变化不相当平稳,它也会产生不正确的结果。 但这就是我要说的:如果你认为 EMA 是你的值的插值,那么如果你保持 alpha 不变,你就完成了(因为插入最近的平均值,因为 Y 没有改变平均值)。如果您说您需要“与标准 EMA 一样有效”的东西 - 原件有什么问题?除非您对所测量的数据有更多信息,否则对 alpha 的任何局部调整充其量都是任意的。 所以你是说在 1 秒或 10 秒内从 1 变为 2 应该对 100 秒移动平均线产生相同的影响? 如果用当前移动平均线的值填充缺失值,情况正是如此,因为 S_new = alpha * Y + (1-alpha) * S_old = alpha * S_old + (1 -alpha) * S_old = S_old . 对,这就是为什么我相信你不想那样做。直观地说,移动平均线不会认为信号一直是从 t(n) 到 t(n+1) 的先前平均值,在 t(n+1) 处突然更改为新样本,否则它会改变平均值的幅度比它所做的要小得多,因为信号与之前的平均值处于不同的水平只有一个无限小的时间长度。【参考方案5】:

通过使用稍有不同的 α,等于 (1-α问题中的那个),基本公式将新值 Y 添加到 S0 的现有平均值 看起来像这样:

S(Y,S0) =

(1-α)Y + αS0 =

Y - αY + αS0 =

Y + α(S0-Y)

如果我们现在添加时间间隔 t 的长度并假设只有 α 取决于该 t,那么该公式如下所示:

S(Y,t,S0) = Y + αt(S0-Y)

现在假设 t = t1 + t2。如果通过将时间间隔 t1 和 t2 的两个 Y 值相加来创建平均值,则生成的平均值如下所示:

S(Y,t2, S(Y,t1,S0)) =

Y + αt2(S(Y,t1,S0) - Y) =

Y + αt2((Y + αt1(S0-Y)) - Y) =

Y + αt2αt1(S0-是)

如果这个平均值应该与一次性添加整个 t 区间相同,则 αt = αt1αt2。满足此要求的 α 定义为:

αx := Ax     (对于某个常数 A)

因为:

αt = At = At1 + t2 = At1 At2 = αt1αt2

这会产生以下平均函数:

S(Y,t,S0) = Y + At(S0-Y)

我还没有真正测试过这个,但如果我做出的假设适合你的场景,这看起来像是一个平均函数,可以很好地处理采样间隔的变化。

【讨论】:

这看起来或多或少是我想到的解决方案。不幸的是,我现在还不能完全遵循这个证明,但我会在接下来的一两天内坐下来更仔细地研究一下。【参考方案6】:

假设我们想要对一个连续函数进行指数衰减平均。但是,我们没有该函数的所有值,只有几个样本。这个公式将对我们拥有的样本和它们在连续平均中的权重进行加权平均。

乘数n = Alpha时间n-时间n-1

Sumn = Valn + Sumn-1*乘数n

Countn = 1 + Countn-1*乘数n

平均n = Sumn/Countn

【讨论】:

检查***.com/editing-help,***.com/questions/31657/… 你也可以看看其中一篇帖子的源码:***.com/revisions/… 我使用HTML的supsub标签做上标和下标,并使用*作为等式的开头,上下各空一行。【参考方案7】:

我会保留alpha 的值,并填写缺失的数据。

由于您不知道在无法采样期间会发生什么,您可以用 0 填充这些样本,或者保持之前的值稳定并将这些值用于 EMA。或者,一旦有了新样本,就进行一些反向插值,填充缺失的值,然后重新计算 EMA。

我想要得到的是你有一个输入x[n],它有孔。没有办法解决您丢失数据的事实。因此,您可以使用零阶保持,或将其设置为零,或在x[n]x[n+M] 之间进行某种插值,其中M 是缺失样本的数量,n 是间隙的开始。甚至可能使用n 之前的值。

【讨论】:

从花了一个小时左右的时间来计算这个,我认为简单地改变 alpha 实际上会给我你所说的两点之间的适当插值,但是在更简单的方法。此外,我认为改变 alpha 也将适当地处理在标准采样间隔之间采集的样本。换句话说,我正在寻找您所描述的内容,但尝试使用数学来找出简单的方法。 我认为没有“适当插值”这样的野兽。你根本不知道在你不取样的时候发生了什么。好的和坏的插值意味着你错过了一些知识,因为你需要根据它来判断插值是好还是坏。尽管如此,您可以设置约束,即最大加速度、速度等。我认为,如果您确实知道如何对丢失的数据进行建模,那么您只需对丢失的数据进行建模,然后应用 EMA 算法而不做任何更改,而不是而不是改变阿尔法。只是我的 2c :) 这正是我在 15 分钟前对问题进行编辑时所要表达的意思:“你根本不知道在你不取样的时候发生了什么”,但即使你在每个指定的时间间隔采样。因此,我的奈奎斯特设想:只要您知道波形的方向变化不超过每两个样本,实际的样本间隔就无关紧要,并且应该能够变化。在我看来,EMA 方程的计算就像波形从最后一个样本值线性变化到当前值一样。 我不认为这是完全正确的。奈奎斯特定理要求每个周期至少需要 2 个样本才能唯一识别信号。如果你不这样做,你就会得到别名。这与采样 f_s1 一段时间,然后是 f_s2,然后返回 f_s1 相同,如果 f_s2 低于 Nyquist 限制,则当您使用 f_s2 采样时,数据中会出现混叠。我还必须承认,我不明白您所说的“波形从最后一个样本线性变化到当前样本”是什么意思。你能解释一下吗?干杯,史蒂夫。 对。假设我的标称采样率是每个周期 250 个样本,但它可能会下降到每个周期十几个样本。我认为这仍然给我留下了很高的采样频率。【参考方案8】:

这类似于我的待办事项列表中的一个未解决的问题。我已经在某种程度上制定了一个方案,但还没有数学上的工作来支持这个建议。

更新和总结:希望保持平滑因子 (alpha) 独立于补偿因子(我在这里称为 beta)。 Jason 在这里已经接受的出色答案对我很有用。

第一步。

如果您还可以测量自上次采样以来的时间(以恒定采样时间的四舍五入倍数 - 因此自上次采样以来的 7.8 毫秒将是 8 个单位),则可用于多次应用平滑。在这种情况下,应用公式 8 次。您有效地使平滑更偏向当前值。

第二步。

为了获得更好的平滑效果,我们需要调整 alpha,同时在前一种情况下应用公式 8 次。

这种平滑近似会遗漏什么?

上面例子中已经漏掉了 7 个样本 这是在第 1 步中通过扁平化将当前值再应用 7 次近似得出的 如果我们定义一个将与 alpha 一起应用的近似因子 beta(作为 alpha*beta 而不仅仅是 alpha),我们将假设 7 个未命中样本在先前样本值和当前样本值之间平稳变化。

【讨论】:

我确实考虑过这个问题,但是对数学的一些思考让我相信,与其将公式与样本值一起应用八次,我可以进行计算一个新的 alpha 将允许我应用公式一次,并给我相同的结果。此外,这将自动处理样本与精确采样时间偏移的问题。 单应用就好。我还不确定 7 个缺失值的近似值有多好。如果连续移动使值在 8 毫秒内抖动很大,则近似值可能与现实完全不同。但是,如果您以 1 毫秒(不包括延迟样本的最高分辨率)进行采样,您已经认为 1 毫秒内的抖动是不相关的。这种推理对你有用吗(我仍在努力说服自己)。 哦,等等,你是说你可以计算一个新的 alpha 常数,无论采样延迟如何都可以一直使用?我觉得不太可能。 我是说可以根据参考 alpha 以及实际区间与参考区间之间的差异来计算任何区间的新 alpha。 对。这是我描述中的因子 beta。将基于差异间隔以及当前和先前的样本来计算 beta 因子。新的 alpha 将是 (alpha*beta) 但它将仅用于该样本。虽然您似乎在“移动”公式中的 alpha,但我倾向于使用恒定的 alpha(平滑因子)和独立计算的 beta(一个调整因子)来补偿刚刚错过的样本。

以上是关于在不同时间采样的指数移动平均线的主要内容,如果未能解决你的问题,请参考以下文章

在python中计算指数移动平均线

简单移动平均线加权移动平均线指数平滑移动平均

PySpark:计算指数移动平均线

在 C++ 中实现指数移动平均线

如何计算postgres的指数移动平均线?

MACD 指标