मुझे लगता है कि इस विषय में भ्रम को जोड़ने वाली 2 चीजें हैं:
- सांख्यिकीय बनाम सिग्नल प्रोसेसिंग परिभाषा: जैसा कि अन्य ने बताया है, आंकड़ों में हम ऑटो-सहसंबंध को सामान्य करते हैं [-1,1]।
- आंशिक बनाम गैर-आंशिक माध्य / विचरण: जब समय एक अंतराल> 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 के साथ समय को पैड नहीं करता है, इसलिए यह परिपत्र एफएफटी है। मैं विस्तार से नहीं बता सकता कि क्यों, यही मैंने कहीं और से सीखा है।