48

我正在编写一些东西,随着时间的推移,我正在从硬件罗盘中获取一堆值。这个指南针非常准确并且经常更新,因此如果它轻微晃动,我最终会得到与其邻居大相径庭的奇数值。我想平滑这些值。

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

我认为,这应该可以很好地消除这些抖动,但让我印象深刻的是它可能效率很低,这可能是正确程序员的已知问题之一,有一个非常简洁的聪明数学解决方案。

然而,我是那些糟糕的自学成才的程序员之一,在任何与 CompSci 或数学模糊相关的事情上都没有接受过任何正规教育。仔细阅读表明这可能是一个高通或低通滤波器,但我找不到任何可以用像我这样的黑客可以理解的术语解释这些算法对一组值的影响,更不用说如何数学有效。例如,此处给出的答案在技术上确实回答了我的问题,但仅以那些可能已经知道如何解决问题的人可以理解的方式回答。

这将是一个非常可爱和聪明的人,他可以用文科毕业生可以理解的术语来解释这是什么问题,以及解决方案是如何工作的。

4

5 回答 5

59

如果您尝试去除偶尔出现的奇数值,则低通滤波器是您确定的三个选项中的最佳选择。低通滤波器允许低速变化,例如用手旋转指南针引起的变化,同时拒绝高速变化,例如道路上的颠簸引起的变化。

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

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

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

这是一个快速图表来说明:

图表比较

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

于 2010-09-21T13:38:14.060 回答
39

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

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

您选择tiny适当的常数(例如,如果您选择 tiny = 1- 1/N,它将具有与大小为 N 的窗口相同的平均量,但在较旧的点上分布不同)。

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

于 2010-09-21T14:27:32.760 回答
6

移动平均线我可以接受......但令我震惊的是它可能非常低效。

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

如果您同时从多个线程接收数据,它会变得有点棘手,但是因为您的数据来自对我来说似乎非常可疑的硬件设备。

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

于 2010-09-21T13:20:21.980 回答
2

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

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

于 2010-09-21T14:39:03.470 回答
1

有一种称为范围门的技术可以很好地处理低出现率的虚假样本。假设使用上面提到的一种过滤技术(移动平均,指数),一旦你有“足够的”历史(一个时间常数),你可以在将新的传入数据样本添加到计算之前测试它的合理性。

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

于 2016-04-30T06:56:24.023 回答