अजगर / SciPy के लिए पीक-खोज एल्गोरिथ्म


136

मैं पहले व्युत्पन्न या कुछ के शून्य-क्रॉसिंग को पाकर खुद को कुछ लिख सकता हूं, लेकिन यह मानक पुस्तकालयों में शामिल होने के लिए एक सामान्य-पर्याप्त फ़ंक्शन की तरह लगता है। किसी को एक का पता है?

मेरा विशेष एप्लिकेशन एक 2D सरणी है, लेकिन आमतौर पर इसका उपयोग FFTs में चोटियों को खोजने के लिए किया जाएगा, आदि।

विशेष रूप से, इन प्रकार की समस्याओं में, कई मजबूत चोटियां होती हैं, और फिर बहुत सारी छोटी "चोटियां" होती हैं जो सिर्फ शोर के कारण होती हैं जिन्हें अनदेखा किया जाना चाहिए। ये सिर्फ उदाहरण हैं; मेरा वास्तविक डेटा नहीं:

1-आयामी चोटियों:

चोटियों के साथ एफएफटी आउटपुट

2-आयामी चोटियों:

रेडॉन ट्रांसफ़ॉर्मेड पीक के साथ आउटपुट को परिवर्तित करता है

शिखर-खोज एल्गोरिथ्म इन चोटियों के स्थान (न केवल उनके मूल्यों) का पता लगाएगा, और आदर्श रूप से सही अंतर-नमूना चोटी को ढूंढेगा, न कि केवल अधिकतम मूल्य वाले सूचकांक, शायद द्विघात प्रक्षेप या कुछ का उपयोग कर ।

आमतौर पर आप केवल कुछ मजबूत चोटियों के बारे में परवाह करते हैं, इसलिए उन्हें या तो चुना जाएगा क्योंकि वे एक निश्चित सीमा से ऊपर हैं, या क्योंकि वे एक क्रमबद्ध सूची के पहले एन चोटियों हैं, जो कि आयाम द्वारा क्रमबद्ध हैं।

जैसा कि मैंने कहा, मुझे पता है कि मुझे इस तरह से कुछ लिखना है। मैं सिर्फ यह पूछ रहा हूं कि क्या कोई पूर्व-मौजूदा फ़ंक्शन या पैकेज है जो अच्छी तरह से काम करने के लिए जाना जाता है।

अपडेट करें:

मैंने MATLAB स्क्रिप्ट का अनुवाद किया और यह 1-डी केस के लिए शालीनता से काम करता है, लेकिन बेहतर हो सकता है।

अद्यतन अद्यतन:

सिक्सटेन ने 1-डी केस के लिए एक बेहतर संस्करण बनाया


@endolith क्या आपके पास मूल MATLAB फ़ाइल है जिसे आपने इसके लिए अजगर का अनुवाद किया है? धन्यवाद!
स्पेसी


2
इसके बारे में क्या: docs.scipy.org/doc/scipy/reference/generated/…
dashesy

