[python] Python / SciPy를위한 피크 찾기 알고리즘

첫 번째 파생물이나 다른 것의 제로 크로싱을 찾아서 직접 쓸 수는 있지만 표준 라이브러리에 포함되는 공통 기능이있는 것 같습니다. 누구나 하나를 알고 있습니까?

내 특정 응용 프로그램은 2D 배열이지만 일반적으로 FFT 등에서 피크를 찾는 데 사용됩니다.

특히 이러한 종류의 문제에는 여러 개의 강한 피크가 있으며 무시해야 할 노이즈로 인해 발생하는 더 작은 “피크”가 많이 있습니다. 이것들은 단지 예일뿐입니다. 내 실제 데이터가 아닙니다.

1 차원 피크 :

피크가있는 FFT 출력

2 차원 피크 :

원형 피크의 라돈 변환 출력

피크 찾기 알고리즘은 이러한 피크의 위치 (값뿐만 아니라)를 찾고, 2 차 보간법 등을 사용하여 최대 값을 갖는 인덱스 만이 아니라 실제 샘플 간 피크를 찾는 것이 이상적입니다 .

일반적으로 몇 개의 강한 피크에만 관심이 있기 때문에 특정 임계 값을 초과하거나 진폭에 따라 순위가 매겨진 순서 목록 의 첫 번째 n 피크 이기 때문에 선택 됩니다.

내가 말했듯이, 나는 이와 같은 것을 쓰는 법을 알고있다. 잘 작동하는 것으로 알려진 기존 기능이나 패키지가 있는지 묻고 있습니다.

최신 정보:

나는 매트랩 스크립트를 번역 하며 1-D의 경우에 친절하게 작동하지만, 더 좋을 수 있습니다.

업데이트 된 업데이트 :

sixtenbe 1D 사례를위한 더 나은 버전만들었습니다 .



답변

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


답변

나는 비슷한 문제를보고 있는데, 가장 좋은 참고 문헌 중 일부는 화학에서 나온 것입니다 (질량 사양 데이터의 피크에서). 피킹 알고리즘에 대한 철저한 검토를 위해 이것을 읽으십시오 . 이것은 내가 찾은 최고 발견 기술에 대한 가장 명확한 리뷰 중 하나입니다. (잡음은 잡음이 많은 데이터에서 이러한 종류의 피크를 찾는 데 가장 좋습니다.).

피크가 명확하게 정의되어 있고 노이즈에 숨겨져 있지 않은 것 같습니다. 필자는 부드러운 savtizky-golay 파생 상품을 사용하여 피크를 찾는 것이 좋습니다 (위의 데이터를 구별하면 위양성이 엉망이됩니다). 이것은 매우 효과적인 기술이며 구현하기가 매우 쉽습니다 (기본 작업과 함께 매트릭스 클래스가 필요함). 단순히 첫 번째 SG 파생 상품의 제로 크로싱을 찾으면 행복 할 것입니다.


답변

scipy scipy.signal.find_peaks_cwt에는 귀하의 요구에 적합한 것 같은 기능이 있지만, 경험이 없으므로 권장 할 수 없습니다.

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


답변

파이썬에서 어떤 피크 찾기 알고리즘을 사용해야하는지 잘 모르는 사용자를 위해 대안에 대한 빠른 개요가 있습니다. https://github.com/MonsieurV/py-findpeaks

MatLab findpeaks함수 와 동등한 기능원한다면 Marcos Duarte 의 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))

어느 것이 당신에게 줄 것입니까?

detect_peaks 결과


답변

신뢰할 수있는 방식으로 스펙트럼에서 피크를 감지하는 것은 예를 들어 80 년대 음악 / 오디오 신호에 대한 정현파 모델링에 대한 모든 작업과 같이 꽤 많이 연구되었습니다. 문헌에서 “Sinusoidal Modeling”을 찾으십시오.

신호가 예제와 같이 깨끗하다면 간단한 “N 이웃보다 진폭이 큰 것을 알려주십시오”는 합리적으로 잘 작동합니다. 시끄러운 신호가있는 경우 간단하지만 효과적인 방법은 피크를 제 시간에보고 추적하는 것입니다. 그런 다음 스펙트럼 피크 대신 스펙트럼 선을 감지합니다. IOW, 신호의 슬라이딩 윈도우에서 FFT를 계산하여 일련의 스펙트럼을 스펙트로 그램이라고도합니다. 그런 다음 시간에 따라 (즉, 연속 창에서) 스펙트럼 피크의 진화를 살펴 봅니다.


답변

나는 당신이 찾고있는 것이 SciPy가 제공한다고 생각하지 않습니다. 이 상황에서 코드를 직접 작성합니다.

scipy.interpolate의 스플라인 보간 및 스무딩은 매우 훌륭하며 피크를 피팅 한 다음 최대 위치를 찾는 데 매우 도움이 될 수 있습니다.


답변

데이터에 대한 특이 치를 찾는 표준 통계 함수 및 방법이 있으며, 아마도 첫 번째 경우에 필요할 것입니다. 파생 상품을 사용하면 두 번째 문제가 해결됩니다. 그러나 연속 함수와 샘플링 된 데이터를 모두 해결하는 방법은 확실하지 않습니다.