python - functions - ¿Cómo puedo usar numpy.correlate para hacer la autocorrelación?
numpy python 3 (8)
Como me encontré con el mismo problema, me gustaría compartir algunas líneas de código con usted. De hecho, hay varias publicaciones bastante similares sobre autocorrelación en stackoverflow por el momento. Si define la autocorrelación como a(x, L) = sum(k=0,NL-1)((xk-xbar)*(x(k+L)-xbar))/sum(k=0,N-1)((xk-xbar)**2)
[esta es la definición dada en la función a_correlate de IDL y concuerda con lo que veo en la respuesta 2 de la pregunta #12269834 ], entonces lo siguiente parece dar los resultados correctos:
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()
Como ven, he probado esto con una curva de sincrón y una distribución aleatoria uniforme, y ambos resultados parecen como los esperaría. Tenga en cuenta que utilicé mode="same"
lugar de mode="full"
como lo hicieron los demás.
Necesito hacer la autocorrelación de un conjunto de números, que, según tengo entendido, es solo la correlación del conjunto consigo mismo.
Lo he intentado usando la función de correlación de numpy, pero no creo el resultado, ya que casi siempre da un vector donde el primer número no es el más grande, como debería ser.
Entonces, esta pregunta es realmente dos preguntas:
- ¿Qué está haciendo exactamente numpy.correlate?
- ¿Cómo puedo usarlo (u otra cosa) para hacer la autocorrelación?
Creo que la respuesta real a la pregunta del OP está contenida sucintamente en este extracto de la documentación de Numpy.correlate:
mode : {''valid'', ''same'', ''full''}, optional
Refer to the `convolve` docstring. Note that the default
is `valid`, unlike `convolve`, which uses `full`.
Esto implica que, cuando se usa sin definición de ''modo'', la función Numpy.correlate devolverá un escalar, cuando se le dé el mismo vector para sus dos argumentos de entrada (es decir, cuando se usa para realizar la autocorrelación).
La autocorrelación viene en dos versiones: estadística y convolución. Ambos hacen lo mismo, excepto por un pequeño detalle: el primero está normalizado para estar en el intervalo [-1,1]. Aquí hay un ejemplo de cómo se hace el estadístico:
def acf(x, length=20):
return numpy.array([1]+[numpy.corrcoef(x[:-i], x[i:]) /
for i in range(1, length)])
Soy un biólogo computacional, y cuando tuve que calcular las correlaciones automáticas / cruzadas entre parejas de series temporales de procesos estocásticos me di cuenta de que np.correlate no estaba haciendo el trabajo que necesitaba.
De hecho, lo que parece faltar en np.correlate es el promedio de todas las parejas posibles de puntos de tiempo en distance / tau.
Aquí es cómo definí una función haciendo lo que necesitaba:
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
Me parece que ninguna de las respuestas anteriores cubre esta instancia de auto / correlación cruzada: espero que esta respuesta pueda ser útil para alguien que trabaje en procesos estocásticos como yo.
Su pregunta 1 ya ha sido ampliamente discutida en varias respuestas excelentes aquí.
Pensé compartir con ustedes algunas líneas de código que le permiten calcular la autocorrelación de una señal basada únicamente en las propiedades matemáticas de la autocorrelación. Es decir, la autocorrelación se puede calcular de la siguiente manera:
restar la media de la señal y obtener una señal imparcial
calcular la transformada de Fourier de la señal imparcial
calcular la densidad espectral de potencia de la señal, tomando la norma cuadrada de cada valor de la transformada de Fourier de la señal imparcial
calcular la transformada de Fourier inversa de la densidad espectral de potencia
normalice la transformada de Fourier inversa de la densidad espectral de potencia por la suma de los cuadrados de la señal imparcial, y tome solo la mitad del vector resultante
El código para hacer esto es el siguiente:
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)
Usando la función numpy.corrcoef
lugar de numpy.correlate
para calcular la correlación estadística para un desfase de t:
def autocorr(x, t=1):
numpy.corrcoef(numpy.array([x[0:len(x)-t], x[t:len(x)]]))
Yo uso talib.CORREL para la autocorrelación de esta manera, sospecho que podría hacer lo mismo con otros paquetes:
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)
Para responder a su primera pregunta, numpy.correlate(a, v, mode)
está realizando la convolución de a
con el reverso de v
dando los resultados recortados por el modo especificado. La definición de convolución , C (t) = Σ -∞ <i <∞ a i v t + i donde -∞ <t <∞, permite obtener resultados de -∞ a ∞, pero obviamente no puede almacenar un tiempo infinitamente largo. formación. Entonces tiene que recortarse, y ahí es donde entra el modo. Hay 3 modos diferentes: completo, mismo y válido:
- El modo "lleno" arroja resultados para cada
t
donde tantoa
comov
tienen cierta superposición. - El modo "mismo" devuelve un resultado con la misma longitud que el vector más corto (
a
ov
). - El modo "válido" devuelve resultados solo cuando
a
yv
se superponen por completo. La documentation paranumpy.convolve
brinda más detalles sobre los modos.
Para su segunda pregunta, creo que numpy.correlate
está dando la autocorrelación, simplemente le está dando un poco más también. La autocorrelación se usa para encontrar cuán similar es una señal, o función, a sí misma en una determinada diferencia de tiempo. En una diferencia de tiempo de 0, la autocorrelación debería ser la más alta porque la señal es idéntica a sí misma, por lo que esperaba que el primer elemento en la matriz de resultados de autocorrelación fuera el más grande. Sin embargo, la correlación no comienza en una diferencia de tiempo de 0. Comienza en una diferencia de tiempo negativa, se cierra a 0 y luego se vuelve positiva. Es decir, estabas esperando:
autocorrelación (a) = Σ -∞ <i <∞ a i v t + i donde 0 <= t <∞
Pero lo que obtuviste fue:
autocorrelación (a) = Σ -∞ <i <∞ a i v t + i donde -∞ <t <∞
Lo que debe hacer es tomar la última mitad del resultado de la correlación, y esa debería ser la autocorrelación que está buscando. Una simple función de python para hacer eso sería:
def autocorr(x):
result = numpy.correlate(x, x, mode=''full'')
return result[result.size/2:]
Por supuesto, necesitará una verificación de errores para asegurarse de que x
sea en realidad una matriz de 1 d. Además, esta explicación probablemente no sea la más matemáticamente rigurosa. He estado lanzando infinitos porque la definición de convolución los usa, pero eso no se aplica necesariamente a la autocorrelación. Por lo tanto, la parte teórica de esta explicación puede ser un poco inestable, pero es de esperar que los resultados prácticos sean útiles. These pages sobre la autocorrelación son bastante útiles, y pueden proporcionarle un mejor trasfondo teórico si no le importa vadear la notación y los conceptos pesados.