sktime SquaringResiduals样本内外预测异常问题咨询
关于sktime中SquaringResiduals无法同时实现样本内和样本外预测的问题
问题场景
使用sktime的SquaringResiduals混合模型时,样本内预测可正常运行,但开启样本外预测代码后出现报错,无法同时完成两类预测。
样本内正常运行代码
from sktime.forecasting.arch import StatsForecastGARCH from sktime.forecasting.squaring_residuals import SquaringResiduals def hybridModel(p,q,model): out_sample_date = FH(np.arange(12), is_relative=True) in_sample_date = FH(df.index, is_relative=False) var_fc = StatsForecastGARCH(p=p,q=q) sqr = SquaringResiduals(forecaster=model, residual_forecaster=var_fc,initial_window=int(len(df))) sqr = sqr.fit(df, fh=in_sample_date) # y_pred2 = sqr.predict(out_sample_date) #out sample prediction y_pred = sqr.predict(in_sample_date) #in sample prediction fig,ax=plot_series(df, y_pred, labels=["passenger", "y_pred"]) return sqr,fig,y_pred,error_matrix(df,y_pred) sqr,fig1,y_pred1,matrix1= hybridModel(1,1,forecaster)
样本外预测报错
开启y_pred2 = sqr.predict(out_sample_date)后,抛出以下错误:
ValueError: A different forecasting horizon `fh` has been provided from the one seen already in `fit`, in this instance of SquaringResiduals. If you want to change the forecasting horizon, please re-fit the forecaster. This is because the fitting of the forecaster SquaringResiduals depends on `fh`.
尝试修改后的报错情况
- 将
sqr.fit(df, fh=in_sample_date)改为sqr.fit(df),报错:
ValueError: The forecasting horizon `fh` must be passed to `fit` of SquaringResiduals, but none was found. This is because fitting of the forecaster SquaringResiduals depends on `fh`.
- 改为
sqr.fit(df, fh=out_sample_date),报错:
ValueError: The `window_length` and the forecasting horizon are incompatible with the length of `y`. Found `window_length`=84, `max(fh)`=11, but len(y)=84. It is required that the window length plus maximum forecast horizon is smaller than the length of the time series `y` itself.
对比模型(TBATS)
非混合模型如TBATS可正常同时完成样本内和样本外预测:
from sktime.forecasting.tbats import TBATS from sktime.forecasting.base import ForecastingHorizon as FH import warnings import numpy as np import pandas as pd import mlflow from sktime.utils import mlflow_sktime as mf from sktime.utils.plotting import plot_series warnings.filterwarnings("ignore") out_sample_date = FH(np.arange(12), is_relative=True) in_sample_date = FH(df.index, is_relative=False) forecaster = TBATS( use_box_cox=True, use_trend=True, use_damped_trend=True, sp=12, use_arma_errors=True, n_jobs=1) forecaster.fit(df) y_pred = forecaster.predict(in_sample_date) y_pred2 = forecaster.predict(out_sample_date) fig,ax = plot_series(df,y_pred,y_pred2,labels=['passenger','prediction','out_sample_pred'])
原因分析
SquaringResiduals是残差驱动的混合预测器,其拟合逻辑和TBATS这类单模型本质不同:
- TBATS等单模型基于整个时间序列的全局模式(趋势、季节性等)建模,拟合完成后可任意指定预测范围,无需在拟合阶段确定
fh。 SquaringResiduals的拟合过程完全依赖输入的fh:它需要先使用基础预测器(你传入的model)对fh指定的时间点生成预测,再计算这些预测的残差,最后用残差预测器(这里是GARCH)对残差的波动建模。整个流程必须在拟合阶段明确要预测的时间范围,因此无法在拟合后更改fh。
另外,你设置的initial_window=int(len(df))是错误的:这个参数指定基础预测器用来生成预测的初始窗口长度,必须满足initial_window + max(fh) < len(y),否则没有足够的序列长度生成fh对应的残差,这也是第二次修改后报错的原因。
解决方案
方案1:一次拟合同时生成样本内和样本外预测
拟合时传入包含样本内所有时间点+样本外相对horizon的组合fh,同时调整initial_window满足长度要求:
from sktime.forecasting.arch import StatsForecastGARCH from sktime.forecasting.squaring_residuals import SquaringResiduals from sktime.forecasting.base import ForecastingHorizon as FH import pandas as pd def hybridModel(p,q,model): # 定义样本外相对horizon(1到12,对应未来12步) out_sample_fh = FH(np.arange(1,13), is_relative=True) # 定义样本内绝对horizon in_sample_fh = FH(df.index, is_relative=False) # 组合两类horizon combined_fh = FH.concat([in_sample_fh, out_sample_fh]) var_fc = StatsForecastGARCH(p=p,q=q) # 计算符合要求的initial_window:留出足够空间生成残差 max_fh = max(combined_fh.to_relative(df.index[-1])) initial_window = len(df) - max_fh sqr = SquaringResiduals(forecaster=model, residual_forecaster=var_fc, initial_window=initial_window) sqr.fit(df, fh=combined_fh) # 获取样本内预测 y_pred_in = sqr.predict(in_sample_fh) # 获取样本外预测 y_pred_out = sqr.predict(out_sample_fh) fig, ax = plot_series(df, y_pred_in, y_pred_out, labels=["passenger", "样本内预测", "样本外预测"]) return sqr, fig, y_pred_in, y_pred_out, error_matrix(df, y_pred_in) sqr, fig1, y_pred1, y_pred2, matrix1 = hybridModel(1,1,forecaster)
方案2:分别拟合模型获取两类预测
如果不需要同时生成两类预测,可分别初始化两个SquaringResiduals实例,分别针对样本内和样本外的fh进行拟合:
from sktime.forecasting.arch import StatsForecastGARCH from sktime.forecasting.squaring_residuals import SquaringResiduals from sktime.forecasting.base import ForecastingHorizon as FH def hybrid_in_out(p,q,model): # 样本内预测模型 in_sample_fh = FH(df.index, is_relative=False) var_fc_in = StatsForecastGARCH(p=p,q=q) # 用80%序列长度作为初始窗口,确保满足initial_window + max(fh) < len(df) initial_window_in = int(len(df)*0.8) sqr_in = SquaringResiduals(forecaster=model, residual_forecaster=var_fc_in, initial_window=initial_window_in) sqr_in.fit(df, fh=in_sample_fh) y_pred_in = sqr_in.predict(in_sample_fh) # 样本外预测模型 out_sample_fh = FH(np.arange(1,13), is_relative=True) var_fc_out = StatsForecastGARCH(p=p,q=q) initial_window_out = len(df) - max(out_sample_fh) sqr_out = SquaringResiduals(forecaster=model, residual_forecaster=var_fc_out, initial_window=initial_window_out) sqr_out.fit(df, fh=out_sample_fh) y_pred_out = sqr_out.predict(out_sample_fh) fig, ax = plot_series(df, y_pred_in, y_pred_out, labels=["passenger", "样本内预测", "样本外预测"]) return sqr_in, sqr_out, fig, y_pred_in, y_pred_out, error_matrix(df, y_pred_in) sqr_in, sqr_out, fig1, y_pred1, y_pred2, matrix1 = hybrid_in_out(1,1,forecaster)
内容的提问来源于stack exchange,提问作者jugesh
相关产品推荐
相关产品推荐

