Bu konuya kafa karıştıran 2 şey olduğunu düşünüyorum:
- istatistiksel ve sinyal işleme tanımı: diğerlerinin de işaret ettiği gibi, istatistikte oto-korelasyonu [-1,1] 'e normalleştiriyoruz.
- kısmi vs kısmi olmayan ortalama / varyans: zaman serileri> 0 gecikmesinde değiştiğinde, örtüşme boyutları her zaman <orijinal uzunluk olacaktır. Orijinalin (kısmi olmayan) ortalamasını ve std'sini mi kullanıyoruz yoksa her zaman yeni bir ortalama mı hesaplıyoruz ve sürekli değişen örtüşmeyi (kısmi) kullanarak std bir fark yaratıyor. (Muhtemelen bunun için resmi bir terim vardır, ancak şimdilik "kısmi" kullanacağım).
Kısmi ve kısmi olmayan ayrımlarla 1d dizisinin otomatik korelasyonunu hesaplayan 5 işlev oluşturdum. Bazıları istatistiklerden formül kullanır, bazıları ise sinyal işleme anlamında ilişkilendirme kullanır ve bu FFT ile de yapılabilir. Ancak tüm sonuçlar istatistik tanımındaki otomatik korelasyonlardır , bu nedenle birbirleriyle nasıl bağlantılı olduklarını gösterirler. Aşağıdaki kod:
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()
İşte çıktı şekli:
5 çizginin hepsini görmüyoruz çünkü 3 tanesi üst üste biniyor (mor renkte). Örtüşmelerin tümü kısmi olmayan oto-korelasyonlardır. Bunun nedeni, sinyal işleme yöntemlerinden ( np.correlate
FFT) yapılan hesaplamaların her bir örtüşme için farklı bir ortalama / std hesaplamamasıdır.
Ayrıca fft, no padding, non-partial
(kırmızı çizgi) sonucunun farklı olduğuna dikkat edin , çünkü FFT yapmadan önce zaman serilerini 0'larla doldurmadı, bu yüzden dairesel FFT. Nedenini ayrıntılı olarak açıklayamam, başka yerden öğrendiğim şey buydu.