KDnuggets

Building Time-Series Machine Learning Models with sktime in Python

8.5内容质量

TL;DR · AI 摘要

sktime 是一个专为时间序列建模设计的 Python 库,提供与 scikit-learn 兼容的 API,支持时间序列的预测、分类、回归和聚类。

核心要点

  • sktime 支持多种时间序列数据结构,包括 Series、Panel 和 Hierarchical。
  • 使用 sktime 可以构建与 scikit-learn 兼容的预处理管道和预测模型。
  • sktime 支持 DatetimeIndex、PeriodIndex 等时间索引,要求索引单调递增。

结构提纲

按章节快速跳转。

  1. 介绍时间序列数据的特殊性以及 sktime 的作用。

  2. 列出使用 sktime 所需的 Python 版本和依赖库。

  3. 解释 sktime 如何处理时间序列数据及其主要数据结构。

  4. 描述如何创建一个用于时间序列建模的示例数据集。

思维导图

用一张图看清主题之间的关系。

查看大纲文本(无障碍 / 无 JS 友好)
  • sktime for Time Series Modeling
    • Key Features
      • Scikit-learn-style API
      • Supports Series, Panel, and Hierarchical Data
      • Time Index Support (DatetimeIndex, PeriodIndex, etc.)
    • Use Cases
      • Forecasting
      • Classification
      • Regression
      • Clustering

金句 / Highlights

值得收藏与分享的关键句。

  • sktime is a Python library built specifically for time series data, offering a scikit-learn-style API.

    Introduction

    ⬇︎ 下载 PNG𝕏 分享到 X
  • Time series data breaks the assumption of scikit-learn that each row is an independent sample.

    What Makes sktime Useful

    ⬇︎ 下载 PNG𝕏 分享到 X
  • sktime supports several time indexes, including DatetimeIndex and PeriodIndex, with the requirement that the index be monotonic.

    What Makes sktime Useful

    ⬇︎ 下载 PNG𝕏 分享到 X
#Python#时间序列#sktime#机器学习
打开原文

使用 Python 中的 sktime 构建时间序列机器学习模型 - KDnuggets

publ: 2026年6月15日

  • 博客热门文章
  • 话题 人工智能 职业建议 计算机视觉 数据工程 数据科学 语言模型 机器学习 MLOps NLP 编程 Python SQL
  • 数据集
  • 活动
  • 资源 快速参考指南 推荐 技术简报
  • 广告

加入新闻通讯

#header end

/ad_wrapper

使用 Python 中的 sktime 构建时间序列机器学习模型

在本文中,我们将使用 sktime 在 Python 中构建时间序列机器学习模型,并探索其用于预测工作流程的核心数据结构。

作者:

Bala Priya C

,KDnuggets 贡献编辑及技术内容专家,2026年6月15日发布于

机器学习

<div class="addthis_native_toolbox"></div>

# 引言

如果你处理传感器读数、服务器指标或任何随时间到达的数据,你已经知道标准的 scikit-learn 管道并不完全适用。时间序列数据具有表格模型忽略的结构:季节性、趋势、时间顺序,以及未来值依赖于过去值的事实。

sktime 是一个专门为这种情况构建的 Python 库。它提供了一个类似 scikit-learn 的 API —— fit、predict、transform,但它是专门为时间序列从头设计的。你可以对时间序列进行预测、分类、回归和聚类,所有操作都使用一致的接口。

在本文中,你将通过一个示例问题进行学习:从工业 HVAC 传感器预测温度读数。你将学习 sktime 如何处理时间序列数据,如何构建预处理管道,如何拟合预测器,以及如何评估它们。

你可以在 GitHub 上获取代码。

# 先决条件

你需要 Python 3.10 或更高版本,并且对 pandas 有基本的了解。使用以下命令安装所有需要的内容:

code
pip install sktime pmdarima statsmodels

如果你更倾向于一次性安装所有可选依赖项,pip install sktime[all_extras] 可以满足你的需求。

# 为什么 sktime 有用

了解 sktime 解决的问题是有帮助的。在 scikit-learn 中,你的数据是一个二维表格 —— 行是样本,列是特征。时间序列数据打破了这一假设,因为每个“行”实际上是一个随时间变化的值序列,这些值的顺序很重要。

