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 probé usando la función de correlación de numpy, pero no creo en 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 son realmente dos preguntas:
- ¿Qué está
numpy.correlate
haciendo exactamente ? - ¿Cómo puedo usarlo (o algo más) para hacer la autocorrelación?
Respuestas:
Para responder a su primera pregunta,
numpy.correlate(a, v, mode)
está realizando la convolución dea
con el reverso dev
y 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 resultados de -∞ a ∞, pero obviamente no se puede almacenar un valor infinitamente largo formación. Por lo tanto, debe recortarse, y ahí es donde entra el modo. Hay 3 modos diferentes: completo, igual y válido:t
casosa
y ambosv
se superponen.a
ov
).a
yv
por completo se superponen entre sí. La documentación paranumpy.convolve
da más detalles sobre los modos.Para tu segunda pregunta, creo que te
numpy.correlate
está dando la autocorrelación, solo te está dando un poco más también. La autocorrelación se usa para encontrar qué tan similar es una señal o función a sí misma en una determinada diferencia de tiempo. Con 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 de la matriz de resultados de autocorrelación fuera el mayor. Sin embargo, la correlación no comienza con una diferencia de tiempo de 0. Comienza con 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 de su resultado de correlación, y esa debería ser la autocorrelación que está buscando. Una función de Python simple para hacer eso sería:
Por supuesto, necesitará una verificación de errores para asegurarse de que en
x
realidad sea una matriz 1-d. Además, esta explicación probablemente no sea la más rigurosa matemáticamente. 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 imprecisa, pero es de esperar que los resultados prácticos sean útiles. Estas páginas sobre autocorrelación son bastante útiles y pueden brindarle una base teórica mucho mejor si no le importa recorrer la notación y los conceptos pesados.fuente
return numpy.correlate(x, x, mode='same')
np.correlate(x,x,mode='full')[len(x)//2:] != np.correlate(x,x,mode='same')
. Por ejemplo,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])
}. La correcta es:np.correlate(x,x,mode='full')[len(x)-1:];
{>>> array([19, 13, 11, 5, 2])
} vea que el primer elemento es el más grande .[len(x)-1:]
comienza desde el retraso 0. Debido a que elfull
modo da un tamaño de resultado2*len(x)-1
, el de A.Levy[result.size/2:]
es lo mismo que[len(x)-1:]
. Sin embargo, es mejor convertirlo en un int, como[result.size//2:]
.La autocorrelación viene en dos versiones: estadística y convolución. Ambos hacen lo mismo, excepto por un pequeño detalle: la versión estadística está normalizada para estar en el intervalo [-1,1]. Aquí hay un ejemplo de cómo se hace la estadística:
fuente
numpy.corrcoef[x:-i], x[i:])[0,1]
en la segunda línea ya que el valor de retorno decorrcoef
es una matriz de 2x2Utilice la
numpy.corrcoef
función en lugar denumpy.correlate
para calcular la correlación estadística para un retraso de t:fuente
Creo que hay 2 cosas que agregan confusión a este tema:
He creado 5 funciones que calculan la autocorrelación de una matriz 1d, con distinciones parciales y no parciales. Algunos usan fórmulas de estadísticas, algunos usan correlación en el sentido de procesamiento de señales, lo que también se puede hacer mediante FFT. Pero todos los resultados son autocorrelaciones en la definición de estadísticas , por lo que ilustran cómo están vinculados entre sí. Código a continuación:
Aquí está la figura de salida:
No vemos las 5 líneas porque 3 de ellas se superponen (en la púrpura). Las superposiciones son todas autocorrelaciones no parciales. Esto se debe a que los cálculos de los métodos de procesamiento de señales (
np.correlate
, FFT) no calculan una media / estándar diferente para cada superposición.También tenga en cuenta que el resultado
fft, no padding, non-partial
(línea roja) es diferente, porque no rellenó la serie temporal con 0 antes de hacer FFT, por lo que es circular FFT. No puedo explicar en detalle por qué, eso es lo que aprendí en otros lugares.fuente
Como acabo de encontrarme con el mismo problema, me gustaría compartir algunas líneas de código con ustedes. De hecho, hay varias publicaciones bastante similares sobre la autocorrelación en stackoverflow a estas alturas. Si define la autocorrelación como
a(x, L) = sum(k=0,N-L-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 está de acuerdo con lo que veo en la respuesta 2 de la pregunta # 12269834 ], entonces lo siguiente parece dar los resultados correctos:Como puede ver, he probado esto con una curva sin y una distribución aleatoria uniforme, y ambos resultados se ven como los esperaría. Tenga en cuenta que usé en
mode="same"
lugar de lomode="full"
que hicieron los demás.fuente
Su pregunta 1 ya se ha discutido ampliamente en varias respuestas excelentes aquí.
Pensé en compartir con ustedes algunas líneas de código que les permiten calcular la autocorrelación de una señal basándose ú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 insesgada
calcular la transformada de Fourier de la señal insesgada
Calcule 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 insesgada.
calcular la transformada de Fourier inversa de la densidad espectral de potencia
normalizar la transformada de Fourier inversa de la densidad espectral de potencia mediante la suma de los cuadrados de la señal insesgada y tomar solo la mitad del vector resultante
El código para hacer esto es el siguiente:
fuente
p = np.abs(f)
?Soy biólogo computacional, y cuando tuve que calcular las correlaciones automáticas / cruzadas entre pares de series de tiempo de procesos estocásticos, me di cuenta de que
np.correlate
no estaba haciendo el trabajo que necesitaba.De hecho, lo que parece faltar
np.correlate
es el promedio de todas las parejas posibles de puntos de tiempo a la distancia 𝜏.Así es como definí una función haciendo lo que necesitaba:
Me parece que ninguna de las respuestas anteriores cubre esta instancia de correlación automática / cruzada: espero que esta respuesta pueda ser útil para alguien que trabaja en procesos estocásticos como yo.
fuente
Yo uso talib.CORREL para autocorrelación como esta, sospecho que podrías hacer lo mismo con otros paquetes:
fuente
Usando la transformación de Fourier y el teorema de convolución
La complejidad del tiempo es N * log (N)
Aquí hay una versión normalizada e imparcial, también es N * log (N)
El método proporcionado por A. Levy funciona, pero lo probé en mi PC, su complejidad de tiempo parece ser N * N
fuente
Una alternativa a numpy.correlate está disponible en statsmodels.tsa.stattools.acf () . Esto produce una función de autocorrelación continuamente decreciente como la descrita por OP. Implementarlo es bastante simple:
El comportamiento predeterminado es detenerse en 40 nlags, pero esto se puede ajustar con la
nlag=
opción para su aplicación específica. Hay una cita en la parte inferior de la página para las estadísticas detrás de la función .fuente
Creo que la respuesta real a la pregunta del OP está contenida sucintamente en este extracto de la documentación de Numpy.correlate:
Esto implica que, cuando se usa sin una definición de 'modo', la función Numpy.correlate devolverá un escalar, cuando se le proporcione el mismo vector para sus dos argumentos de entrada (es decir, cuando se use para realizar la autocorrelación).
fuente
Una solución simple sin pandas:
fuente
Grafique la autocorrelación estadística dada una serie de rendimientos de pandas datatime:
fuente
autocorrelation_plot()
en este caso? (cf. stats.stackexchange.com/questions/357300/… )