移动平均线与移动中位数

信息处理 移动平均线 窗户 中值滤波器
2021-12-25 12:19:58

我在很多地方读到,对于某些应用程序来说,移动中位数移动平均线要好一些,因为它对异常值不太敏感

我想在真实数据上测试这个断言,但我看不到这种效果(绿色:中值,红色:平均值)。看这里:

在此处输入图像描述


这是示例音频数据 test.wav这是Python代码:

import numpy as np
from scipy.io.wavfile import read
import matplotlib.pyplot as plt

def median(lst): return np.median(np.array(lst))
def mean(lst): return sum(lst)/len(lst)

(fs, x) = read('test.wav')

x = abs(x)
env = np.zeros_like(x)
env2 = np.zeros_like(x)

for i in range(len(x)):
    env[i] = median(x[max(i-1000,0):i+1])
    env2[i] = mean(x[max(i-1000,0):i+1])
 
plt.plot(range(len(x)), env, color = 'green')
plt.plot(range(len(x)), env2, color = 'red')
plt.show()

我尝试了不同的窗口宽度值(在代码中:1000),它总是一样的:移动中位数并不比移动平均线好(即对异常值不那么敏感)。


Window width = 10000 (10000 >> the peak width) 相同:

在此处输入图像描述


题:

您能否提供一个示例,表明移动中位数对异常值的敏感度低于移动平均线?如果可能,请使用示例 .WAV 文件数据集(下载链接)。

是否可以对这些数据进行移动中位数,使得结果就像这条黄色曲线?(即没有更多的尖峰!)

在此处输入图像描述

3个回答

移动中位数总是对异常值不那么敏感吗?有时。如果您的峰值非常短(最好比中值/平均样本量短),它将起作用。然而,如果你有一个的尖峰,那么取中位数无助于消除尖峰。

长钉

我已经使用数据集说明了这一点(样本大小 = 5,考虑到 2 个左侧条目和 2 个右侧条目):

Orig. Median Avg.
Data  Filter Filter
-----------------
1       
2       
3      3    3
4      4    4
5      5    11.6
6      6    19
40     40   26.2
40     40   33.2
40     40   33.4
40     40   27
7      9    20.8
8      9    14.8
9      9    9
10     10   10
11      
12

在此处输入图像描述

注意所有 40 的中位数是 40。例如,取第一个 40。左边的值为 5,6,右边的值为 40,40,所以我们得到一个排序数据集 5,6, 40, 40,40(粗体的 40 成为我们的中值滤波结果)。

短尖峰

您还想要一个中值滤波器工作的示例。所以,我们会有一个短暂的峰值。尝试这个:

Orig. Median Average
Data  Filter Filter
-----------------
1       
2       
3      3    3
4      4    10.8
5      5    11.6
40     6    12.4
6      7    13.2
7      8    14
8      8    8
9       
10

在此处输入图像描述

您可以看到中值过滤器确实过滤掉了单个大尖峰,而尖峰使平均过滤器的条目结果偏斜4,5,40,and,6

这不是一个真正的答案,但我想我会报告我所看到的并询问更多信息。

我已经加载了你的test.wav文件,我可以看到下面绘制的信号。

在此处输入图像描述

因此,您在显示的图中得到的并不是中值,而是更像是信号的包络。

第二个问题是信号实际上似乎是信号的一部分。如果我放大光点,那么这就是我所看到的:

在此处输入图像描述

你真正想要达到什么目的?


感谢您的反馈。下面是一些R执行以下操作的代码:

  • 加载 wav 文件。
  • 获取信号的绝对值(由waveR库加载到左声道)。
  • 对数据执行 100 长度的移动平均滤波器,以获得更接近“包络”(红色信号)的数据。
  • 然后将长度为 201、2001 和 4001 的中值滤波器应用于结果(蓝色信号)。

从下面的图中,表现最好的是 4001 长度之一。否则故障的影响仍然存在。

不同窗口长度的中值滤波版本

我现在唯一能看到的错误是“信封”与我想要的真正的信封不匹配。更好的包络检测器可能会改善这一点(例如分析信号等)。

下面是计算的中值滤波包络覆盖在原始信号上的图。

在此处输入图像描述


下面的R代码

#27349
#install.packages("tuneR")
library(tuneR)
x <- readWave("Q27349/test.wav")    
sig <- x@left    
abssig <- abs(sig)    
N <- 100
filtabssig <- filter(abssig, rep(1/N,N))    
plot(abs(filtabssig))    
med <- 0*filtabssig    

N2median <- 1000 # Window length is 2 * N2median + 1
for (k in 1:length(filtabssig))
{
  idxs = seq(max(1,k-N2median), min(length(filtabssig), k+N2median),1)
  med[k] = median(filtabssig[idxs])
}

par(mfrow=c(3,1))
plot(filtabssig, col="red")
lines(med200,col="blue")
title("Median filter length of 201")

plot(filtabssig, col="red")
lines(med1000,col="blue")
title("Median filter length of 2001")

plot(filtabssig, col="red")
lines(med2000,col="blue")
title("Median filter length of 4001")

你说的是正确的 - 移动中位数对异常值不太敏感,其中异常值通常是时间序列中的单个点,与所有其他点非常不同,这可能是由于某种错误。移动中值滤波器只是从结果中删除异常值,其中移动均值/平均值始终考虑每个点。但是,移动中位数可能对跨越多个点的短期显着峰值更加敏感,尤其是当它们跨越移动窗口的一半以上时。