你将使用的主数据容器包括:

数据类型

表示

描述

Series

code
pd.Series

code
pd.DataFrame

在普通预测中使用的单个时间序列。

Panel

具有一个 2 级

code
MultiIndex

多个独立时间序列的集合。

Hierarchical

具有 3 级或以上

具有跨多个维度聚合级别的结构化时间序列集合。

对于时间索引本身,sktime 支持几种时间索引:DatetimeIndex、PeriodIndex、Int64Index 和 RangeIndex 在你的 pandas 对象上。索引必须是单调的。如果你使用 DatetimeIndex,freq 属性应该被设置。

code
import numpy as np
import pandas as pd

np.random.seed(42)

# 从2026年1月1日开始的90天的每小时读数
n_hours = 90 * 24
timestamps = pd.date_range(start="2026-01-01", periods=n_hours, freq="h")

# 趋势:90天内温度逐渐上升5度
trend = np.linspace(0, 5, n_hours)

# 每日周期性变化:温度在下午2点达到峰值,在凌晨4点达到低谷
hour_of_day = np.arange(n_hours) % 24
daily_cycle = 4 * np.sin(2 * np.pi * (hour_of_day - 4) / 24)

# 噪声
noise = np.random.normal(0, 0.8, n_hours)

# 基础温度约为20°C
temperature = 20 + trend + daily_cycle + noise

# 引入一些缺失值(传感器故障)
dropout_indices = [300, 301, 302, 1440, 1441]
temperature[dropout_indices] = np.nan

y = pd.Series(temperature, index=timestamps, name="temp_celsius")
y.index.freq = pd.tseries.frequencies.to_offset("h")

print(y.head())
print(f"\nShape: {y.shape}")
print(f"Missing values: {y.isna().sum()}")
print(f"Index type: {type(y.index)}")

输出:

code
2026-01-01 00:00:00    16.933270
2026-01-01 01:00:00    17.063277
2026-01-01 02:00:00    18.522783
2026-01-01 03:00:00    20.190095
2026-01-01 04:00:00    19.821941
Freq: h, Name: temp_celsius, dtype: float64

Shape: (2160,)
Missing values: 5
Index type:

# 为训练和测试划分时间序列数据

划分时间序列数据与划分表格数据不同 —— 你不能对行进行洗牌。你必须始终按时间顺序划分:使用较早的数据进行训练,使用较晚的数据进行测试。

sktime 提供了 temporal_train_test_split 用于此目的:

code
from sktime.split import temporal_train_test_split

# 将最后7天(168小时)作为测试集
y_train, y_test = temporal_train_test_split(y, test_size=168)

print(f"Train: {y_train.index[0]} → {y_train.index[-1]}")
print(f"Test:  {y_test.index[0]} → {y_test.index[-1]}")
print(f"Train size: {len(y_train)}, Test size: {len(y_test)}")
code
Train: 2026-01-01 00:00:00 → 2026-03-24 23:00:00
Test:  2026-03-25 00:00:00 → 2026-03-31 23:00:00
Train size: 1992, Test size: 168

该函数确保划分是清晰且按时间顺序的 —— 没有未来数据泄露到训练集中。

# 定义预测范围

在拟合任何模型之前,你需要告诉 sktime 你想要预测哪些时间点。这就是 ForecastingHorizon

code
from sktime.forecasting.base import ForecastingHorizon

# 预测168个时间点(7天的每小时数据)
# is_relative=False 表示我们使用的是绝对时间戳
fh = ForecastingHorizon(y_test.index, is_relative=False)

print(f"Horizon length: {len(fh)}")
print(f"First forecast point: {fh[0]}")
print(f"Last forecast point:  {fh[-1]}")

这将输出:

code
Horizon length: 168
First forecast point: 2026-03-25 00:00:00
Last forecast point:  2026-03-31 23:00:00

你也可以使用相对时间范围,如 fh = [1, 2, 3, ..., 168],这表示“1步之后,2步之后,...”。当你有实际的时间点需要预测时,使用绝对时间范围会更清晰。

# 构建预处理和预测管道

实际的传感器数据包含缺失值、季节性模式和趋势 —— 你需要在预测之前或期间处理所有这些内容。sktime 的 TransformedTargetForecaster 允许你将转换与预测模型连接成一个单一的估计器。这些转换会在拟合前应用于目标序列 y,并在预测时自动反转。

