Frage

Ich brauche Autokorrelation einer Reihe von Zahlen zu tun, die wie ich es verstehe nur die Korrelation der Menge mit sich selbst ist.

Ich habe versucht, es numpy die Korrelat-Funktion, aber ich glaube nicht das Ergebnis, wie es fast immer einen Vektor gibt, wo die erste Zahl ist nicht die größte, wie es sein sollte .

Also, diese Frage ist eigentlich zwei Fragen:

  1. Was genau ist numpy.correlate tun?
  2. Wie kann ich es (oder etwas anderes) Autokorrelation zu tun?
War es hilfreich?

Lösung

Um Ihre erste Frage zu beantworten, numpy.correlate(a, v, mode) ist die Faltung von a mit der Rückseite v Durchführung und die Ergebnisse von dem angegebenen Modus abgeschnitten zu geben. Die Definition der Faltung , C (t) = Σ -∞ a i v t + i , wo -∞

  • „voll“ Modus liefert Ergebnisse für jede t wo beide a und v eine gewisse Überlappung haben.
  • „same“ Modus liefert ein Ergebnis mit der gleichen Länge wie der kürzeste Vektor (a oder v).
  • „gültig“ Modus liefert Ergebnisse nur dann, wenn a und v überlappen einander vollständig. Die Dokumentation für numpy.convolve gibt weitere Einzelheiten über die Modi.

Für Ihre zweite Frage, ich denke numpy.correlate ist können Sie die Autokorrelation zu geben, ist es einfach zu geben als auch ein wenig mehr. Die Autokorrelation wird verwendet, um herauszufinden, wie ähnlich ein Signal oder eine Funktion, zu einer bestimmten Zeit Unterschied zu sich selbst ist. Zu einer Zeitdifferenz von 0, sollte die Autokorrelation der höchste sein, da das Signal an sich selbst identisch ist, so erwartet man, dass das erste Element in der Autokorrelationsergebnis Array wäre die größte sein. Jedoch wird die Korrelation nicht zu einem Zeitunterschied von 0 beginnend beginnt es bei einer negativen Zeitdifferenz, schließt sich auf 0, und geht dann positiv. Das heißt, Sie erwarten:

Autokorrelation (a) = Σ -∞ a i v t + i , wobei 0 <= t <∞

Aber was Sie bekamen, war:

Autokorrelation (a) = Σ -∞ a i v t + i , wobei -∞

Was Sie tun müssen, ist die letzte Hälfte des Korrelationsergebnis nehmen, und dass die Autokorrelations sollten Sie suchen. Eine einfache Python-Funktion, das zu tun wäre:

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

Sie werden natürlich müssen Fehler sicherstellen Überprüfung, dass x ist eigentlich ein 1-d-Array. Auch diese Erklärung wahrscheinlich ist nicht die mathematisch rigoros. Ich habe Unendlichkeiten zu werfen um, weil die Definition der Faltung nutzt sie, aber das bedeutet nicht unbedingt für Autokorrelation gelten. So kann der theoretische Teil dieser Erklärung dafür sein, etwas wackelig, aber hoffentlich die praktischen Ergebnisse sind hilfreich. Diese Seiten auf Autokorrelation sind ziemlich nützlich, und Sie können eine viel bessere theoretischen Hintergrund geben, wenn Sie nicht durch die Notation und schwere Konzepte waten nichts dagegen.

Andere Tipps

Auto-Korrelation kommt in zwei Versionen: statistische und Faltung. Beide tun das gleiche, mit Ausnahme eines kleinen Detail: Die statistische Version normiert ist auf dem Intervall [-1,1]. Hier ist ein Beispiel dafür, wie Sie tun, um die statistischen ein:

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

Mit der numpy.corrcoef Funktion anstelle von < a href = "https://docs.scipy.org/doc/numpy/reference/generated/numpy.correlate.html" rel = "nofollow noreferrer"> numpy.correlate die statistische Korrelation für eine Verzögerung von t zu berechnen :

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

