programing

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

procenter 2023. 7. 9. 22:48
반응형

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

제가 직접 작성할 수 있는 것은 첫 번째 도함수의 제로 교차 같은 것을 찾아서 작성할 수 있지만, 표준 라이브러리에 포함될 만큼 충분히 공통적인 함수인 것 같습니다.아는 사람?

제가 특별히 사용하는 애플리케이션은 2D 어레이이지만, 일반적으로 FFT 등에서 피크를 찾는 데 사용됩니다.

특히, 이러한 종류의 문제에서는 여러 개의 강한 피크가 있고, 무시해야 할 소음으로 인해 발생하는 작은 "피크"가 많습니다.다음은 예시일 뿐 실제 데이터는 아닙니다.

1차원 피크:

FFT output with peaks

2차원 피크:

Radon transform output with circled peak

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

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

제가 말씀드렸듯이, 저는 이런 것을 직접 쓸 줄 압니다.기존에 잘 작동하는 것으로 알려진 기능이나 패키지가 있는지 물어본 것입니다.

업데이트:

저는 MATLAB 스크립트를 번역했고 1-D 케이스에 잘 작동하지만 더 나을 수 있습니다.

업데이트됨:

16은 1-D 사례를 위해나은 버전으로 만들어졌습니다.

이름에서 알 수 있듯이 이 기능은 이에 유용합니다.하지만 매개 변수를 잘 이해하는 것이 중요합니다.width,threshold,distance 그리고 무엇보다도 좋은 피크 추출을 얻을 수 있습니다.

제 테스트와 문서에 따르면, 유명성의 개념은 좋은 봉우리를 유지하고 시끄러운 봉우리를 버리는 "유용한 개념"입니다.

저명성이란 무엇입니까?이는 다음에서 볼 수 있듯이 "정상에서 더 높은 지형으로 가기 위해 하강하는 데 필요한 최소 높이"입니다.

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

저는 비슷한 문제를 보고 있는데, 몇 가지 가장 좋은 참고 자료가 화학에서 나온다는 것을 발견했습니다(질량-규격 데이터에서 찾은 피크에서).피크 찾기 알고리즘에 대한 철저한 검토는 다음을 참조하십시오.이것은 제가 경험한 피크 찾기 기술에 대한 가장 명확한 리뷰 중 하나입니다. (웨이블릿은 노이즈가 많은 데이터에서 이러한 종류의 피크를 찾는 데 가장 적합합니다.)

피크가 명확하게 정의되어 있고 노이즈에 가려지지 않은 것처럼 보입니다.그러한 경우, 저는 부드러운 savtizky-golay 파생물을 사용하여 피크를 찾을 것을 권장합니다(위의 데이터를 구별하기만 하면 잘못된 긍정으로 엉망이 될 것입니다).이것은 매우 효과적인 기술이며 구현하기가 매우 쉽습니다(기본 연산이 있는 행렬 클래스가 필요합니다).첫 번째 S-G 도함수의 제로 크로싱만 찾으면 행복할 것 같습니다.

에는 스이시다같함있습수다니가라는 .scipy.signal.find_peaks_cwt당신의 요구에 맞는 것처럼 들리지만, 저는 그것에 대한 경험이 없어서 추천할 수 없습니다.

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

Python에서 어떤 피크 찾기 알고리즘을 사용할지 모르는 사람들을 위해 대안에 대한 빠른 개요를 제공합니다. 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 results

양의 피크와 음의 피크를 모두 감지하려면 PeakDetect가 유용합니다.

from peakdetect import peakdetect

peaks = peakdetect(data, lookahead=20) 
# Lookahead is the distance to look ahead from a peak to determine if it is the actual peak. 
# Change lookahead as necessary 
higherPeaks = np.array(peaks[0])
lowerPeaks = np.array(peaks[1])
plt.plot(data)
plt.plot(higherPeaks[:,0], higherPeaks[:,1], 'ro')
plt.plot(lowerPeaks[:,0], lowerPeaks[:,1], 'ko')

PeakDetection

신뢰할 수 있는 방식으로 스펙트럼의 피크를 감지하는 것은 꽤 많이 연구되었습니다. 예를 들어 80년대 음악/오디오 신호에 대한 사인파 모델링에 대한 모든 작업이 그렇습니다.문헌에서 "시누소이드 모델링"을 찾습니다.

신호가 예제만큼 깨끗하면 "N개의 이웃보다 진폭이 큰 것을 주세요"라는 간단한 것이 상당히 잘 작동할 것입니다.노이즈가 많은 신호가 있는 경우, 간단하지만 효과적인 방법은 피크를 시간 내에 보고 추적하는 것입니다. 그러면 스펙트럼 피크 대신 스펙트럼 라인을 감지할 수 있습니다.IOW, 신호의 슬라이딩 윈도우에서 FFT를 계산하여 시간 내 스펙트럼 세트(스펙트로그램이라고도 함)를 얻습니다.그런 다음 시간 내 스펙트럼 피크의 진화(즉, 연속된 창에서)를 확인합니다.

데이터에 대한 특이치를 찾기 위한 표준 통계 함수와 방법이 있으며, 이는 첫 번째 경우에 필요한 것일 수 있습니다.파생상품을 사용하면 두 번째 문제를 해결할 수 있습니다.하지만 연속 함수와 샘플링된 데이터를 모두 해결하는 방법은 잘 모르겠습니다.

당신이 찾고 있는 것은 SciPy에서 제공하는 것이 아니라고 생각합니다.이 경우 코드는 제가 직접 작성하겠습니다.

스플라인 보간 및 스파이시의 평활화.보간법은 매우 유용하며 피크를 맞춘 다음 최대치의 위치를 찾는 데 매우 유용할 수 있습니다.

우선, "피크"의 정의는 더 이상의 사양이 없다면 모호합니다.예를 들어, 다음 시리즈의 경우 5-4-5를 한 피크 또는 두 피크로 부르시겠습니까?

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

이 경우 최소 두 개의 임계값이 필요합니다. 1) 극단값이 피크로 등록될 수 있는 높은 임계값과 2) 그 아래의 작은 값으로 구분된 극단값이 두 개의 피크가 되도록 낮은 임계값입니다.

피크 감지는 극단값 이론 문헌에서 잘 연구된 주제이며, "극값의 클러스터링"이라고도 합니다.일반적인 응용 프로그램에는 환경 변수의 지속적인 판독치를 기반으로 위험 이벤트를 식별하는 것이 포함됩니다. 예를 들어 폭풍 이벤트를 감지하기 위해 풍속을 분석하는 것이 포함됩니다.

페이지 하단에서 언급한 것처럼 피크에 대한 일반적인 정의는 없습니다.따라서 피크를 찾는 범용 알고리즘은 추가 가정(조건, 매개변수 등)을 가져오지 않고는 작동할 수 없습니다.이 페이지는 가장 많이 제거된 제안 중 일부를 제공합니다.위의 답변에 나열된 모든 문헌은 동일한 것을 수행하기 위한 다소 우회적인 방법이므로 자유롭게 선택하십시오.

어떤 경우에도 사용자의 경험과 해당 스펙트럼(곡선)의 특성(노이즈, 샘플링, 대역폭 등)에 따라 형상을 피크로 분류하기 위해 필요한 특성을 좁히는 것이 사용자의 의무입니다.

언급URL : https://stackoverflow.com/questions/1713335/peak-finding-algorithm-for-python-scipy

반응형