峰寻找算法Python/这
-
19-09-2019 - |
题
我可以写点东西,自己找零境口岸的第一个衍生物或东西,但它似乎是一个共足够的职能包括在标准图书馆。任何人都知道的一个吗?
我的特别的应用程序是一个2D阵列,但通常会被用于寻找峰Fft),等等。
具体地说,在这些类型的问题,有多强峰,然后许多较小的"高峰",只是噪音引起的,应该被忽略。这些仅仅是示例;不我实际数据:
1维峰:
2维峰:
峰寻找算法将找到这些位置的峰值(不仅仅是他们的价值观),理想的情况就会找到真正的样本间的峰值,不只是指数的最大值,可能使用 二次插 或者什么的。
通常你只关心一些强大的山峰,所以他们要么被选中,是因为他们是上述的某一阈值,或者因为他们是第一 n 峰的有序列,排的幅度。
正如我所说的,我知道如何编写这样的东西我自己。我只是问问,如果有一个预先存在的功能或软件包,是已知的工作。
更新:
我 翻译MATLAB脚本 和它的工作体面,1-D的情况,但可能会更好。
更新更新:
sixtenbe 创造一个更好的版本 对于1-D的情况。
解决方案
我不认为你在找什么是SciPy的提供。我会写的代码自己,在这种情况下。
样条插值和从scipy.interpolate平滑是相当不错的,并且可能是在装配峰相当有益的,然后找到他们的最大值的位置。
其他提示
我在看一个类似的问题,我已经发现了一些最好的参考都来自化学(从峰的质谱数据中寻找)。对于峰值寻找算法的一个很好的全面审查阅读这个。这是的峰值寻找技术最好最清晰的评论,我已经跨越运行一个。 (小波是最适合在嘈杂的数据找到这种峰。)。
它看起来像你的山峰都有明确的规定,而不是隐藏在噪声。这是我推荐使用平滑savtizky - 格雷衍生物找到峰值的情况下(如果你只是区分以上数据你就会有误报的一个烂摊子。)。这是一个非常有效的方法,是很容易实现的(你需要一个矩阵类W /基本操作)。如果你只是找到过零点第一S-G衍生物我想你会很高兴。
该函数 scipy.signal.find_peaks
时,作为其顾名思义,就是对这项有益的。但是,要理解以及其参数width
,threshold
,distance
这是重要的,最重要prominence
,以获得良好的峰值提取。
根据我的测试和文档,这个概念的突出是“有用的概念”,以保持良好的峰值,并丢弃嘈杂的峰值。
什么是(地形)突出?它的“所必需的最小高度下降从山顶去任何地势较高” 的,因为它可以在这里看到:
的理念是:
越高突出,更“重要”的峰。
测试:
我用目的(嘈杂)频率变正弦曲线,因为它显示了许多困难。我们可以看到,width
参数并不是非常有用,因为在这里,如果你设定了最低width
太高,那么它将无法在高频部分来跟踪非常接近峰值。如果设置width
太低,你就必须在信号的左部许多不想要的峰值。同样的问题distance
。 threshold
只与直接邻居,在这里是没有用的。 prominence
是一个能提供最佳的解决方案。请注意,您可以结合许多这些参数!
代码:
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import find_peaks
x = np.sin(2*np.pi*(2**np.linspace(2,10,1000))*np.arange(1000)/48000) + np.random.normal(0, 1, 1000) * 0.15
peaks, _ = find_peaks(x, distance=20)
peaks2, _ = find_peaks(x, prominence=1) # BEST!
peaks3, _ = find_peaks(x, width=20)
peaks4, _ = find_peaks(x, threshold=0.4) # Required vertical distance to its direct neighbouring samples, pretty useless
plt.subplot(2, 2, 1)
plt.plot(peaks, x[peaks], "xr"); plt.plot(x); plt.legend(['distance'])
plt.subplot(2, 2, 2)
plt.plot(peaks2, x[peaks2], "ob"); plt.plot(x); plt.legend(['prominence'])
plt.subplot(2, 2, 3)
plt.plot(peaks3, x[peaks3], "vg"); plt.plot(x); plt.legend(['width'])
plt.subplot(2, 2, 4)
plt.plot(peaks4, x[peaks4], "xk"); plt.plot(x); plt.legend(['threshold'])
plt.show()
有是在一个名为scipy.signal.find_peaks_cwt
SciPy的一个函数,它听起来就像是适合您的需求,但我没有与它的经验,所以我不能推荐..
http://docs.scipy.org/ DOC / SciPy的/参照/生成/ scipy.signal.find_peaks_cwt.html
对于那些不一定有关其调查的算法,以利用在蟒蛇,这里一个快速概述的备选方案: https://github.com/MonsieurV/py-findpeaks
想自己一个相当于MatLab findpeaks
功能,我发现的 detect_peaks功能 从马科斯*杜阿尔特是个好赶上。
很容易使用:
import numpy as np
from vector import vector, plot_peaks
from libs import detect_peaks
print('Detect peaks with minimum height and distance filters.')
indexes = detect_peaks.detect_peaks(vector, mph=7, mpd=2)
print('Peaks are: %s' % (indexes))
这会给你:
检测峰以可靠的方式的频谱已经研究了不少,例如所有的工作就在80ies音乐/音频信号正弦建模。寻找在文献“正弦建模”。
如果您的信号被作为例子干净,简单的“给我的东西比的N个相邻更高的幅度”应该很好地工作。如果你有嘈杂的信号,一个简单而有效的方法是看在你的时间高峰,以跟踪它们:那么你检测谱线,而不是谱峰。督察,你计算出你的FFT信号的滑动窗口上,以获得一组时间谱(也称为频谱)。然后,看谱峰的演化在时间(即,在连续的视窗)。
有标准统计的功能和寻找离群数据,这可能是你在第一种情况下所需要的方法。利用衍生品会解决你的第二个。我不知道针对解决了这两个连续函数并取样数据的方法,但是。
第一第一件事,“峰”的定义是模糊的,如果没有进一步的规格。例如,对于下面的系列,你会打电话5-4-5一个峰或两个?
1-2-1-2-1-1-5-4-5-1-1-5-1
在这种情况下,将需要至少两个阈值:1)一个高阈值仅在高于其可以一个极端值寄存器为峰值;和2)低的阈值,使得由在其下方的小值分隔极端值将成为两个峰。
峰值检测是在极值理论文献中充分研究的主题,也称为“极值的去聚”。其典型应用包括基于环境变量例如的连续的读数识别危险事件分析风速来检测风暴事件。