web-dev-qa-db-fra.com

Pourquoi est-ce que je reçois "LinAlgError: Singular matrix" de grangercausalitytests?

J'essaie d'exécuter grangercausalitytests sur deux séries chronologiques:

import numpy as np
import pandas as pd

from statsmodels.tsa.stattools import grangercausalitytests

n = 1000
ls = np.linspace(0, 2*np.pi, n)

df1 = pd.DataFrame(np.sin(ls))
df2 = pd.DataFrame(2*np.sin(1+ls))

df = pd.concat([df1, df2], axis=1)

df.plot()

grangercausalitytests(df, maxlag=20)

Cependant, je reçois

Granger Causality
number of lags (no zero) 1
ssr based F test:         F=272078066917221398041264652288.0000, p=0.0000  , df_denom=996, df_num=1
ssr based chi2 test:   chi2=272897579166972095424217743360.0000, p=0.0000  , df=1
likelihood ratio test: chi2=60811.2671, p=0.0000  , df=1
parameter F test:         F=272078066917220553616334520320.0000, p=0.0000  , df_denom=996, df_num=1

Granger Causality
number of lags (no zero) 2
ssr based F test:         F=7296.6976, p=0.0000  , df_denom=995, df_num=2
ssr based chi2 test:   chi2=14637.3954, p=0.0000  , df=2
likelihood ratio test: chi2=2746.0362, p=0.0000  , df=2
parameter F test:         F=13296850090491009488285469769728.0000, p=0.0000  , df_denom=995, df_num=2
...
/usr/local/lib/python3.5/dist-packages/numpy/linalg/linalg.py in _raise_linalgerror_singular(err, flag)
     88 
     89 def _raise_linalgerror_singular(err, flag):
---> 90     raise LinAlgError("Singular matrix")
     91 
     92 def _raise_linalgerror_nonposdef(err, flag):

LinAlgError: Singular matrix

et je ne sais pas pourquoi c'est le cas.

11
displayname

Le problème se pose en raison de la parfaite corrélation entre les deux séries dans vos données. D'après le traçage, vous pouvez voir qu'en interne un test de wald est utilisé pour calculer les estimations du maximum de vraisemblance pour les paramètres de la série temporelle. Pour ce faire, une estimation de la matrice de covariance des paramètres (qui est alors proche de zéro) et son inverse est nécessaire (comme vous pouvez également le voir sur la ligne invcov = np.linalg.inv(cov_p) dans le tracé). Cette matrice proche de zéro est désormais singulière pour un certain décalage maximum (> = 5) et donc le test se bloque. Si vous ajoutez juste un peu de bruit à vos données, l'erreur disparaît:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.stattools import grangercausalitytests

n = 1000
ls = np.linspace(0, 2*np.pi, n)
df1Clean = pd.DataFrame(np.sin(ls))
df2Clean = pd.DataFrame(2*np.sin(ls+1))
dfClean = pd.concat([df1Clean, df2Clean], axis=1)
dfDirty = dfClean+0.00001*np.random.Rand(n, 2)

grangercausalitytests(dfClean, maxlag=20, verbose=False)    # Raises LinAlgError
grangercausalitytests(dfDirty, maxlag=20, verbose=False)    # Runs fine
22
jotasi

Une autre chose à surveiller est les colonnes en double. Les colonnes en double auront un score de corrélation de 1,0, résultant en une singularité. Sinon, il est également possible que vous ayez 2 fonctionnalités parfaitement corrélées. Et un moyen facile de vérifier cela est avec df.corr(), et recherchez des paires de colonnes avec corrélation = 1.0.

2
user12081571