随着时间的推移平滑值:移动平均值或更好的东西?

时间:2010-09-21 13:01:21

标签: algorithm theory moving-average

我正在编写一些东西,我正在从硬件指南针中随着时间的推移获取一堆值。这个指南针非常准确并且经常更新,结果是如果它略微摇晃,我最终会得到与其邻居非常不一致的奇数值。我想要平滑这些价值。

做了一些阅读后,看起来我想要的是高通滤波器,低通滤波器或移动平均器。我可以得到移动平均线,只保留最后5个值或其他值的历史记录,并使用我的代码中下游的那些值的平均值,我曾经只使用最近的值。

我认为应该很好地消除那些摇摆不定的情况,但是我觉得这可能是非常低效的,这可能是正确编程人员的一个已知问题,其中有一个非常巧妙的Clever Math解决方案。

然而,我是那些可怕的自学成才的程序员之一,在与CompSci或Math几乎模糊不清的任何事情上没有一丝正规教育。稍微阅读一下就表明这可能是一个高通或低通滤波器,但是我找不到任何可以理解为像我这样的黑客可以理解这些算法对一系列值的影响的术语,更不用说如何数学运作。例如,here给出的答案在技术上确实回答了我的问题,但只能用那些可能已经知道如何解决问题的人理解。

这将是一个非常可爱和聪明的人,他可以用艺术毕业生可以理解的方式来解释这个问题以及解决方案的工作原理。

5 个答案:

答案 0 :(得分:56)

如果您尝试删除偶尔的奇数值,则低通滤波器是您已识别的三个选项中最好的。低通滤波器允许低速变化,例如手动旋转罗盘引起的变化,同时拒绝高速变化,例如道路颠簸造成的变化。

移动平均线可能不够,因为数据中单个“blip”的影响会影响几个后续值,具体取决于移动平均窗口的大小。

如果很容易检测到奇数值,你可能会更好地使用完全忽略它们的毛刺消除算法:

if (abs(thisValue - averageOfLast10Values) > someThreshold)
{
    thisValue = averageOfLast10Values;
}

这是一个用于说明的guick图:

graph comparison

第一个图是输入信号,带有一个令人不快的故障。第二张图显示了10个样本移动平均线的影响。最终图表是10样本平均值和上面显示的简单毛刺检测算法的组合。检测到毛刺时,使用10个样本平均值而不是实际值。

答案 1 :(得分:37)

如果你的移动平均线必须很长才能达到所需的平滑度,并且你真的不需要任何特定形状的内核,那么如果你使用指数衰减的移动平均线你会更好:

a(i+1) = tiny*data(i+1) + (1.0-tiny)*a(i)

你选择tiny作为一个合适的常数(例如,如果选择微小= 1/1 / N,它将具有与大小为N的窗口相同的平均值,但在旧点上的分布不同)。

无论如何,由于移动平均线的下一个值仅取决于前一个值和您的数据,因此您不必保留队列或其他任何内容。而且你可以把它想象成这样的事情:“好吧,我有一个新的观点,但我真的不相信它,所以我将保留80%的旧测量估计,并且只有相信这个新数据点20%“。这几乎与说“嗯,我只相信这个新点20%,我将使用其他4个我信任相同数量的点”,除了不是明确地采取其他4个点,你是假设你上次做的平均值是明智的,所以你可以使用以前的工作。

答案 2 :(得分:6)

  

移动平均线我可以贬低......   但它可能会让我感到震惊   非常低效。

移动平均线真的没有理由效率低下。您将所需的数据点数保留在某个缓冲区中(如循环队列)。在每个新数据点上,弹出最旧的值并从总和中减去它,然后按最新值并将其添加到总和中。因此,每个新数据点实际上只需要弹出/推送,加法和减法。您的移动平均值始终是此移位总和除以缓冲区中的值的数量。

如果你从多个线程同时接收数据,它会得到一个技巧,但是因为你的数据来自一个对我来说非常值得怀疑的硬件设备。

哦,还有:可怕的自学成才的程序员团结起来! ;)

答案 3 :(得分:2)

如果使用正确的值,则可以“手动”计算指数衰减的移动平均线,仅使用趋势。如果您正在寻找“10%平滑的指数平滑移动平均线”,请参阅http://www.fourmilab.ch/hackdiet/e4/以了解如何使用笔和纸快速完成此操作。但是既然你有一台计算机,你可能想要进行二进制移位而不是十进制移位;)

这样,你需要的只是当前值的变量和平均值的变量。然后可以从中计算下一个平均值。

答案 4 :(得分:1)

这是一种称为距离门的技术,可以很好地处理低发生的伪样本。假设使用上面提到的一种过滤技术(移动平均值,指数),一旦你有足够的"历史记录(一个时间常数)您可以测试新的传入数据样本的合理性,之前将其添加到计算中。

需要了解信号的最大合理变化率。将原始样本与最近的平滑值进行比较,如果该差异的绝对值大于允许的范围,则该样本被抛出(或者用一些启发式替换,例如基于斜率的预测;差异或者"趋势"来自双指数平滑的预测值)