Wie ich gerade in das gleiche Problem lief, würde Ich mag mit Ihnen ein paar Zeilen Code teilen. In der Tat gibt es einige ziemlich ähnliche Beiträge über Autokorrelation in Stackoverflow jetzt. Wenn Sie die Autokorrelation als a(x, L) = sum(k=0,N-L-1)((xk-xbar)*(x(k+L)-xbar))/sum(k=0,N-1)((xk-xbar)**2) definieren [das ist die Definition in IDL a_correlate Funktion gegeben, und es stimmt, was ich in der Antwort 2 von Frage finden Sie unter # 12269834 ], dann scheint die folgende die richtigen Ergebnisse zu erhalten:

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()

Wie Sie sehen, ich habe getestet dies mit einer sin-Kurve und einer einheitlichen statistischen Verteilung, und beiden Ergebnisse sehen aus wie ich sie erwarten würde. Beachten Sie, dass ich mode="same" statt mode="full" verwendet als die anderen.

Ich denke, es gibt zwei Dinge, die Verwirrung zu diesem Thema hinzufügen:

  1. statistische v.s. Signalverarbeitung Definition: wie andere haben darauf hingewiesen, in Statistiken, die wir normalisieren Autokorrelation in [-1,1].
  2. Teil v.s. Nicht-Teil Mittelwert / Varianz: Wenn die Zeitreihen bei einer Verzögerung verschiebt> 0, ihre Überlappung Größe wird immer

Ich habe 5 Funktionen geschaffen, die Autokorrelation eines 1D-Arrays zu berechnen, mit teilweisem V.S. Nichtteilunterscheidungen. Einige verwenden Formel aus der Statistik, korrelieren einige Verwendung in der Signalverarbeitungs Sinn, die auch über FFT durchgeführt werden kann. Aber alle Ergebnisse sind Auto-Korrelationen in den Statistiken Definition, so dass sie zeigen, wie sie miteinander verbunden sind. Code unten:

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()

Hier ist die Ausgabe Figur:

 image description hier

Wir sehen alle 5 Zeilen nicht, weil drei von ihnen (im Purpur) überlappen. Die Überlappungen sind alle nicht-Teilautokorrelationen. Dies liegt daran, Berechnungen von den Signalverarbeitungsmethoden (np.correlate, FFT) nicht über eine unterschiedliche mittlere / std für jede Überlappung berechnen.

Beachten Sie auch, dass die fft, no padding, non-partial (rote Linie) Ergebnis anders ist, weil es nicht Pad die Zeitreihen mit 0s tat, bevor FFT zu tun, so ist es Kreis FFT. Ich kann nicht im Detail erklären, warum, das ist, was ich von woanders gelernt.

Ihre Frage 1 wurde hier in mehreren ausgezeichneten Antworten bereits ausführlich diskutiert.

dachte ich mit Ihnen ein paar Zeilen Code zu teilen, dass Sie die Autokorrelation eines Signals nur auf die mathematischen Eigenschaften der Autokorrelation Basis berechnen lassen. Das heißt, kann die Autokorrelation in der folgenden Art und Weise berechnet werden:

  1. subtrahiert den Mittelwert aus dem Signal und erhält ein unvoreingenommenes Signal

  2. Berechne die Fourier-Transformation des Signals unvoreingenommenen Transformation

  3. , um die spektrale Leistungsdichte des Signals berechnen, indem die quadratische Norm des jeden Wertes der Fourier-Transformation des Signals unvoreingenommenen Transformation unter

  4. Berechnen der inversen Fourier-Transformation der spektralen Leistungsdichte-Transformation

  5. Normalisieren der inverse Fourier durch die Summe der Quadrate der das nicht vorgespannten Signals der spektralen Leistungsdichte-Transformation, und nur die Hälfte des resultierenden Vektors nehmen

Der Code, dies zu tun, ist die folgende:

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)

I talib.CORREL für Autokorrelation wie diese, ich vermute, dass Sie mit anderen Paketen das gleiche tun könnten:

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)

Mit Fourier-Transformation und die Faltungstheorem

Die Zeit Komplexizität ist N * log (N)

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

Hier ist eine normalisierte und unvoreingenommenen Version, es ist auch 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]

Das Verfahren zur Verfügung gestellt von A. Levy funktioniert, aber ich getestet es in meinem PC, seine Zeit Komplexizität scheint zu sein, N * N

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

Ich denke, die wirkliche Antwort auf die Frage des OP kurz und bündig in diesem Auszug aus der Numpy.correlate Dokumentation enthalten ist:

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

Dies impliziert, dass, wenn ohne ‚Mode‘ Definition verwendet, wird die Funktion Numpy.correlate einen skalaren zurückkehren, wenn derselbe Vektor für seine zwei Eingabeargumente gegeben (das heißt - wenn verwendet Autokorrelation durchzuführen).

Eine einfache Lösung ohne Pandas:

import numpy as np

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

Zeichnen Sie die statistische Autokorrelation eine Pandas Datetime-Serie kehrt gegeben:

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)

Ich bin ein Bioinformatiker, und wenn ich das Auto / Kreuzkorrelationen zwischen Paaren von Zeitreihen von stochastischen Prozessen zu berechnen hatte wurde mir klar, dass np.correlate den Job nicht tat ich brauchte.

Ja, was scheint von np.correlate zu fehlen ist die im Durchschnitt über alle möglichen Paare von Zeitpunkten im Abstand τ.

Hier ist, wie ich eine Funktion definiert das tun, was ich brauchte:

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

Es scheint mir keine der vorherigen Antworten auf diese Instanz von Auto / Kreuzkorrelation. Hoffen, dass diese Antwort auf jemanden nützlich sein kann, auf stochastische Prozesse wie ich arbeite

Eine Alternative zu numpy.correlate ist in statsmodels. tsa.stattools.acf () . Dies ergibt eine kontinuierlich abnehmende Autokorrelationsfunktion wie die von OP beschrieben ist. Die Implementierung ist es ziemlich einfach:

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]

Das Standardverhalten ist bei 40 nlags zu stoppen, aber dies kann mit der nlag= Option für Ihre spezifische Anwendung angepasst werden. Es gibt ein Zitat am Ende der Seite für die Statistiken hinter der Funktion .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top