[[statsmodels]]のARモデルのpredictメソッドのdynamicオプションについて。
---
[[Time Series Analysis in Python with statsmodels]]
---
[Autoregressions — statsmodels](https://www.statsmodels.org/dev/examples/notebooks/generated/autoregressions.html#Forecasting)
> Forecasts are produced using the predict method from a results instance. The default produces static forecasts which are one-step forecasts. Producing multi-step forecasts requires using dynamic=True.
> 予測は、resultsインスタンスからpredictメソッドで生成されます。デフォルトでは、1ステップの予測である静的な予測が生成されます。多段階の予測を行うには、dynamic=Trueを使用する必要があります。
> この次のセルでは、サンプルの最後の24期間について、12段階の聞き取りによる予測を作成します。これにはループが必要です。
```python
import numpy as np
start = ind_prod.index[-24]
forecast_index = pd.date_range(start, freq=ind_prod.index.freq, periods=36)
cols = ["-".join(str(val) for val in (idx.year, idx.month)) for idx in forecast_index]
forecasts = pd.DataFrame(index=forecast_index, columns=cols)
for i in range(1, 24):
fcast = res_glob.predict(
start=forecast_index[i], end=forecast_index[i + 12], dynamic=True
)
forecasts.loc[fcast.index, cols[i]] = fcast
_, ax = plt.subplots(figsize=(16, 10))
ind_prod.iloc[-24:].plot(ax=ax, color="black", linestyle="--")
ax = forecasts.plot(ax=ax)
```
[statsmodels.tsa.ar_model.AutoReg.predict — statsmodels](https://www.statsmodels.org/v0.12.2/generated/statsmodels.tsa.ar_model.AutoReg.predict.html#statsmodels.tsa.ar_model.AutoReg.predict)
> Integer offset relative to start at which to begin dynamic prediction. Prior to this observation, true endogenous values will be used for prediction; starting with this observation and continuing through the end of prediction, forecasted endogenous values will be used instead. Datetime-like objects are not interpreted as offsets. They are instead used to find the index location of dynamic which is then used to to compute the offset.
動的予測を開始する開始点からの相対的な整数オフセット。この観測の前に、真の内因性値が予測に使用される。この観測から始まり、予測の終わりまで、予測された内因性値が代わりに使用される。日時的なオブジェクトはオフセットとして解釈されない。代わりに、オフセットを計算するために使用されるdynamicのインデックス位置を見つけるために使用されます。
## コードリーディング
以下statsmodels v0.12.2
**static prediction**
```python
def _static_oos_predict(self, params, num_oos, exog_oos):
new_x = self._setup_oos_forecast(num_oos, exog_oos)
if self._maxlag == 0:
return new_x @ params
forecasts = np.empty(num_oos)
nexog = 0 if self.exog is None else self.exog.shape[1]
ar_offset = self._x.shape[1] - nexog - self._lags.shape[0]
for i in range(num_oos):
for j, lag in enumerate(self._lags):
loc = i - lag
val = self._y[loc] if loc < 0 else forecasts[loc]
new_x[i, ar_offset + j] = val
forecasts[i] = new_x[i : i + 1] @ params
return forecasts
def _static_predict(self, params, start, end, num_oos, exog, exog_oos):
"""
Path for static predictions
Parameters
----------
start : int
Index of first observation
end : int
Index of last in-sample observation. Inclusive, so start:end+1
in slice notation.
num_oos : int
Number of out-of-sample observations, so that the returned size is
num_oos + (end - start + 1).
exog : ndarray
Array containing replacement exog values
exog_oos : ndarray
Containing forecast exog values
"""
hold_back = self._hold_back
nobs = self.endog.shape[0]
x = np.empty((0, self._x.shape[1]))
if start <= nobs:
is_loc = slice(start - hold_back, end + 1 - hold_back)
x = self._x[is_loc]
if exog is not None:
x = x.copy()
# Replace final columns
x[:, -exog.shape[1] :] = exog[start : end + 1]
in_sample = x @ params
if num_oos == 0: # No out of sample
return self._wrap_prediction(in_sample, start, end + 1)
out_of_sample = self._static_oos_predict(params, num_oos, exog_oos)
prediction = np.hstack((in_sample, out_of_sample))
return self._wrap_prediction(prediction, start, end + 1 + num_oos)
```
- 後半のループで、[[自己回帰モデル|ARモデル]]の$y_{t}$ (`forecasts[i]`)を順次計算している。
- `new_x[i : i + 1] @ params`は一次の線形結合の計算。
- AR係数(params)の値は変化しない。
- static_oos_predictは全然通っていないかも?
- `in_sample = x @ params` だけ計算している。
**dynamic prediction**
```python
def _setup_oos_forecast(self, add_forecasts, exog_oos):
x = np.zeros((add_forecasts, self._x.shape[1]))
oos_exog = self._deterministics.out_of_sample(steps=add_forecasts)
n_deterministic = oos_exog.shape[1]
x[:, :n_deterministic] = to_numpy(oos_exog)
# skip the AR columns
loc = n_deterministic + len(self._lags)
if self.exog is not None:
x[:, loc:] = exog_oos[:add_forecasts]
return x
def _dynamic_predict(
self, params, start, end, dynamic, num_oos, exog, exog_oos
):
"""
:param params:
:param start:
:param end:
:param dynamic:
:param num_oos:
:param exog:
:param exog_oos:
:return:
"""
reg = []
hold_back = self._hold_back
if (start - hold_back) <= self.nobs:
is_loc = slice(start - hold_back, end + 1 - hold_back)
x = self._x[is_loc]
if exog is not None:
x = x.copy()
# Replace final columns
x[:, -exog.shape[1] :] = exog[start : end + 1]
reg.append(x)
if num_oos > 0:
reg.append(self._setup_oos_forecast(num_oos, exog_oos))
reg = np.vstack(reg)
det_col_idx = self._x.shape[1] - len(self._lags)
det_col_idx -= 0 if self.exog is None else self.exog.shape[1]
# + 1 is due t0 inclusiveness of predict functions
adj_dynamic = dynamic - start + 1
forecasts = np.empty(reg.shape[0])
forecasts[:adj_dynamic] = reg[:adj_dynamic] @ params
for h in range(adj_dynamic, reg.shape[0]):
# Fill in regressor matrix
for j, lag in enumerate(self._lags):
fcast_loc = h - lag
if fcast_loc >= 0:
val = forecasts[fcast_loc]
else:
# If before the start of the forecasts, use actual values
val = self.endog[start + fcast_loc]
reg[h, det_col_idx + j] = val
forecasts[h] = reg[h : h + 1] @ params
return self._wrap_prediction(forecasts, start, end + 1 + num_oos)
```
- regはxのコピー
- for ループ内でregは更新されているjj
- xはactual valuesと同じ
- adj_dynamic => 1
- det_col_idx -> 0
- 最初の`forecats[:adj_dybamic]` は実測値にAR係数をかけただけ。
- `forecasts = np.empty(reg.shape[0])` は初期化されていないのでxの値が入っている