Eu preciso fazer a autocorrelação de um conjunto de números, que pelo que entendi é apenas a correlação do conjunto consigo mesmo.
Eu tentei usando a função correlate de numpy, mas não acredito no resultado, pois quase sempre dá um vetor onde o primeiro número não é o maior, como deveria ser.
Então, esta questão é realmente duas questões:
- O que exatamente está
numpy.correlate
fazendo? - Como posso usá-lo (ou outra coisa) para fazer a autocorrelação?
Respostas:
Para responder à sua primeira pergunta,
numpy.correlate(a, v, mode)
é realizar a convolução dea
com o reverso dev
e dar os resultados recortados pelo modo especificado. A definição de convolução , C (t) = ∑ -∞ <i <∞ a i v t + i onde -∞ <t <∞, permite resultados de -∞ a ∞, mas obviamente você não pode armazenar um infinitamente longo array. Portanto, ele deve ser cortado, e é aí que entra o modo. Existem 3 modos diferentes: completo, igual e válido:t
locais em que ambosa
ev
têm alguma sobreposição.a
ouv
).a
ev
completamente sobrepõem uns aos outros. A documentação paranumpy.convolve
dá mais detalhes sobre os modos.Para a sua segunda pergunta, acho que
numpy.correlate
está dando a autocorrelação, está apenas dando um pouco mais também. A autocorrelação é usada para descobrir o quão similar um sinal, ou função, é consigo mesmo em uma certa diferença de tempo. Em uma diferença de tempo de 0, a autocorrelação deve ser a mais alta porque o sinal é idêntico a ele mesmo, então você esperava que o primeiro elemento na matriz de resultado de autocorrelação fosse o maior. No entanto, a correlação não começa em uma diferença de tempo de 0. Ela começa em uma diferença de tempo negativa, fecha em 0 e, em seguida, torna-se positiva. Ou seja, você estava esperando:autocorrelação (a) = ∑ -∞ <i <∞ a i v t + i onde 0 <= t <∞
Mas o que você conseguiu foi:
autocorrelação (a) = ∑ -∞ <i <∞ a i v t + i onde -∞ <t <∞
O que você precisa fazer é pegar a última metade do resultado da correlação, e essa deve ser a autocorrelação que você está procurando. Uma função python simples para fazer isso seria:
É claro que você precisará da verificação de erros para ter certeza de que
x
é realmente um array 1-d. Além disso, essa explicação provavelmente não é a mais matematicamente rigorosa. Tenho discutido infinitos porque a definição de convolução os usa, mas isso não se aplica necessariamente à autocorrelação. Portanto, a parte teórica desta explicação pode ser um pouco confusa, mas espero que os resultados práticos sejam úteis. Essas páginas sobre autocorrelação são muito úteis e podem fornecer uma base teórica muito melhor se você não se importar em percorrer a notação e conceitos pesados.fonte
return numpy.correlate(x, x, mode='same')
np.correlate(x,x,mode='full')[len(x)//2:] != np.correlate(x,x,mode='same')
. Por exemplo,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])
}. O correto é:np.correlate(x,x,mode='full')[len(x)-1:];
{>>> array([19, 13, 11, 5, 2])
} veja que o primeiro item é o maior .[len(x)-1:]
começa no 0-lag. Como ofull
modo fornece um tamanho de resultado2*len(x)-1
, A.Levy's[result.size/2:]
é o mesmo que[len(x)-1:]
. É melhor torná-lo um int, no entanto[result.size//2:]
.A autocorrelação vem em duas versões: estatística e convolução. Ambos fazem o mesmo, exceto por um pequeno detalhe: A versão estatística é normalizada para estar no intervalo [-1,1]. Aqui está um exemplo de como você faz o estatístico:
fonte
numpy.corrcoef[x:-i], x[i:])[0,1]
a segunda linha, pois o valor de retorno decorrcoef
é uma matriz 2x2Use a
numpy.corrcoef
função em vez denumpy.correlate
para calcular a correlação estatística para um atraso de t:fonte
Acho que há 2 coisas que confundem este tópico:
Eu criei 5 funções que calculam a autocorrelação de um array 1d, com distinções parciais versus não parciais. Alguns usam fórmulas de estatísticas, outros usam correlato no sentido de processamento de sinal, o que também pode ser feito via FFT. Mas todos os resultados são autocorrelações na definição de estatísticas , portanto, ilustram como estão vinculados uns aos outros. Código abaixo:
Aqui está o resultado:
Não vemos todas as 5 linhas porque 3 delas se sobrepõem (no roxo). As sobreposições são todas autocorrelações não parciais. Isso ocorre porque os cálculos dos métodos de processamento de sinal (
np.correlate
, FFT) não calculam uma média / padrão diferente para cada sobreposição.Observe também que o resultado
fft, no padding, non-partial
(linha vermelha) é diferente, porque ele não preencheu a série do tempo com 0s antes de fazer FFT, então é FFT circular. Não consigo explicar em detalhes o porquê, foi o que aprendi em outro lugar.fonte
Como acabei de encontrar o mesmo problema, gostaria de compartilhar algumas linhas de código com você. Na verdade, existem vários posts bastante semelhantes sobre autocorrelação em stackoverflow até agora. Se você definir a autocorrelação 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 é a definição dada na função a_correlate do IDL e concorda com o que vejo na resposta 2 da pergunta # 12269834 ], então o seguinte parece dar os resultados corretos:Como você pode ver, testei isso com uma curva de pecado e uma distribuição aleatória uniforme, e ambos os resultados parecem esperados. Observe que eu usei em
mode="same"
vez demode="full"
como os outros fizeram.fonte
Sua pergunta 1 já foi amplamente discutida em várias respostas excelentes aqui.
Pensei em compartilhar com vocês algumas linhas de código que permitem calcular a autocorrelação de um sinal com base apenas nas propriedades matemáticas da autocorrelação. Ou seja, a autocorrelação pode ser calculada da seguinte maneira:
subtraia a média do sinal e obtenha um sinal imparcial
calcular a transformada de Fourier do sinal imparcial
calcular a densidade espectral de potência do sinal, tomando a norma quadrada de cada valor da transformada de Fourier do sinal imparcial
calcular a transformada inversa de Fourier da densidade espectral de potência
normalize a transformada inversa de Fourier da densidade espectral de potência pela soma dos quadrados do sinal não enviesado e pegue apenas metade do vetor resultante
O código para fazer isso é o seguinte:
fonte
p = np.abs(f)
?Sou um biólogo computacional e, quando tive que calcular as correlações auto / cruzadas entre pares de séries temporais de processos estocásticos, percebi que
np.correlate
não estava fazendo o trabalho de que precisava.Na verdade, o que parece estar faltando
np.correlate
é a média de todos os pares possíveis de pontos de tempo à distância 𝜏.Aqui está como eu defini uma função fazendo o que eu precisava:
Parece-me que nenhuma das respostas anteriores cobre esta instância de auto / correlação cruzada: espero que esta resposta possa ser útil para alguém que trabalha com processos estocásticos como eu.
fonte
Eu uso talib.CORREL para autocorrelação como esta, suspeito que você poderia fazer o mesmo com outros pacotes:
fonte
Usando a transformação de Fourier e o teorema da convolução
A complexidade do tempo é N * log (N)
Aqui está uma versão normalizada e imparcial, também é N * log (N)
O método fornecido por A. Levy funciona, mas eu testei em meu PC, sua complexidade de tempo parece ser N * N
fonte
Uma alternativa para numpy.correlate está disponível em statsmodels.tsa.stattools.acf () . Isso resulta em uma função de autocorrelação continuamente decrescente como a descrita por OP. Implementar é bastante simples:
O comportamento padrão é parar em 40 nlags, mas isso pode ser ajustado com a
nlag=
opção para seu aplicativo específico. Há uma citação na parte inferior da página para as estatísticas por trás da função .fonte
Acho que a verdadeira resposta para a pergunta do OP está contida de forma sucinta neste trecho da documentação Numpy.correlate:
Isso implica que, quando usada sem definição de 'modo', a função Numpy.correlate retornará um escalar, quando dado o mesmo vetor para seus dois argumentos de entrada (ou seja, quando usada para realizar autocorrelação).
fonte
Uma solução simples sem pandas:
fonte
Trace a autocorrelação estatística dada uma data de tempo do pandas Série de retornos:
fonte
autocorrelation_plot()
neste caso? (cf. stats.stackexchange.com/questions/357300/… )