code
from sktime.forecasting.exp_smoothing import ExponentialSmoothing
from sktime.forecasting.compose import TransformedTargetForecaster
from sktime.transformations.series.impute import Imputer
from sktime.transformations.series.detrend import Deseasonalizer, Detrender

pipeline = TransformedTargetForecaster(
    steps=[
        # Step 1: 使用线性插值填充缺失的传感器读数
        ("imputer", Imputer(method="linear")),
        # Step 2: 去除线性趋势,使预测器看到一个平稳序列
        ("detrender", Detrender()),
        # Step 3: 去除每日季节性(对于每小时数据,周期为24小时,sp=24)
        ("deseasonalizer", Deseasonalizer(model="additive", sp=24)),
        # Step 4: 预测清理后的平稳残差
        ("forecaster", ExponentialSmoothing(trend=None, seasonal=None)),
    ]
)

pipeline.fit(y_train, fh=fh)
y_pred = pipeline.predict()

print(y_pred.head())
code
2026-03-25 00:00:00    21.210066
2026-03-25 01:00:00    21.788986
2026-03-25 02:00:00    22.615184
2026-03-25 03:00:00    23.688449
2026-03-25 04:00:00    24.621127
Freq: h, Name: temp_celsius, dtype: float64

每个步骤的作用如下:

  • Imputer(method="linear") 通过线性插值填充缺失值,这在传感器数据中效果很好。
  • Detrender() 为训练序列拟合一个线性趋势并减去它;在预测时会将趋势加回去。
  • Deseasonalizer(sp=24) 从残差中去除24小时周期;sp表示季节周期。
  • 最后,ExponentialSmoothing 对去趋势和去季节化的残差进行预测。
  • 当调用 predict() 时,所有逆变换会自动按相反顺序应用,你将得到原始温度尺度的预测结果。

# 评估预测

sktime 与标准评估指标集成。对于预测,平均绝对误差(MAE)和平均绝对百分比误差(MAPE)是常见的选择。

code
from sktime.performance_metrics.forecasting import (
    mean_absolute_error,
    mean_absolute_percentage_error,
)

mae = mean_absolute_error(y_test, y_pred)
mape = mean_absolute_percentage_error(y_test, y_pred)

print(f"MAE:  {mae:.3f} °C")
print(f"MAPE: {mape*100:.2f}%")
code
MAE:  0.584 °C
MAPE: 2.40%

# 替换不同的预测器

sktime 接口最大的优势之一是替换底层算法只需更改一行代码。让我们尝试用 ARIMA 模型替换指数平滑模型并进行比较。

code
from sktime.forecasting.arima import ARIMA

pipeline_arima = TransformedTargetForecaster(
    steps=[
        ("imputer", Imputer(method="linear")),
        ("detrender", Detrender()),
        ("deseasonalizer", Deseasonalizer(model="additive", sp=24)),
        # 在清理后的残差上使用 ARIMA(1,1,1)
        ("forecaster", ARIMA(order=(1, 1, 1), suppress_warnings=True)),
    ]
)

pipeline_arima.fit(y_train, fh=fh)
y_pred_arima = pipeline_arima.predict()

mae_arima = mean_absolute_error(y_test, y_pred_arima)
mape_arima = mean_absolute_percentage_error(y_test, y_pred_arima)

print(f"ARIMA MAE:  {mae_arima:.3f} °C")
print(f"ARIMA MAPE: {mape_arima*100:.2f}%")
code
ARIMA MAE:  0.586 °C
ARIMA MAPE: 2.41%

关键在于预处理步骤 —— 缺失值填补、去趋势、去季节性 —— 保持一致。你只改变了最终的预测器,而其他所有内容都围绕它整洁地组合在一起。

# 时间序列交叉验证

仅保留一个测试窗口可能会产生误导。sktime 通过尊重时间顺序的拆分器提供了时间序列交叉验证。

SlidingWindowSplitter 使用滑动窗口:训练窗口在时间上向前滑动,始终保持相同的长度。ExpandingWindowSplitter 在你向前移动时逐步扩大训练集,这在你想要使用所有可用历史数据时更为合适。

