You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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`.

尝试修改后的报错情况

  1. 将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`.
  1. 改为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 09:27:03