मैं autocorrelation करने के लिए numpy.correlate का उपयोग कैसे कर सकता हूं?


106

मुझे संख्याओं के समूह का स्वतः-सहसंबंध करने की आवश्यकता है, जैसा कि मैं समझता हूं कि यह केवल स्वयं के साथ समुच्चय का सहसंबंध है।

मैंने इसे numpy के सहसंबंधी फ़ंक्शन का उपयोग करके आज़माया है, लेकिन मुझे परिणाम पर विश्वास नहीं है, क्योंकि यह लगभग हमेशा एक वेक्टर देता है जहां पहला नंबर सबसे बड़ा नहीं है, क्योंकि यह होना चाहिए।

तो, यह प्रश्न वास्तव में दो प्रश्न हैं:

  1. वास्तव में क्या numpy.correlateकर रहा है?
  2. ऑटो-सहसंबंध बनाने के लिए मैं इसे (या कुछ और) कैसे उपयोग कर सकता हूं?

इन्हें भी देखें: सामान्यीकृत ऑटोक्रेलेशन के बारे में जानकारी के लिए stackoverflow.com/questions/12269834/…
amcnabb

जवाबों:


114

अपने पहले प्रश्न का उत्तर देने के लिए, उल्टे के साथ और निर्दिष्ट मोड के द्वारा दिए गए परिणामों को देने के numpy.correlate(a, v, mode)लिए दृढ़ संकल्प का प्रदर्शन कर रहा है। घुमाव की परिभाषा , सी (टी) = Σ -∞ <i <∞ एक मैं वी टी + मैं जहां -∞ <टी <∞, परिणामों से -∞ को ∞ के लिए अनुमति देता है, लेकिन आप स्पष्ट रूप से एक असीम लंबा संग्रहीत नहीं कर सकता सरणी। तो इसे क्लिप करना होगा, और यह वह जगह है जहां मोड आता है। 3 अलग मोड हैं: पूर्ण, समान, और मान्य:av

  • "पूर्ण" मोड tदोनों के लिए परिणाम देता है जहां दोनों aऔर vकुछ ओवरलैप होते हैं।
  • "समान" मोड सबसे कम वेक्टर ( aया v) के समान लंबाई के साथ एक परिणाम देता है ।
  • "वैध" मोड से परिणाम प्रदान केवल जब aऔर vपूरी तरह से एक दूसरे को ओवरलैप। प्रलेखन के लिए numpy.convolveमोड पर और अधिक विस्तार देता है।

आपके दूसरे प्रश्न के लिए, मुझे लगता numpy.correlate है कि आपको ऑटोक्रेलेशन दिया जा रहा है, यह आपको थोड़ा और साथ ही दे रहा है। ऑटोकैरेलेशन का उपयोग यह पता लगाने के लिए किया जाता है कि एक निश्चित समय के अंतर पर संकेत, या कार्य समान कैसे होते हैं। 0 के एक समय के अंतर पर, ऑटो-सहसंबंध उच्चतम होना चाहिए क्योंकि संकेत स्वयं के समान है, इसलिए आपने अपेक्षा की थी कि ऑटोक्रॉलेशन परिणाम सरणी में पहला तत्व सबसे बड़ा होगा। हालाँकि, सहसंबंध 0. के एक समय के अंतर से शुरू नहीं हो रहा है। यह नकारात्मक समय के अंतर से शुरू होता है, 0 पर बंद होता है, और फिर सकारात्मक होता है। यही है, आप उम्मीद कर रहे थे:

