You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何SciPy find_peaks无法识别部分峰值?参数优化咨询

问题描述

使用SciPy的find_peaks函数自动识别峰值时遇到参数优化困境:

  • 数据已完成归一化和最小-最大缩放,取值范围为0-1
  • 设置prominence=0.01时,部分视觉上显著的峰值无法被识别
  • 将prominence调低至小于0.01,会捕获大量噪声点

当前使用的峰值计算代码:

import numpy as np
from scipy.signal import find_peaks

def find_peaks_relative_height(data, threshold_factor=0.01):
    """Find peaks in data using relative height threshold."""
    threshold = (np.amax(data) - np.amin(data)) * threshold_factor
    peaks, _ = find_peaks(data, prominence=threshold)
    return peaks

图示情况:

  • 两张叠加图:一张标记噪声点为峰值,另一张无标记峰值
  • find_peaks未识别出显著峰值的图表
  • 标记大量噪声点为峰值的图表
解决思路

1. 结合多参数过滤噪声

不要仅依赖prominence,同时设置width、height、distance等参数缩小有效峰值范围:

  • width:限制峰值最小宽度,过滤尖锐噪声点
  • height:设置峰值最小高度,确保只保留高于阈值的峰值
  • distance:限制峰值间最小间隔,避免密集噪声被误判

示例代码:

def find_peaks_with_multi_params(data):
    peaks, properties = find_peaks(
        data,
        prominence=0.01,
        height=0.1,  # 仅保留高度≥0.1的峰值,可按需调整
        width=2,     # 峰值至少覆盖2个数据点,过滤单噪声点
        distance=5   # 两个峰值至少间隔5个数据点
    )
    return peaks

2. 先平滑数据再识别峰值

通过平滑算法过滤高频噪声,同时保留真实峰值的形状:

移动平均平滑

def moving_average(data, window_size=3):
    return np.convolve(data, np.ones(window_size)/window_size, mode='same')

# 平滑后再找峰值
smoothed_data = moving_average(your_data, window_size=5)
peaks = find_peaks_relative_height(smoothed_data, threshold_factor=0.01)

Savitzky-Golay滤波(更适合保留峰值特征)

from scipy.signal import savgol_filter

smoothed_data = savgol_filter(your_data, window_length=5, polyorder=2)
peaks = find_peaks_relative_height(smoothed_data, threshold_factor=0.01)

3. 自定义局部prominence阈值

避免用全局极值计算阈值,针对每个峰值的局部邻域计算突出度:

def find_peaks_local_prominence(data, window_size=20):
    peaks = []
    for i in range(1, len(data)-1):
        # 先判断是否为局部最大值
        if data[i] > data[i-1] and data[i] > data[i+1]:
            # 取局部窗口内的最小值作为基准
            local_min = np.min(data[max(0, i-window_size):min(len(data), i+window_size)])
            prominence = data[i] - local_min
            if prominence >= 0.01:
                peaks.append(i)
    return np.array(peaks)

4. 利用prominence的高级参数

通过wlen指定计算突出度的局部窗口范围,避免全局极值干扰:

peaks, properties = find_peaks(
    data,
    prominence=0.01,
    wlen=30  # 仅在当前点前后30个数据点范围内计算prominence
)

内容的提问来源于stack exchange,提问作者Max Tsai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 21:23:15