skforecast源码解析:核心Forecaster类设计与实现原理
skforecast是一个基于scikit-learn API构建的时间序列预测库,其核心设计理念是将传统机器学习模型转化为强大的时间序列预测工具。本文将深入解析skforecast中Forecaster类的架构设计与实现原理,帮助开发者理解其内部工作机制。## 一、Forecaster类层次结构skforecast采用抽象基类(ABC)设计模式,构建了清晰的类层次结构。所有预测器都继承自
skforecast源码解析:核心Forecaster类设计与实现原理
skforecast是一个基于scikit-learn API构建的时间序列预测库,其核心设计理念是将传统机器学习模型转化为强大的时间序列预测工具。本文将深入解析skforecast中Forecaster类的架构设计与实现原理,帮助开发者理解其内部工作机制。
一、Forecaster类层次结构
skforecast采用抽象基类(ABC)设计模式,构建了清晰的类层次结构。所有预测器都继承自ForecasterBase抽象类,该类定义了时间序列预测所需的核心接口。
从源码中可以看到,ForecasterBase位于skforecast/base/_forecaster_base.py,它定义了5个必须实现的抽象方法:
create_train_X_y: 构建训练矩阵fit: 模型训练接口predict: 预测接口set_params: 参数设置接口set_lags: 滞后特征设置接口
基于这个抽象基类,skforecast实现了多种预测策略,包括:
ForecasterRecursive: 递归式多步预测ForecasterDirect: 直接多步预测ForecasterRnn: 基于RNN的深度学习预测ForecasterStats: 统计模型预测(如ARIMA、ETS)
二、核心ForecasterBase类解析
ForecasterBase作为所有预测器的基类,提供了基础功能和统一接口。其核心代码位于skforecast/base/_forecaster_base.py。
1. 关键属性设计
该类定义了时间序列预测所需的核心属性,包括:
lags: 用于预测的滞后特征window_size: 构建特征所需的窗口大小transformer_y: 目标变量转换transformer_exog: exogenous变量转换differentiation: 时间序列差分阶数
这些属性通过初始化方法设置,并在整个预测过程中保持一致。
2. 抽象方法定义
ForecasterBase定义了预测器必须实现的核心方法:
@abstractmethod
def create_train_X_y(
self,
y: pd.Series,
exog: pd.Series | pd.DataFrame | None = None
) -> tuple[pd.DataFrame, pd.Series]:
pass
@abstractmethod
def fit(
self,
y: pd.Series,
exog: pd.Series | pd.DataFrame | None = None
) -> None:
pass
@abstractmethod
def predict(
self,
steps: int,
last_window: pd.Series | pd.DataFrame | None = None,
exog: pd.Series | pd.DataFrame | None = None
) -> pd.Series:
pass
这些抽象方法确保了所有预测器具有统一的接口,使得用户可以无缝切换不同的预测策略。
三、ForecasterRecursive实现原理
ForecasterRecursive是skforecast中最常用的预测器之一,采用递归策略进行多步预测。其源码位于skforecast/recursive/_forecaster_recursive.py。
1. 初始化与参数设置
ForecasterRecursive的初始化方法接受多个关键参数:
def __init__(
self,
estimator: object = None,
lags: int | list[int] | np.ndarray[int] | range[int] | None = None,
window_features: object | list[object] | None = None,
transformer_y: object | None = None,
transformer_exog: object | None = None,
weight_func: Callable | None = None,
differentiation: int | None = None,
fit_kwargs: dict[str, object] | None = None,
binner_kwargs: dict[str, object] | None = None,
forecaster_id: str | int | None = None,
regressor: object = None
) -> None:
其中最核心的参数是estimator(scikit-learn兼容的模型)和lags(滞后特征设置)。
2. 递归预测机制
递归预测的核心思想是使用当前预测结果作为下一时间步的输入特征。其工作流程如下:
实现这一机制的关键代码在predict方法中,大致流程为:
- 初始化预测窗口(last_window)
- 对每个预测步骤:
- 使用当前窗口创建特征
- 预测下一时间步的值
- 更新窗口,将新预测值加入
3. 特征工程实现
ForecasterRecursive通过_create_lags方法构建滞后特征矩阵:
def _create_lags(
self,
y: np.ndarray,
X_as_pandas: bool = False,
train_index: pd.Index | None = None
) -> tuple[np.ndarray | pd.DataFrame | None, np.ndarray]:
X_data = None
if self.lags is not None:
y_strided = np.lib.stride_tricks.sliding_window_view(y, self.window_size)[:-1]
X_data = y_strided[:, self.window_size - self.lags]
# ... 格式转换代码
y_data = y[self.window_size:]
return X_data, y_data
这段代码使用滑动窗口技术高效构建滞后特征矩阵,是时间序列预测的核心步骤。
四、数据处理与转换
skforecast提供了丰富的数据处理功能,确保时间序列数据符合模型要求。
1. 时间序列差分
为处理非平稳时间序列,ForecasterRecursive支持差分操作:
if self.differentiation is not None:
self.differentiator = TimeSeriesDifferentiator(
order=differentiation, window_size=self.window_size
)
差分操作在fit方法中应用,并在预测时自动逆转,确保结果在原始尺度上。
2. 特征转换
支持对目标变量和外部变量进行转换:
y = transform_dataframe(
df = y,
transformer = self.transformer_y,
fit = fit_transformer,
inverse_transform = False,
)
转换操作在训练和预测阶段保持一致,确保数据处理流程的连贯性。
五、模型训练与预测流程
1. 训练流程
ForecasterRecursive的训练流程主要在fit方法中实现,核心步骤包括:
- 数据验证与预处理
- 特征工程(滞后特征、窗口特征)
- 模型训练
- 存储训练信息(如最后窗口、残差等)
2. 预测流程
预测流程在predict方法中实现,核心步骤包括:
- 输入验证
- 特征构建
- 递归预测
- 结果转换(逆转差分、逆变换)
六、概率预测实现
skforecast支持多种概率预测方法,包括:
- 基于残差的bootstrap方法
- 分位数回归
- conformal预测
这些功能通过predict_interval、predict_quantiles等方法实现,为风险评估提供了强大工具。
七、实际应用与扩展
1. 多变量预测
通过ForecasterDirectMultiVariate类支持多变量预测,允许同时预测多个相关时间序列。
2. 模型选择与调优
skforecast提供了专门的模型选择工具,如GridSearchForecaster和BayesianSearchForecaster,位于skforecast/model_selection/_search.py,支持滞后特征和模型参数的联合优化。
3. 集成与堆叠
通过组合多个Forecaster实例,可以构建更强大的集成预测模型,提高预测稳健性。
八、总结
skforecast的Forecaster类设计体现了良好的软件工程实践,通过抽象基类统一接口,使用组合模式实现功能扩展,同时保持与scikit-learn生态的兼容性。其核心优势包括:
- 灵活性:支持多种预测策略和模型
- 可扩展性:易于添加新的预测算法和特征工程方法
- 易用性:统一的API设计降低使用门槛
- 健壮性:完善的数据验证和错误处理
通过深入理解Forecaster类的设计与实现,开发者可以更好地利用skforecast进行时间序列预测,甚至扩展其功能以满足特定需求。核心源码位于skforecast/recursive/_forecaster_recursive.py和skforecast/base/_forecaster_base.py,建议感兴趣的开发者进一步阅读这些文件以获取更深入的理解。
更多推荐







所有评论(0)