119 votes

Comment puis-je utiliser numpy.correlate pour faire de l'autocorrélation ?

J'ai besoin de faire l'auto-corrélation d'un ensemble de nombres, ce qui, si je comprends bien, est juste la corrélation de l'ensemble avec lui-même.

J'ai essayé en utilisant la fonction correlate de numpy, mais je ne crois pas le résultat, car il donne presque toujours un vecteur où le premier nombre est no le plus grand, comme il se doit.

Donc, cette question est en fait deux questions :

  1. Qu'est-ce que c'est exactement numpy.correlate à faire ?
  2. Comment puis-je l'utiliser (ou autre chose) pour faire de l'auto-corrélation ?

0 votes

Voir aussi : stackoverflow.com/questions/12269834/ pour des informations sur l'autocorrélation normalisée.

127voto

A. Levy Points 8344

Pour répondre à votre première question, numpy.correlate(a, v, mode) réalise la convolution de a avec l'inverse de v et donnant les résultats écrêtés par le mode spécifié. Le site définition de la convolution , C(t)= - < i < a i v t+i où - < t < , permet d'obtenir des résultats de - à , mais il est évident que vous ne pouvez pas stocker un tableau infiniment long. Il faut donc l'écrêter, et c'est là que le mode intervient. Il existe trois modes différents : complet, identique et valide :

  • Le mode "complet" renvoie les résultats pour chaque t où les deux a y v ont un certain chevauchement.
  • Le mode "same" renvoie un résultat de la même longueur que le vecteur le plus court ( a o v ).
  • Le mode "valide" renvoie des résultats uniquement lorsque a y v se chevauchent complètement. Le site documentation para numpy.convolve donne plus de détails sur les modes.

Pour votre deuxième question, je pense numpy.correlate es vous donne l'autocorrélation, il vous donne juste un peu plus aussi. L'autocorrélation est utilisée pour déterminer dans quelle mesure un signal, ou une fonction, est similaire à lui-même à une certaine différence de temps. Pour une différence de temps de 0, l'autocorrélation devrait être la plus élevée parce que le signal est identique à lui-même, vous vous attendez donc à ce que le premier élément du tableau de résultats de l'autocorrélation soit le plus grand. Cependant, la corrélation ne commence pas à une différence de temps de 0. Elle commence à une différence de temps négative, se rapproche de 0, puis devient positive. C'est ce que vous attendiez :

autocorrélation(a) = - < i < a i v t+i où 0 <= t <

Mais ce que vous avez obtenu, c'est :

autocorrélation(a) = - < i < a i v t+i où - < t <

Ce que vous devez faire est de prendre la dernière moitié de votre résultat de corrélation, et cela devrait être l'autocorrélation que vous recherchez. Une fonction python simple pour faire cela serait :

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

Vous aurez, bien sûr, besoin de vérifier les erreurs pour vous assurer que x est en fait un tableau à 1 dimension. De plus, cette explication n'est probablement pas la plus rigoureuse mathématiquement. J'ai utilisé des infinis parce que la définition de la convolution les utilise, mais cela ne s'applique pas nécessairement à l'autocorrélation. Ainsi, la partie théorique de cette explication peut être légèrement bancale, mais j'espère que les résultats pratiques seront utiles. Ces pages sur l'autocorrélation sont très utiles, et peuvent vous donner une meilleure base théorique si vous n'êtes pas gêné par la notation et les concepts lourds.

7 votes

Dans les versions actuelles de numpy, le mode 'same' peut être spécifié pour réaliser exactement ce que A. Levy a proposé. Le corps de la fonction pourrait alors se lire return numpy.correlate(x, x, mode='same')

14 votes

@DavidZwicker mais les résultats sont différents ! np.correlate(x,x,mode='full')[len(x)//2:] != np.correlate(x,x,mode='same') . Par exemple, 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]) }. Le bon est : np.correlate(x,x,mode='full')[len(x)-1:]; { >>> array([19, 13, 11, 5, 2]) } voir le premier élément es le plus grand .

19 votes

Notez que cette réponse donne l'autocorrélation non normalisée.

31voto

user1025724 Points 61

L'auto-corrélation existe en deux versions : statistique et convolution. Elles font toutes deux la même chose, à un détail près : La version statistique est normalisée pour être sur l'intervalle [-1,1]. Voici un exemple de la façon de faire la version statistique :

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

9 votes

Vous voulez numpy.corrcoef[x:-i], x[i:])[0,1] dans la deuxième ligne comme valeur de retour de corrcoef est une matrice 2x2

0 votes

Quelle est la différence entre l'autocorrélation statistique et l'autocorrélation convolutive ?

2 votes

@DanielPendergast : La deuxième phrase répond à cette question : Ils font tous deux la même chose, à un détail près : La première [statistique] est normalisée pour être sur l'intervalle [-1,1].

24voto

rrv Points 398

Utilisez le numpy.corrcoef au lieu de la fonction numpy.correlate pour calculer la corrélation statistique pour un retard de t :

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

0 votes

Les "coefficients de corrélation" ne font-ils pas référence à l'autocorrélation utilisée dans le traitement du signal et non à l'autocorrélation utilisée en statistique ? fr.wikipedia.org/wiki/Autocorrelation#Traitement du signal

0 votes

@DanielPendergast Je ne suis pas aussi familier avec le traitement du signal. Dans la documentation de numpy : "Renvoie les coefficients de corrélation produit-moment de Pearson". Est-ce la version pour le traitement du signal ?

12voto

maschu Points 131

Comme je viens de rencontrer le même problème, j'aimerais partager quelques lignes de code avec vous. En fait, il y a déjà plusieurs messages similaires sur l'autocorrélation dans stackoverflow. Si vous définissez l'autocorrélation comme a(x, L) = sum(k=0,N-L-1)((xk-xbar)*(x(k+L)-xbar))/sum(k=0,N-1)((xk-xbar)**2) [C'est la définition donnée par la fonction a_correlate d'IDL et elle correspond à ce que je vois dans la réponse 2 de la question. #12269834 ], alors ce qui suit semble donner les résultats corrects :

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

Comme vous le voyez, j'ai testé cette méthode avec une courbe sinusoïdale et une distribution aléatoire uniforme, et les deux résultats sont conformes à ce que j'attendais. Notez que j'ai utilisé mode="same" au lieu de mode="full" comme les autres.

-4voto

tgray Points 4002

1) Voici la documentation pour numpy.correlate . Le code à l'intérieur du fichier ressemble à ceci :

mode = _mode_from_name(mode)
return multiarray.correlate(a,v,mode)

multiarray.correlate pointe vers un fichier .pyd (c'est-à-dire un fichier DLL), donc pour connaître le fonctionnement interne, vous devriez probablement demander aux développeurs de numpy.

2) Si vous ne croyez pas les résultats de numpy, vous pouvez essayer La fonction de corrélation de SciPy .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X