2015-02-02 20 views
7

È possibile eseguire una correlazione automatica incrociata/automatica su array 1D con una funzione numpy/scipy/matplotlib? Ho visto numpy.correlate() e matplotlib.pyplot.xcorr (basato sulla funzione numpy), ed entrambi sembrano non essere in grado di fare una correlazione incrociata circolare.python correlazione circolare circolare

Per illustrare la differenza, userò l'esempio di un array di [1, 2, 3, 4]. Con la correlazione circolare, viene fatta un'ipotesi periodica e un ritardo di 1 assomiglia a [2, 3, 4, 1]. Le funzioni python che ho trovato sembrano usare solo padding zero, cioè [2, 3, 4, 0]. C'è un modo per ottenere queste funzioni per fare la correlazione circolare? In caso contrario, esiste una soluzione standard per le correlazioni circolari?

risposta

8

È possibile implementare la periodica (aka circolare) di correlazione incrociata utilizzando il FFT:

from numpy.fft import fft, ifft 

def periodic_corr(x, y): 
    """Periodic correlation, implemented using the FFT. 

    x and y must be real sequences with the same length. 
    """ 
    return ifft(fft(x) * fft(y).conj()).real 

È possibile anche implementare utilizzando np.correlate, se non ti dispiace l'overhead sostenute da np.hstack((y[1:], y)):

import numpy as np 

def periodic_corr_np(x, y): 
    """Periodic correlation, implemented using np.correlate. 

    x and y must be real sequences with the same length. 
    """ 
    return np.correlate(x, np.hstack((y[1:], y)), mode='valid') 
+0

Non solo la versione fft elimina l'overhead di hstack, ma rende anche il calcolo in n * log (n) complessità rispetto a n^2 nel caso di correlazione. –

+0

Secondo [1] e alcune [altre fonti] (http://mathworld.wolfram.com/Cross-Correlation.html) il primo termine dovrebbe essere coniugato: 'ifft (fft (x) .conj() * fft (y)). real' [1] Papoulis, A. The Fourier Integral e le sue applicazioni. New York: McGraw-Hill, pp. 244-245 e 252-253, 1962. [Link di Google Libri] (https://books.google.de/books?id=txMIAQAAIAAJ) –

2
from numpy import roll, correlate 
x = [1,2,3,4] 
roll(x, 1) #[4,1,2,3] 
roll(x, 2) #[3,4,1,2] 
roll(x, 3) #[2,3,4,1] 

Per correlare x con x circolarmente spostato da k, è possibile fare

k = 2 
correlate(x, roll(x,k))