numpy.correlateを使用して自己相関を行うにはどうすればよいですか?


106

数値のセットの自動相関を行う必要があります。これは、私が理解しているように、セットとそれ自体の相関です。

私はnumpyの相関関数を使用して試してみましたが、最初の数が最大ではないはずのベクトルがほとんど常にあるため、結果は信じられません。

したがって、この質問は実際には2つの質問です。

  1. 正確には何をしnumpy.correlateていますか?
  2. 自動相関を行うにはどうすればよいですか(または他の何か)。

正規化された自己相関については、stackoverflow.com / questions / 12269834 / も参照してください。
amcnabb 2013年

回答:


114

最初の質問に答えるにnumpy.correlate(a, v, mode)a、の逆の畳み込みを実行vし、指定されたモードで切り取られた結果を与えます。畳み込みの定義、C(T)=Σ -∞<I <∞ のV T + Iところ-∞<T <∞、-∞から∞に結果することができますが、あなたは明らかに無限に長い保管することはできませんアレイ。つまり、クリップする必要があり、そこがモードの出番です。3つの異なるモードがあります。フル、同じ、および有効です。

  • すべてのための「フル」モードに戻り結果tの両方の場所av一部重複しています。
  • 「同じ」モードでは、最短のベクトル(aまたはv)と同じ長さの結果が返されます。
  • 「有効」モードはav互いに完全にオーバーラップする場合にのみ結果を返します。ドキュメントのためには、numpy.convolveモードに関するより詳細な情報を提供します。

2番目の質問についてnumpy.correlate 、自己相関が得られると思います。これは、もう少しだけでも得られます。自己相関は、信号または関数が特定の時間差でそれ自体にどの程度類似しているかを見つけるために使用されます。時差が0の場合、信号はそれ自体と同一であるため、自己相関が最も高くなるはずです。したがって、自己相関結果配列の最初の要素が最大になると予想しました。ただし、相関は時間差0から始まりません。負の時間差から始まり、0に近づいてから、正になります。つまり、あなたは期待していました:

自己相関()=Σ -∞<I <∞ IのV T + I 0 <= T <∞

しかし、あなたが得たのは:

自己相関()=Σ -∞<I <∞ IのV T + Iここで、-∞<T <∞

行う必要があるのは、相関結果の後半を取得することであり、これが目的の自己相関でなければなりません。それを行う単純なpython関数は次のようになります。

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

もちろん、これxが実際に1次元配列であることを確認するには、エラーチェックが必要です。また、この説明はおそらく数学的に最も厳密ではありません。畳み込みの定義では無限大を使用しているため、私は無限大をあちこちに使用してきましたが、自己相関には必ずしも当てはまりません。したがって、この説明の理論的な部分は少し不安定であるかもしれませんが、うまくいけば、実際的な結果が役立つでしょう。自己相関に関するこれらの ページは非常に役立ちます。表記法と重い概念をあちこち歩いてもかまわない場合は、理論的背景がはるかによくなります。


6
numpyの現在のビルドでは、A。Levyが提案したものを正確に実現するために、「同じ」モードを指定できます。その後、関数の本体を読み取ることができますreturn numpy.correlate(x, x, mode='same')
David Zwicker、2011

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 2013年

