Repository: statsmodels/statsmodels

Issue:
VARMAX fit returns AttributeError: cannot reshape list
Hello,

Every time I try to fit a VARMAX model with exogenous variables, I get this error:

```python
AttributeError                            Traceback (most recent call last)
<ipython-input-150-40d241e2864d> in <module>
      2 model = VARMAX(train,exog=exog_train, order=order,  trend=trend, enforce_stationarity=False, enforce_invertibility=False)
      3     # fit model
----> 4 model.start_params

/anaconda3/lib/python3.7/site-packages/statsmodels/tsa/statespace/varmax.py in start_params(self)
    384         # Transform trend / exog params from mean form to intercept form
    385         if self.k_ar > 0 and self.k_trend > 0 or self.mle_regression:
--> 386             print(ar_params)
    387             tmp1= np.array(ar_params).reshape(
    388                     self.k_endog * self.k_ar, self.k_endog

AttributeError: 'list' object has no attribute 'reshape'
```

The code in the error is slightly different from what you would get, because I tried fixing the bug myself (and failed) but the error is the same no matter what I do. The error occurs not when I call the VARMAX function, but rather when I call the modelname.fit(). I truly cannot understand why it's doing this, I put np.array() around everything in the source code trying to fix it. I only get the error when I include an exogenous variable. Please help or let me know what other information you need from me!

Thank you!




Discussion:
Can you please provide a small, self contained example that reproduces the
problem?

On Fri, Aug 23, 2019, 23:14 Sbrowneo <notifications@github.com> wrote:

> Hello,
>
> Every time I try to fit a VARMAX model with exogenous variables, I get
> this error:
>
> AttributeError                            Traceback (most recent call last)<ipython-input-150-40d241e2864d> in <module>
>       2 model = VARMAX(train,exog=exog_train, order=order,  trend=trend, enforce_stationarity=False, enforce_invertibility=False)
>       3     # fit model----> 4 model.start_params
> /anaconda3/lib/python3.7/site-packages/statsmodels/tsa/statespace/varmax.py in start_params(self)
>     384         # Transform trend / exog params from mean form to intercept form
>     385         if self.k_ar > 0 and self.k_trend > 0 or self.mle_regression:--> 386             print(ar_params)
>     387             tmp1= np.array(ar_params).reshape(
>     388                     self.k_endog * self.k_ar, self.k_endog
> AttributeError: 'list' object has no attribute 'reshape'
>
> The code in the error is slightly different from what you would get,
> because I tried fixing the bug myself (and failed) but the error is the
> same no matter what I do. The error occurs not when I call the VARMAX
> function, but rather when I call the modelname.fit(). I truly cannot
> understand why it's doing this, I put np.array() around everything in the
> source code trying to fix it. I only get the error when I include an
> exogenous variable. Please help or let me know what other information you
> need from me!
>
> Thank you!
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/statsmodels/statsmodels/issues/6127?email_source=notifications&email_token=ABKTSRP4S5KHBCFWSUPRCIDQGBOMDA5CNFSM4IPEBQI2YY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4HHENP7A>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/ABKTSRL4ANAVCLYQE5XM6MLQGBOMDANCNFSM4IPEBQIQ>
> .
>


Resolving patch:
diff --git a/statsmodels/tsa/statespace/varmax.py b/statsmodels/tsa/statespace/varmax.py
--- a/statsmodels/tsa/statespace/varmax.py
+++ b/statsmodels/tsa/statespace/varmax.py
@@ -392,7 +392,7 @@ def start_params(self):
                     ma_params *= 0
 
         # Transform trend / exog params from mean form to intercept form
-        if self.k_ar > 0 and self.k_trend > 0 or self.mle_regression:
+        if self.k_ar > 0 and (self.k_trend > 0 or self.mle_regression):
             coefficient_matrices = (
                 ar_params.reshape(
                     self.k_endog * self.k_ar, self.k_endog


Test patch:
diff --git a/statsmodels/tsa/statespace/tests/test_varmax.py b/statsmodels/tsa/statespace/tests/test_varmax.py
--- a/statsmodels/tsa/statespace/tests/test_varmax.py
+++ b/statsmodels/tsa/statespace/tests/test_varmax.py
@@ -13,7 +13,7 @@
 import pandas as pd
 import pytest
 
-from statsmodels.tsa.statespace import varmax
+from statsmodels.tsa.statespace import varmax, sarimax
 from statsmodels.iolib.summary import forg
 
 from .results import results_varmax
@@ -1129,3 +1129,47 @@ def test_apply_results():
 
     assert_allclose(res3.forecast(10, exog=np.ones(10)),
                     res1.forecast(10, exog=np.ones(10)))
+
+
+def test_vma1_exog():
+    # Test the VMAX(1) case against univariate MAX(1) models
+    dta = pd.DataFrame(
+        results_varmax.lutkepohl_data, columns=['inv', 'inc', 'consump'],
+        index=pd.date_range('1960-01-01', '1982-10-01', freq='QS'))
+    dta = np.log(dta).diff().iloc[1:]
+
+    endog = dta.iloc[:, :2]
+    exog = dta.iloc[:, 2]
+
+    ma_params1 = [-0.01, 1.4, -0.3, 0.002]
+    ma_params2 = [0.004, 0.8, -0.5, 0.0001]
+
+    vma_params = [ma_params1[0], ma_params2[0],
+                  ma_params1[2], 0,
+                  0, ma_params2[2],
+                  ma_params1[1], ma_params2[1],
+                  ma_params1[3], ma_params2[3]]
+
+    # Joint VMA model
+    mod_vma = varmax.VARMAX(endog, exog=exog, order=(0, 1),
+                            error_cov_type='diagonal')
+    mod_vma.ssm.initialize_diffuse()
+    res_mva = mod_vma.smooth(vma_params)
+
+    # Smoke test that start_params doesn't raise an error
+    sp = mod_vma.start_params
+    assert_equal(len(sp), len(mod_vma.param_names))
+
+    # Univariate MA models
+    mod_ma1 = sarimax.SARIMAX(endog.iloc[:, 0], exog=exog, order=(0, 0, 1),
+                              trend='c')
+    mod_ma1.ssm.initialize_diffuse()
+    mod_ma2 = sarimax.SARIMAX(endog.iloc[:, 1], exog=exog, order=(0, 0, 1),
+                              trend='c')
+    mod_ma2.ssm.initialize_diffuse()
+    res_ma1 = mod_ma1.smooth(ma_params1)
+    res_ma2 = mod_ma2.smooth(ma_params2)
+
+    # Have to ignore first 2 observations due to differences in initialization
+    assert_allclose(res_mva.llf_obs[2:],
+                    (res_ma1.llf_obs + res_ma2.llf_obs)[2:])