1
@endolith मुझे पता है कि यह प्रश्न बहुत पुराना है, लेकिन यह बहुत उपयोगी है;) मैंने आज सुबह कुछ घंटे बिताए find_peaks, इसलिए मैंने यह उत्तर जोड़ा जो भविष्य के संदर्भ के लिए उपयोगी हो सकता है। (मुझे यकीन है कि आप 2009 से इसे पहले ही पा चुके हैं, लेकिन यह अन्य लोगों के लिए है + खुद जब मैं खुद को कुछ वर्षों में फिर से
पूछूंगा

जवाबों:


74

फ़ंक्शन scipy.signal.find_peaks, जैसा कि इसके नाम से पता चलता है, इसके लिए उपयोगी है। लेकिन यह अच्छी तरह से समझने के लिए इसके मापदंडों महत्वपूर्ण है width, threshold, distance और सब से ऊपरprominence एक अच्छा शिखर निकासी प्राप्त करने के लिए।

मेरे परीक्षणों और प्रलेखन के अनुसार, प्रमुखता की अवधारणा की अवधारणा अच्छी चोटियों को रखने के लिए "उपयोगी अवधारणा" है, और शोर करने वाली चोटियों को छोड़ दें।

(स्थलाकृतिक) प्रमुखता क्या है ? यह "शिखर से किसी भी उच्च भूभाग तक जाने के लिए आवश्यक न्यूनतम ऊंचाई है" , जैसा कि यहाँ देखा जा सकता है:

यहाँ छवि विवरण दर्ज करें

विचार यह है:

प्रमुखता जितनी अधिक होगी, उतनी ही महत्वपूर्ण "महत्वपूर्ण" चोटी है।

परीक्षा:

यहाँ छवि विवरण दर्ज करें

मैंने उद्देश्य पर एक (शोर) आवृत्ति-भिन्न साइनसॉइड का उपयोग किया क्योंकि यह कई कठिनाइयों को दर्शाता है। हम देख सकते हैं कि widthपैरामीटर यहां बहुत उपयोगी नहीं है क्योंकि यदि आप न्यूनतम widthबहुत अधिक सेट करते हैं , तो यह उच्च आवृत्ति वाले हिस्से में बहुत करीब चोटियों को ट्रैक करने में सक्षम नहीं होगा। यदि आप widthबहुत कम सेट करते हैं, तो आपके पास सिग्नल के बाएं हिस्से में कई अवांछित चोटियां होंगी। के साथ भी यही समस्या है distancethresholdकेवल प्रत्यक्ष पड़ोसियों के साथ तुलना करता है, जो यहां उपयोगी नहीं है। 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()

मैं इसके बाद क्या हूं। लेकिन क्या आप किसी ऐसे कार्यान्वयन को जानते हैं जो 2D सरणी में प्रमुखता पाता है?
जेसन

43

मैं इसी तरह की समस्या को देख रहा हूं, और मुझे रसायन विज्ञान से प्राप्त कुछ बेहतरीन संदर्भ (मास-स्पेक डेटा में चोटियों को खोजने से) मिले हैं। एल्गोरिदम को खोजने के लिए चोटी की अच्छी समीक्षा के लिए इसे पढ़ें । यह चोटी खोजने की तकनीक का सबसे अच्छा स्पष्ट समीक्षाओं में से एक है जिसे मैंने पार किया है। (शोर डेटा में इस तरह की चोटियों को खोजने के लिए वेवलेट सबसे अच्छे हैं।)

ऐसा लगता है कि आपकी चोटियाँ स्पष्ट रूप से परिभाषित हैं और शोर में छिपी नहीं हैं। यही कारण है कि मैं चोटियों को खोजने के लिए चिकनी सविट्की-गॉले डेरिवेटिव का उपयोग करने की सलाह दूंगा (यदि आप ऊपर दिए गए डेटा को अलग करते हैं तो आपके पास झूठी सकारात्मकता की गड़बड़ होगी।)। यह एक बहुत प्रभावी तकनीक है और इसे लागू करने के लिए बहुत आसान है (आपको मैट्रिक्स क्लास w / बुनियादी संचालन की आवश्यकता है)। यदि आपको लगता है कि आपको लगता है कि आप खुश होंगे तो पहले एसजी व्युत्पन्न के शून्य को पार करें।


2
मैं एक सामान्य उद्देश्य समाधान की तलाश में था, न कि केवल उन विशेष छवियों पर काम करता है। मैंने पायथन को एक MATLAB स्क्रिप्ट को अनुकूलित किया और यह शालीनता से काम करता है।
एंडोलिथ

1
सही पर। मैटलैब एल्गोरिदम के लिए एक अच्छा स्रोत है। स्क्रिप्ट किस तकनीक का उपयोग करती है? (BTW, SG एक बहुत ही सामान्य उद्देश्य तकनीक है)।
पॉल

2
मैंने इसे ऊपर लिंक किया। यह मूल रूप से केवल स्थानीय मैक्सिमा की खोज करता है जो अपने पड़ोसियों के ऊपर एक निश्चित सीमा से अधिक होती हैं। निश्चित रूप से बेहतर तरीके हैं।
एंडोलिथ

1
@Paul मैंने उस पेज को बुकमार्क किया। IYO और संक्षेप में, आपको लगता है कि इस चोटी के व्यवसाय के लिए आपने कौन सी विशिष्ट तकनीक पर काम किया है?
स्पेसी

अगर तीन बिंदुओं के बीच में से एक बड़ा है या अन्य दो से छोटा है, तो परीक्षण से बेहतर व्युत्पन्न के शून्य क्यों हैं। मैंने पहले ही sg transfor लागू किया है, एक अतिरिक्त लागत की तरह लगता है।
kirill_igum

20

Scipy में एक फंक्शन होता है, scipy.signal.find_peaks_cwtजो लगता है कि आपकी आवश्यकताओं के लिए उपयुक्त है, हालाँकि मुझे इसका अनुभव नहीं है, इसलिए मैं इसकी सिफारिश नहीं कर सकता हूँ।

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


12
हाँ, यह अस्तित्व में नहीं था जब मैं इस से पूछा, और मैं अभी भी यकीन है कि यह कैसे उपयोग करने के लिए नहीं कर रहा हूँ
endolith

1
आपने इसे कुछ समय पहले जोड़ा था, लेकिन इसने कमाल का काम किया। इसका उपयोग पाई के रूप में सरल है। बस सरणी में पास करें, और एक और सरणी (यानी। np.arange (1,10)) जो आप चाहते हैं चोटियों की सभी चौड़ाई को सूचीबद्ध करता है; पतली या चौड़ी चोटियों के लिए फ़िल्टर करने का अच्छा लाभ अगर किसी को ज़रूरत हो। एक बार फिर धन्यवाद!
मीलों

15

उन लोगों के लिए जो पाइकॉन में उपयोग करने के लिए चोटी-खोजने वाले एल्गोरिदम के बारे में निश्चित नहीं हैं, यहां विकल्पों का तेजी से अवलोकन किया गया है: https://github.com/MonsieurV/py-findpeaks

खुद findpeaksको मैटलैब फंक्शन के बराबर चाहते हुए , मैंने पाया है कि मार्कोस डुटर्टे का डिटेक्ट_पिक्स फंक्शन एक अच्छा कैच है।

उपयोग करने के लिए बहुत आसान:

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 परिणाम


1
चूंकि यह पोस्ट लिखी गई थी, इसलिए find_peaksफ़ंक्शन को इसमें जोड़ा गया था scipy
onewhaleid

6

एक विश्वसनीय तरीके से एक स्पेक्ट्रम में चोटियों का पता लगाने का काफी अध्ययन किया गया है, उदाहरण के लिए 80 के दशक में संगीत / ऑडियो सिग्नल के लिए साइनसोइडल मॉडलिंग पर सभी काम। साहित्य में "साइनसोइडल मॉडलिंग" की तलाश करें।

यदि आपके संकेत उदाहरण के रूप में साफ हैं, तो एक सरल "मुझे एन पड़ोसियों की तुलना में अधिक आयाम के साथ कुछ दे" अच्छी तरह से काम करना चाहिए। यदि आपके पास शोर के संकेत हैं, तो समय पर अपनी चोटियों को देखने के लिए एक सरल लेकिन प्रभावी तरीका है, उन्हें ट्रैक करने के लिए: आप तब वर्णक्रमीय चोटियों के बजाय वर्णक्रमीय रेखाओं का पता लगाते हैं। IOW, आप समय में स्पेक्ट्रम का एक सेट (जिसे स्पेक्ट्रोग्राम भी कहा जाता है) पाने के लिए अपने सिग्नल की स्लाइडिंग विंडो पर एफएफटी की गणना करते हैं। आप समय में वर्णक्रमीय शिखर के विकास को देखते हैं (अर्थात लगातार खिड़कियों में)।


समय में चोटियों को देखो? वर्णक्रमीय रेखाओं का पता लगाएं? मुझे यकीन नहीं है कि इसका क्या मतलब है। यह वर्ग तरंगों के लिए काम करेगा?

ओह, आप FFT के बजाय STFT का उपयोग करने के बारे में बात कर रहे हैं। यह प्रश्न विशेष रूप से एफएफटी के बारे में नहीं है; यह सिर्फ एक उदाहरण है। यह किसी भी सामान्य 1 डी या 2 डी सरणी में चोटियों को खोजने के बारे में है।
एंडोलिथ

4

मुझे नहीं लगता कि आप जो खोज रहे हैं वह SciPy द्वारा प्रदान किया गया है। मैं खुद कोड लिखूंगा, इस स्थिति में।

Scipy.interpolate से स्पलाइन इंटरपोलेशन और स्मूथिंग काफी अच्छी हैं और हो सकता है कि फिटिंग की चोटियों में काफी सहायक हो और फिर अपनी अधिकतम स्थिति का पता लगा सकें।


16
मेरी माफी, लेकिन मुझे लगता है कि यह एक टिप्पणी होनी चाहिए, एक जवाब नहीं। यह सिर्फ अपने आप से इसे लिखने का सुझाव देता है, कार्यों के लिए एक अस्पष्ट सुझाव के साथ जो उपयोगी हो सकता है (पॉल के जवाब में लोग बहुत अधिक प्रासंगिक हैं, संयोग से)।
अमी तेवरी

1

डेटा के आउटलेयर को खोजने के लिए मानक सांख्यिकीय फ़ंक्शंस और विधियाँ हैं, जो कि शायद आपको पहले मामले में चाहिए। डेरिवेटिव का उपयोग करना आपके दूसरे को हल करेगा। मैं एक ऐसी विधि के लिए निश्चित नहीं हूं जो निरंतर कार्यों और सैंपल किए गए डेटा दोनों को हल करती है।


0

पहले चीजें पहले, "पीक" की परिभाषा अस्पष्ट है अगर आगे विनिर्देशों के बिना। उदाहरण के लिए, निम्नलिखित श्रृंखला के लिए, क्या आप 5-4-5 को एक चोटी या दो कहेंगे?

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

इस मामले में, आपको कम से कम दो थ्रेसहोल्ड की आवश्यकता होगी: 1) केवल एक उच्च दहलीज जिसके ऊपर एक चरम मूल्य रजिस्टर हो सकता है; और 2) एक कम सीमा ताकि छोटे मूल्यों से अलग चरम मान दो चोटियों बन जाए।

पीक डिटेक्शन चरम मूल्य सिद्धांत साहित्य में एक अच्छी तरह से अध्ययन किया गया विषय है, जिसे "चरम मूल्यों की घोषणा" के रूप में भी जाना जाता है। इसके विशिष्ट अनुप्रयोगों में पर्यावरण चर के निरंतर रीडिंग के आधार पर खतरनाक घटनाओं की पहचान करना शामिल है जैसे कि तूफान की घटनाओं का पता लगाने के लिए हवा की गति का विश्लेषण करना।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.