autocorrelation (a) = ( -∞ <i <∞ एक मैं वी टी + मैं जहां 0 <= टी <∞

लेकिन आपको जो मिला वह था:

autocorrelation (a) = ∑ -or <i <। a i i v t + i जहाँ -∞ <t <(

आपको जो करने की आवश्यकता है वह आपके सहसंबंध परिणाम का अंतिम आधा हिस्सा है, और यह वह स्वत: संबंध होना चाहिए जिसकी आप तलाश कर रहे हैं। यह करने के लिए एक साधारण अजगर समारोह होगा:

def autocorr(x):
    result = numpy.correlate(x, x, mode='full')
    return result[result.size/2:]

बेशक, आपको यह सुनिश्चित करने के लिए त्रुटि जाँच की आवश्यकता होगी कि xवास्तव में 1-डी सरणी है। इसके अलावा, यह स्पष्टीकरण शायद सबसे गणितीय रूप से कठोर नहीं है। मैं शिशुओं के आस-पास फेंक रहा हूं, क्योंकि दृढ़ संकल्प की परिभाषा उनका उपयोग करती है, लेकिन यह जरूरी नहीं है कि ऑटोक्रेलेशन के लिए लागू हो। तो, इस स्पष्टीकरण का सैद्धांतिक हिस्सा थोड़ा विस्की हो सकता है, लेकिन उम्मीद है कि व्यावहारिक परिणाम सहायक हैं। ऑटोकैरेलेशन पर ये पृष्ठ बहुत मददगार हैं, और यदि आप नोटेशन और भारी अवधारणाओं के माध्यम से लुप्त होने का मन नहीं बनाते हैं, तो आप बहुत बेहतर सैद्धांतिक पृष्ठभूमि दे सकते हैं।


6
संख्यात्मक के वर्तमान बिल्ड में, मोड 'वही' को वही प्राप्त करने के लिए निर्दिष्ट किया जा सकता है जो ए। लेवी ने प्रस्तावित किया था। समारोह का शरीर तब पढ़ सकता थाreturn numpy.correlate(x, x, mode='same')
डेविड ज़्विकर

13
@DavidZwicker लेकिन परिणाम अलग हैं! np.correlate(x,x,mode='full')[len(x)//2:] != np.correlate(x,x,mode='same')। उदाहरण के लिए, x = [1,2,3,1,2]; np.correlate(x,x,mode='full');{ >>> array([ 2, 5, 11, 13, 19, 13, 11, 5, 2])} np.correlate(x,x,mode='same');{ >>> array([11, 13, 19, 13, 11])}। सही एक है: np.correlate(x,x,mode='full')[len(x)-1:];{ >>> array([19, 13, 11, 5, 2])} देख पहले आइटम है सबसे बड़ा एक
डेवलपर

19
ध्यान दें कि यह उत्तर अप्राकृतिक निरंकुशता देता है।
amcnabb

4
मुझे लगता है कि @Developer सही स्लाइसिंग देता है: [len(x)-1:]0-अंतराल से शुरू होता है। क्योंकि fullमोड एक परिणाम का आकार देता है 2*len(x)-1, A.Levy की तरह [result.size/2:]ही है [len(x)-1:]। यह एक इंट हालांकि, बेहतर बनाने के लिए बेहतर है [result.size//2:]
जेसन

मैंने पाया कि यह एक इंट होना चाहिए, कम से कम अजगर में 3.7
kevinkayaks

25

ऑटो-सहसंबंध दो संस्करणों में आता है: सांख्यिकीय और दृढ़ संकल्प। वे दोनों समान करते हैं, थोड़े विस्तार के अलावा: सांख्यिकीय संस्करण को अंतराल पर सामान्यीकृत किया जाता है [-1,1]। यहाँ एक उदाहरण है कि आप सांख्यिकीय कैसे करते हैं:

def acf(x, length=20):
    return numpy.array([1]+[numpy.corrcoef(x[:-i], x[i:])[0,1]  \
        for i in range(1, length)])

9
आप numpy.corrcoef[x:-i], x[i:])[0,1]दूसरी पंक्ति में चाहते हैं जैसे कि corrcoef2x2 का मैट्रिक्स मान है
luispedro

सांख्यिकीय और दृढ़ निरूपण के बीच अंतर क्या है?
डैनियल का कहना है कि 3

1
@DanielPendergast: दूसरा वाक्य उत्तर देता है कि: वे दोनों एक ही करते हैं, थोड़े विस्तार के अलावा: पूर्व [सांख्यिकीय] को अंतराल पर सामान्यीकृत किया जाता है [-1,1]
n1k31t4

21

T के अंतराल के लिए सांख्यिकीय सहसंबंध की गणना करने के numpy.corrcoefबजाय फ़ंक्शन का उपयोग करें numpy.correlate:

def autocorr(x, t=1):
    return numpy.corrcoef(numpy.array([x[:-t], x[t:]]))

क्या "सहसंबंध गुणांक" सिग्नल प्रोसेसिंग में उपयोग किए जाने वाले ऑटोकॉरेलेशन का उल्लेख नहीं करता है और न ही आंकड़ों में प्रयुक्त ऑटोक्रेलेशन? en.wikipedia.org/wiki/Autocorrelation#Signal_processing
डैनियल का कहना है मोनिका

@DanielPendergast मैं सिग्नल प्रोसेसिंग से उतना परिचित नहीं हूँ। सुन्न डॉक्स से: "पीयरसन उत्पाद-पल सहसंबंध गुणांक लौटाएं।" क्या वह सिग्नल प्रोसेसिंग संस्करण है?
रामोन जे रोमेरो वाई विजिल

18

मुझे लगता है कि इस विषय में भ्रम को जोड़ने वाली 2 चीजें हैं:

  1. सांख्यिकीय बनाम सिग्नल प्रोसेसिंग परिभाषा: जैसा कि अन्य ने बताया है, आंकड़ों में हम ऑटो-सहसंबंध को सामान्य करते हैं [-1,1]।
  2. आंशिक बनाम गैर-आंशिक माध्य / विचरण: जब समय एक अंतराल> 0 पर शिफ्ट होता है, तो उनके ओवरलैप का आकार हमेशा <मूल लंबाई होगा। क्या हम मूल (गैर-आंशिक) के माध्य और एसटीडी का उपयोग करते हैं, या हमेशा एक नए माध्य की गणना करते हैं और कभी-कभी बदलते ओवरलैप (आंशिक) का उपयोग करते हुए एसटीडी से फर्क पड़ता है। (इसके लिए शायद एक औपचारिक शब्द है, लेकिन मैं "आंशिक" का उपयोग अभी करने जा रहा हूं)।

मैंने 5 फ़ंक्शन बनाए हैं जो 1 डी सरणी के ऑटो-सहसंबंध की गणना करते हैं, आंशिक बनाम गैर-आंशिक अंतर के साथ। कुछ आंकड़ों से सूत्र का उपयोग करते हैं, कुछ सिग्नल प्रोसेसिंग अर्थ में सहसंबंध का उपयोग करते हैं, जो एफएफटी के माध्यम से भी किया जा सकता है। लेकिन सभी परिणाम आँकड़ों की परिभाषा में स्वतः-सहसंबंध हैं , इसलिए वे बताते हैं कि वे एक-दूसरे से कैसे जुड़े हैं। नीचे कोड:

import numpy
import matplotlib.pyplot as plt

def autocorr1(x,lags):
    '''numpy.corrcoef, partial'''

    corr=[1. if l==0 else numpy.corrcoef(x[l:],x[:-l])[0][1] for l in lags]
    return numpy.array(corr)

def autocorr2(x,lags):
    '''manualy compute, non partial'''

    mean=numpy.mean(x)
    var=numpy.var(x)
    xp=x-mean
    corr=[1. if l==0 else numpy.sum(xp[l:]*xp[:-l])/len(x)/var for l in lags]

    return numpy.array(corr)

def autocorr3(x,lags):
    '''fft, pad 0s, non partial'''

    n=len(x)
    # pad 0s to 2n-1
    ext_size=2*n-1
    # nearest power of 2
    fsize=2**numpy.ceil(numpy.log2(ext_size)).astype('int')

    xp=x-numpy.mean(x)
    var=numpy.var(x)

    # do fft and ifft
    cf=numpy.fft.fft(xp,fsize)
    sf=cf.conjugate()*cf
    corr=numpy.fft.ifft(sf).real
    corr=corr/var/n

    return corr[:len(lags)]

def autocorr4(x,lags):
    '''fft, don't pad 0s, non partial'''
    mean=x.mean()
    var=numpy.var(x)
    xp=x-mean

    cf=numpy.fft.fft(xp)
    sf=cf.conjugate()*cf
    corr=numpy.fft.ifft(sf).real/var/len(x)

    return corr[:len(lags)]

def autocorr5(x,lags):
    '''numpy.correlate, non partial'''
    mean=x.mean()
    var=numpy.var(x)
    xp=x-mean
    corr=numpy.correlate(xp,xp,'full')[len(x)-1:]/var/len(x)

    return corr[:len(lags)]


if __name__=='__main__':

    y=[28,28,26,19,16,24,26,24,24,29,29,27,31,26,38,23,13,14,28,19,19,\
            17,22,2,4,5,7,8,14,14,23]
    y=numpy.array(y).astype('float')

    lags=range(15)
    fig,ax=plt.subplots()

    for funcii, labelii in zip([autocorr1, autocorr2, autocorr3, autocorr4,
        autocorr5], ['np.corrcoef, partial', 'manual, non-partial',
            'fft, pad 0s, non-partial', 'fft, no padding, non-partial',
            'np.correlate, non-partial']):

        cii=funcii(y,lags)
        print(labelii)
        print(cii)
        ax.plot(lags,cii,label=labelii)

    ax.set_xlabel('lag')
    ax.set_ylabel('correlation coefficient')
    ax.legend()
    plt.show()

यहाँ उत्पादन आंकड़ा है:

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

हम सभी 5 लाइनों को नहीं देखते हैं क्योंकि उनमें से 3 ओवरलैप (बैंगनी रंग में) हैं। ओवरलैप सभी गैर-आंशिक ऑटो-सहसंबंध हैं। इसका कारण है सिग्नल प्रोसेसिंग के तरीकों से गणना (np.correlate , FFT) से गणना प्रत्येक ओवरलैप के लिए एक अलग माध्य / std की गणना नहीं करती है।

यह भी ध्यान दें कि fft, no padding, non-partial(लाल रेखा) परिणाम अलग है, क्योंकि यह एफएफटी करने से पहले 0 के साथ समय को पैड नहीं करता है, इसलिए यह परिपत्र एफएफटी है। मैं विस्तार से नहीं बता सकता कि क्यों, यही मैंने कहीं और से सीखा है।


12

जैसा कि मैं बस उसी समस्या में भाग गया, मैं आपके साथ कोड की कुछ पंक्तियाँ साझा करना चाहूंगा। वास्तव में स्टैकओवरफ्लो में ऑटोक्रॉरेलेशन के बारे में अब तक कई समान पोस्ट हैं। यदि आप a(x, L) = sum(k=0,N-L-1)((xk-xbar)*(x(k+L)-xbar))/sum(k=0,N-1)((xk-xbar)**2)ऑटोकॉरेलेशन को परिभाषित करते हैं, तो [यह IDL के a_correlate फ़ंक्शन में दी गई परिभाषा है और यह मेरे द्वारा प्रश्न # 12269834 के उत्तर 2 में जो दिखता है, उससे सहमत है , तो निम्नलिखित सही परिणाम देते हैं:

import numpy as np
import matplotlib.pyplot as plt

# generate some data
x = np.arange(0.,6.12,0.01)
y = np.sin(x)
# y = np.random.uniform(size=300)
yunbiased = y-np.mean(y)
ynorm = np.sum(yunbiased**2)
acor = np.correlate(yunbiased, yunbiased, "same")/ynorm
# use only second half
acor = acor[len(acor)/2:]

plt.plot(acor)
plt.show()

जैसा कि आप देखते हैं कि मैंने इसे एक पाप वक्र और एक समान यादृच्छिक वितरण के साथ परीक्षण किया है, और दोनों परिणाम ऐसे दिखते हैं जैसे मैं उनसे उम्मीद करता हूं। ध्यान दें कि मैंने दूसरों mode="same"की mode="full"तरह इस्तेमाल किया।


9

आपके प्रश्न 1 को पहले ही यहाँ कई उत्कृष्ट उत्तरों में बड़े पैमाने पर चर्चा की जा चुकी है।

मैंने आपके साथ कोड की कुछ पंक्तियों को साझा करने का विचार किया है, जो आपको केवल एक संकेत के आटोक्लेररेशन की गणना करने की अनुमति देता है जो केवल ऑटोक्रेलेशन के गणितीय गुणों पर आधारित है। अर्थात्, निरंकुशता की गणना निम्नलिखित तरीके से की जा सकती है:

  1. संकेत से माध्य को घटाएं और एक निष्पक्ष संकेत प्राप्त करें

  2. निष्पक्ष संकेत के फूरियर रूपांतरण की गणना करें

  3. निष्पक्ष संकेत के फूरियर रूपांतरण के प्रत्येक मान के वर्ग मान लेकर, सिग्नल की पावर वर्णक्रमीय घनत्व की गणना करें

  4. पॉवर स्पेक्ट्रल घनत्व के व्युत्क्रम फूरियर रूपांतरण की गणना करें

  5. निष्पक्ष सिग्नल के वर्गों के योग द्वारा पावर स्पेक्ट्रल घनत्व के व्युत्क्रम फूरियर रूपांतरण को सामान्य करें, और परिणामी वेक्टर का केवल आधा हिस्सा लें

ऐसा करने के लिए कोड निम्नलिखित है:

def autocorrelation (x) :
    """
    Compute the autocorrelation of the signal, based on the properties of the
    power spectral density of the signal.
    """
    xp = x-np.mean(x)
    f = np.fft.fft(xp)
    p = np.array([np.real(v)**2+np.imag(v)**2 for v in f])
    pi = np.fft.ifft(p)
    return np.real(pi)[:x.size/2]/np.sum(xp**2)

क्या यह संभव है कि इसमें कुछ गड़बड़ है? मैं अन्य ऑटो सहसंबंध कार्यों के साथ इसके परिणामों का मिलान नहीं कर सकता। फ़ंक्शन समान दिखता है, लेकिन लगता है कि कुछ हद तक परिष्कृत है।
पिंडकास

@pindakaas क्या आप अधिक विशिष्ट हो सकते हैं? कृपया जानकारी प्रदान करें कि आपको कौन सी विसंगतियां हैं, किन कार्यों के साथ।
रग्गेरो

उपयोग क्यों नहीं p = np.abs(f)?
डायलान

@dylnan यह f के घटकों के मॉड्यूल देगा , जबकि हम चाहते हैं कि यहाँ एक वेक्टर जिसमें f के घटकों के वर्ग मॉड्यूल हों
रग्गरो

1
हाँ, लेकिन क्या आपको पता है कि सूची बोध करना शायद धीमा है।
जेसन

2

मैं एक कम्प्यूटेशनल जीवविज्ञानी हूं, और जब मुझे स्टोकैस्टिक प्रक्रियाओं की समय श्रृंखला के जोड़ों के बीच ऑटो / क्रॉस-सहसंबंधों की गणना करनी थी, तो मुझे एहसास हुआ कि np.correlateमुझे वह काम नहीं करना चाहिए जिसकी मुझे ज़रूरत थी।

वास्तव में, जो चीज से गायब होना प्रतीत होता np.correlateहै वह दूरी distance पर समय बिंदुओं के सभी संभावित जोड़ों पर औसत है

यहां बताया गया है कि मैंने एक फ़ंक्शन को परिभाषित किया जो मुझे आवश्यक था:

def autocross(x, y):
    c = np.correlate(x, y, "same")
    v = [c[i]/( len(x)-abs( i - (len(x)/2)  ) ) for i in range(len(c))]
    return v

ऐसा लगता है कि पिछले उत्तरों में से कोई भी ऑटो / क्रॉस-सहसंबंध के इस उदाहरण को कवर नहीं करता है: आशा है कि यह उत्तर मेरे जैसे स्टोचस्टिक प्रक्रियाओं पर काम करने वाले किसी व्यक्ति के लिए उपयोगी हो सकता है।


1

मैं इस तरह autocorrelation के लिए talib.CORREL का उपयोग करता हूं, मुझे संदेह है कि आप अन्य पैकेजों के साथ भी ऐसा कर सकते हैं:

def autocorrelate(x, period):

    # x is a deep indicator array 
    # period of sample and slices of comparison

    # oldest data (period of input array) may be nan; remove it
    x = x[-np.count_nonzero(~np.isnan(x)):]
    # subtract mean to normalize indicator
    x -= np.mean(x)
    # isolate the recent sample to be autocorrelated
    sample = x[-period:]
    # create slices of indicator data
    correls = []
    for n in range((len(x)-1), period, -1):
        alpha = period + n
        slices = (x[-alpha:])[:period]
        # compare each slice to the recent sample
        correls.append(ta.CORREL(slices, sample, period)[-1])
    # fill in zeros for sample overlap period of recent correlations    
    for n in range(period,0,-1):
        correls.append(0)
    # oldest data (autocorrelation period) will be nan; remove it
    correls = np.array(correls[-np.count_nonzero(~np.isnan(correls)):])      

    return correls

# CORRELATION OF BEST FIT
# the highest value correlation    
max_value = np.max(correls)
# index of the best correlation
max_index = np.argmax(correls)

1

फूरियर रूपांतरण और प्रमेय प्रमेय का उपयोग करना

समय जटिलता एन * लॉग (एन) है

def autocorr1(x):
    r2=np.fft.ifft(np.abs(np.fft.fft(x))**2).real
    return r2[:len(x)//2]

यहाँ एक सामान्यीकृत और निष्पक्ष संस्करण है, यह एन * लॉग (एन) भी है

def autocorr2(x):
    r2=np.fft.ifft(np.abs(np.fft.fft(x))**2).real
    c=(r2/x.shape-np.mean(x)**2)/np.std(x)**2
    return c[:len(x)//2]

ए। लेवी द्वारा प्रदान की गई विधि काम करती है, लेकिन मैंने अपने पीसी में इसका परीक्षण किया, इसकी समय जटिलता एन * एन लगती है

def autocorr(x):
    result = numpy.correlate(x, x, mode='full')
    return result[result.size/2:]

1

Numpy.correlate के लिए एक वैकल्पिक में उपलब्ध है statsmodels.tsa.stattools.acf () । यह ओपी द्वारा वर्णित एक की तरह लगातार घटते ऑटोक्रेलेशन फ़ंक्शन को जन्म देता है। इसे लागू करना काफी सरल है:

from statsmodels.tsa import stattools
# x = 1-D array
# Yield normalized autocorrelation function of number lags
autocorr = stattools.acf( x )

# Get autocorrelation coefficient at lag = 1
autocorr_coeff = autocorr[1]

डिफ़ॉल्ट व्यवहार 40 nlags पर रोकना है, लेकिन इसे nlag=आपके विशिष्ट एप्लिकेशन के विकल्प के साथ समायोजित किया जा सकता है । फ़ंक्शन के पीछे के आंकड़ों के लिए पृष्ठ के निचले भाग में एक उद्धरण है ।


0

मुझे लगता है कि ओपी के प्रश्न का वास्तविक उत्तर स्पष्ट रूप से Numpy.correlate दस्तावेज़ से इस अंश में निहित है:

mode : {'valid', 'same', 'full'}, optional
    Refer to the `convolve` docstring.  Note that the default
    is `valid`, unlike `convolve`, which uses `full`.

इसका तात्पर्य यह है कि, जब कोई 'मोड' परिभाषा के साथ उपयोग किया जाता है, तो Numpy.correlate फ़ंक्शन एक स्केलर लौटाएगा, जब अपने दो इनपुट तर्कों के लिए एक ही वेक्टर दिया जाता है (अर्थात - जब ऑटोक्रॉलेशन करने के लिए उपयोग किया जाता है)।


0

पांडा के बिना एक सरल उपाय:

import numpy as np

def auto_corrcoef(x):
   return np.corrcoef(x[1:-1], x[2:])[0,1]

0

स्टैटिशियल ऑटोकैरेलेशन प्लॉट को पंडों के डेटाइम टाइम रिटर्न की श्रृंखला दी गई:

import matplotlib.pyplot as plt

def plot_autocorr(returns, lags):
    autocorrelation = []
    for lag in range(lags+1):
        corr_lag = returns.corr(returns.shift(-lag)) 
        autocorrelation.append(corr_lag)
    plt.plot(range(lags+1), autocorrelation, '--o')
    plt.xticks(range(lags+1))
    return np.array(autocorrelation)

autocorrelation_plot()इस मामले में उपयोग क्यों नहीं ? ( cf.ysts.stackexchange.com/questions/357300/… )
Qaswed
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.