Hampel滤波器

Hampel滤波器是一种基于中值和中值绝对偏差(MAD)的滤波器,旨在识别和去除时间序列数据中的异常值。相对于传统均值和标准差方法,Hampel滤波器对异常值更具鲁棒性

Hampel滤波器的核心在于中值的计算和MAD的求解。中值代表数据的中间值,而MAD度量了数据点与中值之间的离散程度

中值:

对于包含\(N\)个数据点的数据集\(X\),中值计算公式如下:

  • 如果\(N\)为奇数:中值=\(X_{\frac{N+1}{2}}\)

  • 如果\(N\)为偶数:中值=\(\frac{1}{2}(X_{\frac{N}{2}}+X_{\frac{N}{2}+1})\)

中值绝对偏差(MAD):

MAD是每个数据点\(X_i\)与数据集\(X\)的中值之间绝对差的中值:

MAD=中值(|\(X_i\)-中值(\(X\))|)

其中,\(X_i\)表示每一个数据点

Hampel滤波器异常值判定标准:

如果数据点\(X_i\)被认定为异常值(即其绝对偏差除以MAD超过阈值),那么将其替换为数据集\(X\)的中值;否则,保持数据点的原始值

\[X_i= \begin{cases} 中值(X) \quad \rm{if} \frac{|X_i-中值(X)|}{MAD}>阈值\\ X_i \quad \quad \quad \text{otherwise} \end{cases} \]

# 生成包含异常值的正弦波数据
def generate_data_with_outliers():
    time = np.linspace(0, 10, 100)
    signal = np.sin(time) + np.random.normal(0, 0.1, 100)
    # 添加异常值
    outliers_indices = [20, 40, 60, 80]
    outliers_values = [2.0, -1.9, 2.1, -0.5]
    
    for index, value in zip(outliers_indices, outliers_values):
        signal[index] = value
    return time, signal
def hampel(vals_orig, k=5, v=3):
    """
    使用Hampel滤波器去除时间序列中的异常值。
    参数:
        - vals_orig: numpy数组,原始时间序列数据
        - k: 整数,滤波器窗口的大小(半窗口大小为k/2)
        - v: 浮点数,用于异常值检测的阈值
    返回:
        - vals_filt: numpy数组,经过滤波的时间序列数据
        - outliers_indices: list,异常值的索引列表
    """
    # 创建输入数据的副本
    vals_filt = np.copy(vals_orig)
    outliers_indices = []
    # 定义Hampel滤波器函数
    n = len(vals_orig)
    for i in range(k, n - k):
        # 提取窗口
        window = vals_orig[i - k:i + k + 1]
        # 计算中值和中值绝对偏差(MAD)
        median = np.median(window)
        mad = np.median(np.abs(window - median))
        # 检查当前值是否为异常值
        if np.abs(vals_orig[i] - median) > v * mad:
            # 用中值替换异常值
            vals_filt[i] = median
            # 记录异常值的索引
            outliers_indices.append(i)
    return vals_filt, outliers_indices
    # 生成包含异常值的数据
    time, data = generate_data_with_outliers()    
    # 对数据应用Hampel滤波器
    filtered_data, outliers_indices = hampel(data)
    # 绘制原始数据和滤波后的数据
    plt.figure(figsize=(10, 6))
    plt.plot(time, data, label='origenal data')
    plt.scatter(time[outliers_indices], data[outliers_indices], c='red', 
    	marker='o', label='outliers', s=50)
    plt.plot(time, filtered_data, label='data filtered', linestyle='--', color='red')
    plt.fill_between(time, filtered_data, data, color='red', alpha=0.2, label='outliers region')
    plt.title('outliers removal using hampel identifier')
    plt.grid(True)
    plt.legend()
    plt.show()

posted @ 2024-02-16 16:46  华小电  阅读(163)  评论(0编辑  收藏  举报