Exogene Python ARIMA-Variable außerhalb der Probe

Ich versuche, eine Zeitreihe im ARIMA-Paket von Python-Statistikmodellen unter Einbeziehung einer exogenen Variablen vorherzusagen, kann jedoch nicht herausfinden, wie die exogene Variable im Vorhersageschritt korrekt eingefügt werden kann. SehenHier für docs.

import numpy as np
from scipy import stats
import pandas as pd

import statsmodels.api as sm

vals = np.random.rand(13)
ts = pd.TimeSeries(vals)
df = pd.DataFrame(ts, columns=["test"])
df.index = pd.Index(pd.date_range("2011/01/01", periods = len(vals), freq = 'Q'))

fit1 = sm.tsa.ARIMA(df, (1,0,0)).fit()
#this works fine:
pred1 = fit1.predict(start=12, end = 16)
print(pred1)

Out[32]: 
2014-03-31    0.589121
2014-06-30    0.747575
2014-09-30    0.631322
2014-12-31    0.654858
2015-03-31    0.650093
Freq: Q-DEC, dtype: float64

Fügen Sie nun eine trendexogene Variable hinzu

exogx = np.array(range(1,14))
#to make this easy, let's look at the ols of the trend (arima(0,0,0))
fit2 = sm.tsa.ARIMA(df, (0,0,0),exog = exogx).fit()
print(fit2.params)

const    0.555226
x1       0.013132
dtype: float64

print(fit2.fittedvalues)

2011-03-31    0.568358
2011-06-30    0.581490
2011-09-30    0.594622
2011-12-31    0.607754
2012-03-31    0.620886
2012-06-30    0.634018
2012-09-30    0.647150
2012-12-31    0.660282
2013-03-31    0.673414
2013-06-30    0.686546
2013-09-30    0.699678
2013-12-31    0.712810
2014-03-31    0.725942
Freq: Q-DEC, dtype: float64

Beachten Sie, wie zu erwarten, dass dies eine Trendlinie ist, die sich mit jedem Zeitanstieg um 0,013132 erhöht (dies sind natürlich zufällige Daten. Wenn Sie sie also ausführen, sind die Werte unterschiedlich, aber die positive oder negative Trendgeschichte ist die gleich). Der nächste Wert (für die Zeit = 14) sollte also 0,555226 + 0,013132 * 14 = 0,739074 sein.

#out of sample exog should be (14,15,16)
pred2 = fit2.predict(start = 12, end = 16, exog = np.array(range(13,17)))
print(pred2)
2014-03-31    0.725942
2014-06-30    0.568358
2014-09-30    0.581490
2014-12-31    0.594622
2015-03-31    0.765338
Freq: Q-DEC, dtype: float64

So sagt der 31.03.2014 (das letzte Beispiel) richtig voraus, aber der 30.06.2014 beginnt wieder am Anfang (t = 1), aber beachtet den 31.03.2015 (eigentlich immer die letzte Beobachtung der Vorhersage). unabhängig vom Horizont) erreicht t = 16 (dh (Wert - Schnittpunkt) / beta = (0,765338 - 0,555226) / 0,013132).

Beachten Sie zur Verdeutlichung, was passiert, wenn ich die Werte der x-Matte aufblase

fit2.predict(start = 12, end = 16, exog = np.array(range(13,17))*10000)
Out[41]: 
2014-03-31       0.725942
2014-06-30       0.568358
2014-09-30       0.581490
2014-12-31       0.594622
2015-03-31    2101.680532
Freq: Q-DEC, dtype: float64

Sehen Sie, dass 2015-03-31 explodiert ist, aber keiner der anderen xmat-Werte berücksichtigt wurde? Was mache ich hier falsch ???

Ich habe versucht, mit allen mir bekannten Methoden für die Übergabe der Exog-Variablen herumzuspielen (Ändern der Dimension, Erstellen einer Matrix für das Exog, Erstellen des Exogs als Eingabe plus Horizont usw. usw. usw.). Anregungen wäre sehr dankbar.

Ich benutze 2.7 von Anaconda2.1 numpy 1.8.1 scipy 0.14.0 pandas 0.14.0 statsmodels 0.5.0

und haben das Problem auf Windows 7 64-Bit und Centos 64-Bit überprüft.

Auch ein paar Dinge. Ich verwende ARIMA für die ARIMA-Funktionalität und das oben Genannte dient nur der Veranschaulichung (das heißt, ich kann nicht "nur OLS verwenden ...", wie ich mir vorstellen kann). Ich kann aufgrund der Einschränkungen des Projekts (und allgemeiner der mangelnden Unterstützung von R in Base Spark) auch nicht "nur R verwenden".

Hier sind die interessanten Teile des Codes für den Fall, dass Sie es selbst ausprobieren möchten

import numpy as np
from scipy import stats
import pandas as pd
import statsmodels.api as sm

vals = np.random.rand(13)
ts = pd.TimeSeries(vals)
df = pd.DataFrame(ts, columns=["test"])
df.index = pd.Index(pd.date_range("2011/01/01", periods = len(vals), freq = 'Q'))

exogx = np.array(range(1,14))
fit2 = sm.tsa.ARIMA(df, (0,0,0),exog = exogx).fit()
print(fit2.fittedvalues)
pred2 = fit2.predict(start = 12, end = 16, exog = np.array(range(13,17))*10000)
print(pred2)

Antworten auf die Frage(3)

Ihre Antwort auf die Frage