code
from sktime.split import ExpandingWindowSplitter
from sktime.forecasting.model_evaluation import evaluate

# Expanding window: start with 1800-hour train set, evaluate on 168-hour windows
cv = ExpandingWindowSplitter(
    initial_window=1800,
    fh=list(range(1, 169)),
    step_length=168,
)

results = evaluate(
    forecaster=pipeline,
    y=y,
    cv=cv,
    scoring=mean_absolute_error,
    return_data=False,
)

print(results[["test__DynamicForecastingErrorMetric", "fit_time"]].round(3))
print(f"\nMean CV MAE: {results['test__DynamicForecastingErrorMetric'].mean():.3f} °C")
code
test__DynamicForecastingErrorMetric  fit_time
0                                0.627     0.274
1                                0.585     0.100

Mean CV MAE: 0.606 °C

evaluate 返回一个包含每折指标和时间的 DataFrame。交叉验证的 MAE 证实了模型在数据的不同时间窗口上具有一致的泛化能力。

# 下一步

本文介绍了 sktime 中的核心预测工作流程,但该库的功能远不止于基本的预测任务。

它还支持时间序列分类、带有不确定性估计的概率预测、在多个相关时间序列之间训练共享模型、将传统机器学习算法适应于序列预测,以及自动化模型选择和调优工作流程。

sktime 最大的优势之一是其一致的 API 和与更广泛的 Python 机器学习生态系统集成,这使得初学者和有经验的实践者都能更容易地进行实验。sktime 的文档和示例笔记本尤其写得非常好,如果你经常处理预测或时间序列数据问题,值得将其收藏。

Bala Priya C 是来自印度的开发者和技术作家。她喜欢在数学、编程、数据科学和内容创作的交汇点上工作。她的兴趣和专长领域包括 DevOps、数据科学和自然语言处理。她喜欢阅读、写作、编程和咖啡!目前,她正在通过撰写教程、操作指南、观点文章等,学习并分享她的知识给开发者社区。Bala 还创建了引人入胜的资源概述和编码教程。

更多相关内容

  • 使用 Rust 构建高性能机器学习模型
  • 构建真正有用的机器学习模型的技巧
  • 构建预测模型:Python 中的逻辑回归
  • 构建数据管道以使用大型语言模型创建应用程序
  • 构建机器学习作品集的终极指南:助你获得工作机会
  • 使用 Django 构建机器学习应用程序

<hr class="grey-line"><br> <div><h3>我们推荐的前 5 门免费课程</h3><br> </div>

Mailchimp for WordPress v4.13.0 - https://wordpress.org/plugins/mailchimp-for-wp/

/ Mailchimp for WordPress 插件

您可以从这里开始编辑。

如果评论已关闭。

<= 上一篇

下一篇 =>

#content end

<script type="text/javascript">kda_sid_write(kda_sid_n);</script>

最新文章

  • 2026 年成为 LLM 工程师的路线图:停止在 Pandas 中编写循环:尝试 7 种更快的替代方法 使用 Python 3 中的 sktime 构建时间序列机器学习模型 Pandas 数据清洗与准备技巧 将 Claude Code 与本地模型结合使用 3 个 NumPy 技巧提升数值性能

热门文章

  • 将 Claude Code 与本地模型结合使用
  • 低成本本地智能代理编程:Claude Code + Ollama + Gemma4
  • Anthropic 的 Claude 技能构建完整指南
  • 5 个有用的 Python 脚本自动处理无聊的 PDF 任务
  • 为您的创业点子获取资金的 7 种最佳方式
  • 用于 Python Web 开发的 10 个 GitHub 仓库
  • AI 工程师必须知道的 5 个 Python 概念
  • 使用 Python 中的 sktime 构建时间序列机器学习模型
  • 3 个 Pandas 数据清洗与准备技巧
  • 5 篇有趣论文清晰解释 LLMs

#content_wrapper end

© 2026

Guiding Tech Media

|

关于

联系方式

广告

隐私政策

服务条款

发布于 2026 年 6 月 15 日,作者:bala-priya

blank

不,谢谢!

/.main_wrapper

<script defer type="text/javascript" src="https://s7.addthis.com/js/300/addthis_widget.js#pubid=gpsaddthis"></script>

noptimize

/noptimize