web-dev-qa-db-ja.com

Python / SciPyのピーク検出アルゴリズム

一次導関数のゼロクロッシングまたは何かを見つけることで自分で何かを書くことができますが、標準ライブラリに含まれる一般的な十分な関数のようです。誰もが知っていますか?

私の特定のアプリケーションは2Dアレイですが、通常はFFTなどでピークを見つけるために使用されます。

具体的には、この種の問題では、複数の強いピークがあり、無視する必要のあるノイズが原因の小さな「ピーク」がたくさんあります。これらは単なる例です。私の実際のデータではありません:

1次元のピーク:

FFT output with peaks

2次元のピーク:

Radon transform output with circled peak

ピーク検出アルゴリズムは、これらのピークの位置(それらの値だけでなく)を見つけ、理想的には、おそらく 2次補間 を使用して、最大値を持つインデックスだけでなく、真のサンプル間ピークを見つけます何か。

通常、少数の強いピークのみを気にするので、特定のしきい値を超えているか、または順序付けされた最初のnピークであるために選択されます振幅によってランク付けされたリスト。

私が言ったように、私はこのようなものを自分で書く方法を知っています。うまく機能することがわかっている既存の関数またはパッケージがあるかどうかを尋ねています。

更新:

I MATLABスクリプトの翻訳 であり、1-Dの場合には適切に機能しますが、改善される可能性があります。

更新された更新:

sixtenbe より良いバージョンを作成 1-Dの場合。

119
endolith

あなたが探しているのはSciPyによって提供されているとは思いません。この状況では、自分でコードを記述します。

Scipy.interpolateのスプライン補間とスムージングは​​非常に優れており、ピークのフィッティングとその最大位置の特定に非常に役立つ場合があります。

3
Eric O Lebigot

私は同様の問題を検討していますが、最良のリファレンスのいくつかは化学(質量分析データで検出されたピーク)からのものであることがわかりました。ピーキング検出アルゴリズムの十分なレビューについては、 this を参照してください。これは、私が遭遇したピーク発見手法の最も明確なレビューの1つです。 (ウェーブレットは、ノイズの多いデータでこの種のピークを見つけるのに最適です。).

ピークが明確に定義され、ノイズに隠れていないようです。そのため、スムーズなsavtizky-golay微分を使用してピークを見つけることをお勧めします(上記のデータを区別するだけでは、誤検出が大量に発生します)。これは非常に効果的な手法であり、実装が非常に簡単です(基本操作を備えたマトリックスクラスが必要です)。最初のS-G派生物のゼロクロスを単に見つけた場合、私はあなたが幸せになると思います。

42
Paul

関数 scipy.signal.find_peaks は、その名前が示すように、これに役立ちます。ただし、良好なピーク抽出を得るには、そのパラメーターwidththresholddistanceおよびとりわけprominenceを十分に理解することが重要です。

私のテストとドキュメントによると、prominenceの概念は、良好なピークを維持し、ノイズの多いピークを破棄するための「有用な概念」です。

(topographic)prominence とは何ですか?ここに見られるように、「頂上からより高い地形に到達するために下降するのに必要な最小の高さ」です。

enter image description here

アイデアは次のとおりです。

プロミネンスが高いほど、ピークは「重要」になります。

テスト:

enter image description here

多くの困難を示すため、意図的に(ノイズのある)周波数変動正弦波を使用しました。 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()
31
Basj

Scipyにはscipy.signal.find_peaks_cwtという名前の関数がありますが、これはあなたのニーズに合っているように聞こえますが、私は経験がないのでお勧めできません。

http://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks_cwt.html

20

Pythonでどのピーク検出アルゴリズムを使用するかわからない場合は、代替の概要を以下に示します。 https://github.com/MonsieurV/py-findpeaks

MatLab findpeaks関数と同等のものが欲しいので、Marcos Duarteの detect_peaks function が良いキャッチであることがわかりました。

とても使いやすい:

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))

それはあなたに与えるでしょう:

detect_peaks results

14
Yoan Tournade

信頼できる方法でスペクトルのピークを検出することはかなり研究されてきました。たとえば、80年代の音楽/オーディオ信号の正弦波モデリングに関するすべての研究です。文献で「正弦波モデリング」を探してください。

信号が例と同じくらいきれいであれば、単純な「N個の隣人よりも大きい振幅を持つものをくれ」と合理的に機能するはずです。ノイズの多い信号がある場合、シンプルで効果的な方法は、ピークを時間内に調べて追跡することです。その後、スペクトルピークの代わりにスペクトル線を検出します。 IOWでは、信号のスライディングウィンドウでFFTを計算し、時間内のスペクトルのセット(スペクトログラムとも呼ばれます)を取得します。次に、スペクトルピークの時間的変化(つまり、連続したウィンドウ)を確認します。

6

データの外れ値を見つけるための標準的な統計関数と方法がありますが、これはおそらく最初の場合に必要なものです。デリバティブを使用すると、2番目の問題が解決します。ただし、連続関数とサンプリングデータの両方を解決する方法についてはわかりません。

1
nullpointer

まず最初に、「ピーク」の定義は、それ以上の仕様がなければ曖昧です。たとえば、次のシリーズでは、5-4-5を1ピークまたは2ピークと呼びますか?

1-2-1-2-1-1-5-4-5-1-1-5-1

この場合、少なくとも2つのしきい値が必要になります。1)しきい値を超えると、極値がピークとして登録されます。 2)しきい値が低いため、その下の小さな値で区切られた極値は2つのピークになります。

ピーク検出は、極値理論の文献でよく研究されているトピックであり、「極値のクラスター解除」としても知られています。その典型的なアプリケーションには、環境変数の連続測定値に基づいたハザードイベントの特定が含まれます。風速を分析して嵐のイベントを検出します。

0
Ian Liu