平滑/过滤数据流的最佳方法

时间:2018-12-31 23:32:09

标签: filter stream smoothing

我有一个整数数据流(数据随时间流逝),看起来像这样。

[46,46,46,47,47,47,47,47,47,46,47,47,47,47,47,47,46,47,47, 47,47,47,47,47,4647,46,46,46,46,46,46,46,100,100,100,70,100, 100]

基本上是整数流,最后一个整数显示在屏幕上。有时,噪声(一个“坏”整数)会在短时间内显示,导致屏幕闪烁该整数。我想通过不显示噪音来避免这种闪烁。

我想过滤/删除仅连续出现1-2次的数字,因为它们通常是噪音。如果有一个新的整数,则取决于下一个1-2个整数是否相同,这可能是噪声。

稍有延迟是可以的。我想避免对数据进行平均,因为如果数字从40跳到100,我希望它不要oop到100(即40、60、80、100),而是在被认为不是时立即变为100。噪音。

平滑/过滤此类数据的最佳技术是什么?

1 个答案:

答案 0 :(得分:1)

首先,我不是信号处理专家,但是我有一些基本的经验(我们称之为)。另外,我还看到了您的其他(可能是相关的)问题,并且您在谈论调谐器和音符。假设这与该问题有关(?)。

简短答案:


您可以将局部短缓冲区过滤与中值或模式一起使用。按照您所描述的那样,以最简单的形式,您可以“安全地”消除超出一些预定义的噪声阈值并且在当前缓冲区中仅出现一次的值。

长答案:


在统计信息中,除了标准MODEAVERAGE之外还有MEDIAN

以整个39个值的数组为例,您在问题中给出了一个例子:

main_array_values_by_occurrence = [46 => 13次,47 => 20次,70 => 1次,100 => 5次]

average = 54.05 => 54 rounded
median  = 47
mode    = 47

Mode和Median函数可以帮助您确定哪个值应该是代表值。本质上,模式类似于通过出现和值升序对值进行排序,但是在多模式分布中,它并不总是清楚其值是什么。

您会发现,在偶尔出现尖峰(特别是大尖峰)的情况下,使用平均值并不是那么好。

中位数作为比较算法的主要候选者听起来很有吸引力,但是您应该使用什么呢?中位数还是模式?这实际上取决于您正在使用的数据类型及其分布。例如,如果说我们正在检测一种乐器的音高(音符)并且我们的检测器具有不错的准确性,那么模式方法听起来是一个不错的选择,因为中位数可能会产生误导。如果我们的调谐器检测到60%的时间笔记A4和40%的时间其他笔记,则在“平均”上它检测到A4,因为该音调在我们的数据流中占主导地位。上面的链接here上也有关于模式用例的更多信息。


首先,捕获一组5个连续值(任意缓冲区大小或“扫描”间隔)的流:缓冲区越小意味着效率越低;缓冲区越大意味着分辨率越低且延迟越长,并将它们存储在数组中:

array_1 = [46 (first in) 46 46 47 47 (last in)]

如果您希望数据大部分保持不变,也可以将它们分组(按发生次数计数)。这将为您捕获的组提供一些开始分析点。

array_1_occur = [46 => 3 47 => 2]

然后,您可以使用简单的比较算法以连续的方式确定它们之间的相对差异;您可以将这些值和+/-差异存储在单独的数组中。

array_1_diff = [0 0 0 +1 +1]

在此阶段,最简单的过滤可能很容易,所有超过阈值且出现率较低(例如<2)的值都可以立即消除。如果希望使其更健壮,则还必须考虑下一个缓冲区批处理,并且仅当它们是本地组(包括邻居)中的真正单个实例时才删除它们。

您需要为“噪声”定义一个阈值,为简单起见将其称为“噪声阈值”或容差。说,如果仅出现一次的值从上一个缓冲区的中值或众数跳到+10,则会将其“标记为”噪声并进行进一步分析。

array_2 = [46 46 90 47 47]

array_2_min = 46
array_2_max = 90
array_2_avg = (46+46+90+47+47) : 5 = 55.2
array_2_local_avg_ref = round(55.2) = 55 ( <-- useless in this case because median() value 47 is VERY DIFFERENT from average value! => thus we DISCARD it from analysis and mark value of 90 as a major SUSPECT )

对于array_1示例:

array_1_avg = 46
array_1_med = 47 (you order values from lowest to largest and take the middle one as median)
array_1_mod = 46 (not sure 100% about bi-modal or multi-modal cases at least in Excel a value of 46 is returned possibly as the lowest integer with highest occurrence in the ordered list. You can customize that in the event of multi-mode or no mode distribution algorithm fallback to median)

然后,您必须确定是要丢弃它还是保留它。

如何?好吧,如果在5个值的数组中,除单个数据点外,所有值都是〜相同(就容差而言),则显然是一个嘈杂的候选对象。可以从中间值或众数值比较中确定。最糟糕的情况是该组包含所有5个不同的值。在这种情况下,将最接近上一个捕获组的值的值作为参考点。但是,如果下一个5数组包含与嘈杂候选者相同范围内的所有值,该怎么办?因此,出于这个原因,我们需要将其保留到下一个5个值进行比较和分析。如果候选人离“规范”还差得很远,我们可以确认这是噪音还是类似随机的奇异事件(无关紧要)。另一方面,如果我们发现至少有一个比它接近的值(记住阈值或步长),而不是我们保持它。

对于基本N = 2(过去+现在)或N = 3(过去+现在+未来)甚至更多,输出流中的延迟将至少为N x buffer_length个数据点(样本)。


一些简单的观察结果:如果步长仅为+/- 1,则任何从“范数”跳出的值都将被视为噪声。问题是,如果值开始波动很大,例如,每个连续样本分别为+/- 1(振荡事件),该怎么办?在那种情况下,您将很难确定什么是“范数”,因为您只能使用整数。可以通过保持例如最后15-50-100个数据样本的平均值并在这种情况下(没有变化)获取最后一个稳定值来解决该问题。

“理想情况下”,您应该保留3 *个缓冲区:用于分析的当前和将来的缓冲区。当前需要参考上一个参考,而改善瞬变(在半稳定流中跳转到新值)则需要“未来”参考。

实际上,您不需要3(或N)个缓冲区。一个缓冲区就可以了,但是您可以在内部将其拼接为多个部分(例如,将15个样本的缓冲区内部划分为3个部分),这将大大简化处理(这一部分可能并不明显,因此我已经提到了)。 / p>

无论如何,您都需要分析样本,尝试确定样本分布,然后构建算法并尝试实际数据流并对其进行调整。并且不可避免地,您将失去某些频率或空间分辨率(取决于信号的类型),这些分辨率或频率分辨率取决于本地组(缓冲区)的长度。

当然,使用某些条件(例如检查当前样本与中值/众数值之间的距离并去除有噪声的样本)有点作弊,因为它不是像卷积之类的“真实” NR算法。在这种情况下,这是捷径。

除非创建一个非常大的缓冲区,然后使用学习或慢速适应的局部组算法来最大程度地减小波动(噪声),但要尽可能多地保留您明确提到的瞬态,否则,将永远无法完全消除波动。对于延迟至关重要的“实时”信号/流,您必须保持最小的缓冲,从而消除了“理想”滤波的可能性。