4
@Developerは正しいスライスを提供すると思います。0 [len(x)-1:]ラグから始まります。fullモードは結果サイズを与えるため2*len(x)-1、A.Levyはと[result.size/2:]同じ[len(x)-1:]です。のように、それをintにする方が良い[result.size//2:]です。
ジェイソン

私はそれが、少なくとものpython 3.7で、int型でなければならない見つけ
kevinkayaks

25

自動相関には、統計と畳み込みという2つのバージョンがあります。詳細は少し異なりますが、どちらも同じです。統計バージョンは、間隔[-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]の戻り値corrcoefは2x2マトリックスなので、2行目に必要です
luispedro

統計的自己相関とたたみ込み自己相関の違いは何ですか?
ダニエルは、モニカを

1
@DanielPendergast:2番目の文はその答えです:少し詳細を除いて、どちらも同じように動作します:前者[統計]は間隔[-1,1]に正規化されます
n1k31t4

21

numpy.corrcoef代わりに関数を使用してnumpy.correlate、tのラグの統計的相関を計算します。

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

「相関係数」は、信号処理で使用される自己相関ではなく、統計で使用される自己相関を指すのではないですか?en.wikipedia.org/wiki/Autocorrelation#Signal_processing
Danielはモニカを

@DanielPendergast私は信号処理に慣れていません。numpy docsから:「リターンピアソンの積率相関係数。」それは信号処理バージョンですか?
ラモンJロメロYビジル

18

このトピックを混乱させる2つの点があると思います。

  1. 統計処理と信号処理の定義:他の人が指摘したように、統計では自己相関を[-1,1]に正規化します。
  2. 部分的vs非部分的平均/分散:timeseriesが0を超えるラグでシフトする場合、それらのオーバーラップサイズは常に<元の長さになります。元の(部分的ではない)の平均と標準偏差を使用しますか、それとも常に新しい平均を計算し、常に変化するオーバーラップ(部分的)を使用して標準偏差が違いを生みますか?(これにはおそらく正式な用語がありますが、ここでは「部分」を使用します)。

1次元配列の自己相関を計算する5つの関数を作成しました。部分的な違いと非部分的な違いがあります。統計の公式を使用するものもあれば、信号処理の意味で相関するものもあり、これはFFTを介して行うこともできます。ただし、すべての結果は統計定義の自己相関であるため、結果が互いにどのようにリンクされているかを示しています。以下のコード:

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)からの計算では、オーバーラップごとに異なる平均/標準が計算されないためです。

またfft, no padding, non-partial、FFTを実行する前にtimeseriesに0を埋め込んでいないため、(赤い線)の結果が異なることに注意してください。循環FFTです。その理由を詳しく説明することはできませんが、それが他の場所から学んだことです。


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 2017

@pindakaasもっと具体的に教えてもらえますか?あなたが見つけたどのような不一致がどの機能であるかについての情報を提供してください。
Ruggero、

なぜ使用しないのp = np.abs(f)ですか?
dylnan

@dylnanこれでfのコンポーネントのモジュールが得られますが、ここではfのコンポーネントの正方モジュールを含むベクトルが必要です。
ルッジェロ

1
ええ、でもリストを理解するのはおそらくもっと遅いことをご存知でしたか?
ジェイソン

2

私は計算生物学者であり、時系列の確率過程のカップル間の自己相関/相互相関を計算しなければならないときに、np.correlate必要な仕事をしていないことに気づきました。

実際、そこから欠落しているように見えるのnp.correlateは、距離atで考えられるすべての時間ポイント平均です。

これが私が必要なことをする関数をどのように定義したかです:

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

私はこのような自己相関に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

フーリエ変換と畳み込み定理の使用

時間の複雑さは N * log(N)です

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

これは正規化された公平なバージョンで、N * log(N)でもあり ます

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]

A. Levyが提供する方法は機能しますが、自分のPCでテストしました。その時間の複雑さはN * Nのようです

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

1

numpy.correlateの代替はstatsmodels.tsa.stattools.acf()で利用できます。これにより、OPで記述されるような自己相関関数が連続的に減少します。それを実装するのはかなり簡単です:

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

OPの質問に対する実際の答えは、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関数は、2つの入力引数に同じベクトルを指定すると(つまり、自己相関を実行するために使用される場合)、スカラーを返すことを意味します。


0

パンダなしのシンプルなソリューション:

import numpy as np

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

0

pandas datatimeの一連のリターンを指定して、統計的自己相関をプロットします。

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()この場合はなぜ使用しないのですか?(参照stats.stackexchange.com/questions/357300/...
Qaswed
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.