前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >股市预测,销量预测,病毒传播...一个时间序列建模套路搞定全部!⛵

股市预测,销量预测,病毒传播...一个时间序列建模套路搞定全部!⛵

原创
作者头像
ShowMeAI
发布2022-08-09 17:45:00
7040
发布2022-08-09 17:45:00
举报
文章被收录于专栏:ShowMeAI研究中心

💡 作者:韩信子@ShowMeAI 📘 深度学习实战系列:https://www.showmeai.tech/tutorials/42 📘 NLP 实战系列:https://www.showmeai.tech/tutorials/45 📘 本文地址:https://www.showmeai.tech/article-detail/288 📢 声明:版权所有,转载请联系平台与作者并注明出处 📢 收藏ShowMeAI查看更多精彩内容

我们在日常业务中遇到的很多问题,都可以归属到时间序列范畴内——股市涨跌变化、电商销量预测、传染病传播挖掘等,其实都可以用『时间序列』解决。

时间序列建模工具库有很多,比较知名的有 Uber 开源的 📘Orbit工具库、LinkedIn 开源的 📘Greykite 工具库,提供了部分解决方法。

最近 Salesforce 团队研发的 📘Merlion 工具库声名鹊起。Merlion 作为后起之秀,覆盖非常全面,提供了很多时间序列的算法解决方案。本篇 ShowMeAI 就给大家介绍一下如何使用 Merlion 解决『时间序列』问题。

Merlion 是一个用于时间序列的智能Python 库,提供了一个端到端的机器学习框架,包括加载和转换数据,建立和训练模型,模型结果后处理,以及评估模型性能Merlion 支持各种时间序列学习任务,包括单变量和多变量时间序列的预测、异常检测和变化点检测。这个库的目的是为工程师和研究人员提供一站式解决方案,快速开发特定的时间序列需求模型,并在多个时间序列数据集上进行基准测试。

💡 环境配置

Merlion最基本的安装只需要 运行命令 pip install salesforce-merlion。但这个基础版本并不包含所有模型,如果要安装全部模型,如 LightGBM 或 Facebook 的 Prophet,我们切换成命令 pip install "salesforce-merlion[all]" 就可以。

💡 工具库架构

在深入学习使用 Merlion 解决时间序列问题之前,让我们先看看它的架构。下图按时间顺序显示了它的不同模型以及它们如何协同工作。

在本文中,ShowMeAI 将聚焦于时间序列,介绍除 后处理/post processing 模块之外的所有部分(因为这个部分仅用于异常检测,并不一定与时间序列问题相关)。

💡 数据加载

Merlion 的数据结构是 TimeSeries,支持多变量单变量时间序列。其底层是对一系列 UnivariateTimeSeries 进行的封装。

为了将数据放入所需的数据结构中,我们使用 TimeSeries 的函数 .from_pd()。这个函数接受带有 DatetimeIndex 的 DataFrame 作为输入,并且默认检查每个索引是否唯一以及是否设置了频率 freq(默认1h)。

以下为从 pandas DataFrame 加载单变量时间序列的示例代码。

代码语言:python
代码运行次数:0
复制
# 没有缺失值情况的简单案例
from merlion.utils import TimeSeries
import pandas as pd
import numpy as np


# 注意,这里需要手动设置freq参数,否则数据会混乱
ts_series = pd.Series(data = [20, 21, 25, 18],
                      index = pd.date_range('2020-04-01', '2020-04-04', freq='D'),
                      name = 'v'
                     )
ts_df = pd.DataFrame(ts_series)

# 构建TimeSeries对象
ts = TimeSeries.from_pd(ts_df)

如果输入的『单变量时间序列』包含缺失值或 nan 值,Merlion 会删除它们及其对应的索引。

在输入『多元时间序列』面临多序列不对齐的情况时,Merlion 工具库可以检查多元时间序列『是否包含任何缺失值』或『每个变量的索引是否未对齐』(调用 TimeSeries.is_aligned 属性)。如果没有对齐(.is_aligned 属性为 False),可以调用 .align() 函数对其进行修复对齐。

代码语言:python
代码运行次数:0
复制
# 无缺失的简单情况
from merlion.utils import TimeSeries
import pandas as pd
import numpy as np

# 多元时间序列
ts_series_1 = pd.Series(data = [20, 21, 25, 18],
                      index = pd.date_range('2020-04-01', '2020-04-04', freq='D')
                     )
ts_series_2 = pd.Series(data = [20, 21, np.nan, 18],
                      index = pd.date_range('2020-04-01', '2020-04-04', freq='D')
                     )
ts_df = pd.DataFrame({'v1': ts_series_1, 'v2': ts_series_2})


# 基于Dataframe构建TimeSeries对象
ts = TimeSeries.from_pd(ts_df)

# 输出是否对齐
print(ts.is_aligned)

# 对齐操作
ts_aligned = ts.align()
print(ts_aligned.is_aligned)

默认情况下,.align() 函数将合并任何单个单变量中存在的所有时间戳,并使用线性插值来估算缺失值。

切片和分割

除了 .align() 函数,Merlion 带有另外两个方便的函数:

  • .window(t0, tf) :在t0tf 范围之间切出一个子集,输入参数可以是任何合理的日期时间格式,也可以是 Unix 时间戳。
  • .bisect(t) :类似于 .window(),将时间序列分成左右部分。

预处理

Merlion 提供常见的数据 预处理转换技术 ,例如最小-最大归一化、幂变换 (box-cox) 或指数移动平均。完整预处理方法列表可以在📘这查看。

比如下列代码就是在建模步骤之前使用『最小 - 最大归一化』对数据预处理:

代码语言:python
代码运行次数:0
复制
from merlion.transform.normalize import MinMaxNormalize
# 初始化数据预处理器
transform = MinMaxNormalize()
# 拟合
transform.train(ts_aligned)
# 应用预处理器变换
ts_transformed = transform(ts_aligned)
# 逆变换
transform.invert(ts_transformed)

💡 模型库

Merlion 提供了一系列不同的模型,可以用于时间序列等问题:

  • ARIMA (自回归综合移动平均线)
  • SARIMA (具有用户指定季节性的 ARIMA)
  • ETS (误差、趋势、季节性)
  • Prophet (围绕 Facebook 的 Prophet 的包装)
  • Smoother (用于单变量时间序列预测的多尺度指数平滑器)
  • 向量自回归 用于多元时间序列预测的
  • Bagging (随机森林)和 提升树(lightgbm)
  • 长短期记忆网络

大家也可以 📘在这里 定义自己的模型。

下面的例子基于 📘航空乘客数据集,进行时间序列建模展示。

🏆 实战数据集下载(百度网盘):点击 这获取本文 [15] 使用 Merlion 库快速开发时间序列模型 『Monthly Airline Passenger Numbers 1949-1960 数据集』

ShowMeAI官方GitHubhttps://github.com/ShowMeAI-Hub

代码语言:python
代码运行次数:0
复制
import pandas as pd
from merlion.utils import TimeSeries
# 加载数据
air_pass = pd.read_csv("airline-passengers.csv")
# 把日期设置为索引
air_pass.set_index('Month', inplace=True)
air_pass.index = pd.to_datetime(air_pass.index)
# 一定要确保freq设定好
air_pass.index.freq = 'MS'


# 读取为TimeSeries对象
air_pass_ts = TimeSeries.from_pd(air_pass, freq='MS')
print(air_pass_ts.is_aligned)


# 使用 .bisect() 函数切分数据为训练集和测试集
# 我们希望预估未来6个月的乘客量
air_pass_ts_train, air_pass_ts_test = air_pass_ts.bisect('1960-07-01')

上述代码中:我们首先读取数据为 DataFrame 格式,再将其转换为 Merlion 的 TimeSeries 数据结构,之后检查数据集是否对齐(比如有没有缺失的索引),最后我们可以将数据拆分为训练集和测试集。

代码语言:python
代码运行次数:0
复制
from merlion.models.forecast.trees import LGBMForecaster, LGBMForecasterConfig
# 设定模型配置
lgbm_config = LGBMForecasterConfig(maxlags = 30,
                                   max_forecast_steps=len(air_pass_ts_test)
                                  )
# 初始化模型
lgbm = LGBMForecaster(lgbm_config)
# 拟合模型
lgbm.train(air_pass_ts_train)
# 预估
lgbm_fc = lgbm.forecast(air_pass_ts_test.time_stamps)

上述代码使用 LightGBM 模型,基于过去的数据对未来进行预测。如果我们想可视化预测结果,可以使用 Merlion 中的两种方法:

  • .plot_forecast()
  • .plot_forecast_plotly()

下面为绘图示例代码。

代码语言:python
代码运行次数:0
复制
import matplotlib.pyplot as plt
fig, ax = lgbm.plot_forecast(time_series=air_pass_ts_test)
plt.show()

我们得到如下的预估结果和真实结果对比图。

大家可能看出来了,这个预估结果并不是太好,我们可以做进一步的调整优化(例如使用不同的参数或变换)。我们这里只做可视化的演示,暂时不纠结预估效果。

💡 自动机器学习

对模型进行超参数调优也是一个很麻烦的事情,但 Merlion 附带了一个 AutoML 包,它支持:

  • SARIMA 的自动超参数选择
  • 自动季节性检测
  • Facebook Prophet 的自动(多)季节性检测
  • ETS 的自动季节性检测

以下示例使用与上述相同的数据集,并展示了如何将 AutoML 用于 SARIMA 模型。

代码语言:python
代码运行次数:0
复制
from merlion.models.automl.autosarima import AutoSarima, AutoSarimaConfig


sarima_config = AutoSarimaConfig(auto_pqPQ=True, auto_d=True, auto_D=True, auto_seasonality=True,
                           approximation=True, maxiter=5)
sarima = AutoSarima(sarima_config)


# 模型训练
train_pred, train_err = sarima.train(
    air_pass_ts_train, train_config={"enforce_stationarity": True,
                              "enforce_invertibility": True}
)
sarima_fc = sarima.forecast(air_pass_ts_test.time_stamps)

💡 模型选择与模型集成

Merlion 提供了两种常用的模型集成技术:

  • ① 对多个模型取平均值中位数的传统集成方法
  • ② 自动模型选择

我们先看看传统集成方法的应用:

代码语言:python
代码运行次数:0
复制
# 使用lgbm和autosarima两个方法
from merlion.models.forecast.trees import LGBMForecaster, LGBMForecasterConfig
from merlion.models.automl.autosarima import AutoSarima, AutoSarimaConfig


# 使用模型集成技术
from merlion.evaluate.forecast import ForecastMetric
from merlion.models.ensemble.combine import Mean, ModelSelector
from merlion.models.ensemble.forecast import ForecasterEnsemble, ForecasterEnsembleConfig


# 设定训练设置
from merlion.models.ensemble.base import EnsembleTrainConfig

# 定义模型
lgbm_config = LGBMForecasterConfig(maxlags = 30, max_forecast_steps=len(air_pass_ts_test))
lgbm = LGBMForecaster(lgbm_config)


sarima_config = AutoSarimaConfig(auto_pqPQ=True, auto_d=True, auto_D=True, auto_seasonality=True, approximation=True, maxiter=5)
sarima = AutoSarima(sarima_config)


# 传统集成,多模型求均值
ensemble_config = ForecasterEnsembleConfig(
    combiner=Mean(), models=[lgbm,sarima]
)


# 集成配置
# 我们使用20%的数据作为验证集
ensemble_train_config = EnsembleTrainConfig(valid_frac=0.2,
                                            per_model_train_configs=[None,{
                                                "enforce_stationarity": True,
                                                 "enforce_invertibility": True
                                            }])
# 训练与预测
ensemble = ForecasterEnsemble(config=ensemble_config)
ensemble.train(air_pass_ts_train,train_config=ensemble_train_config)
ensemble.forecast(air_pass_ts_test.time_stamps)

下面的代码是自动模型选择的方法示例代码:

代码语言:python
代码运行次数:0
复制
# 使用lgbm和autosarima两个方法
from merlion.models.forecast.trees import LGBMForecaster, LGBMForecasterConfig
from merlion.models.automl.autosarima import AutoSarima, AutoSarimaConfig


# 使用集成技术
from merlion.evaluate.forecast import ForecastMetric
from merlion.models.ensemble.combine import Mean, ModelSelector
from merlion.models.ensemble.forecast import ForecasterEnsemble, ForecasterEnsembleConfig


# 通过评估指标来选择模型
from merlion.evaluate.forecast import ForecastMetric


# 定义模型
lgbm_config = LGBMForecasterConfig(maxlags = 5, max_forecast_steps=len(air_pass_ts_test))
lgbm = LGBMForecaster(lgbm_config)

sarima_config = AutoSarimaConfig(auto_pqPQ=True, auto_d=True, auto_D=True, auto_seasonality=True, approximation=True, maxiter=5)
sarima = AutoSarima(sarima_config)

# 通过sMAPE指标选择最佳模型
selector_config = ForecasterEnsembleConfig(
    combiner=ModelSelector(metric=ForecastMetric.sMAPE))
selector = ForecasterEnsemble(
    config=selector_config, models=[lgbm, sarima])

selector.train(air_pass_ts_train)
selector.forecast(air_pass_ts_test.time_stamps)

除了 sMAPE Merlion 还支持许多其他错误指标,例如 MAE 或 RMSE,完整列表可以查看 📘这里。

💡 存储和加载模型

如果您想存储训练过的模型或加载,现有的 Merlion 的所有模型都带有 .save().load() 类方法。您还可以在适用于任意模型的 modelFactory 包的帮助下加载模型。这 .save() 方法在给定路径创建一个新目录,它存储模型的配置(json)以及它的状态(二进制)。

以下示例显示了我们如何从上面的集成示例中保存和加载模型。

代码语言:python
代码运行次数:0
复制
# 存储与加载模型
from merlion.models.factory import ModelFactory
import json
import pprint

# 我们只保存使用了的模型
selector.save("models",save_only_used_models=True)

# 我们输出模型配置看一下
pp = pprint.PrettyPrinter()
with open("models/config.json") as f:
    pp.pprint(json.load(f))

# 使用ForecasterEnsemble加载模型
selector_loaded = ForecasterEnsemble.load('models/')

# 或者使用ModelFactory加载模型
mdl_factory_selector = ModelFactory.load(name="ForecasterEnsemble", model_path='models/')

默认情况下 .save() 方法会将所有定义的模型存储在我们本地。在这个例子中,我们设置 save_only_used_models=True,所以我们只存储评估指标 sMAPE 上效果最好的模型。不过我们创建好的配置文件包含了所有集成模型的元信息。

💡 评估管道(pipeline)

最后要提到的是,Merlion 有一个非常酷的功能来模拟实时模型部署。这使我们能够根据(多个)评估指标来评估我们开发的预测器的质量。

这种模拟评估与滑动交叉验证(rolling cross validation)非常相似,在时间序列建模中是很常见的验证方法。

下述代码是我们在之前开发的 lgbm 模型上模拟部署:

代码语言:python
代码运行次数:0
复制
from merlion.evaluate.forecast import ForecastEvaluator, ForecastEvaluatorConfig, ForecastMetric


def create_evaluator(model):
    # 重新初始化模型
    model.reset()
    evaluator = ForecastEvaluator(
        model=model, config=ForecastEvaluatorConfig(
            cadence="90d", horizon="180d", retrain_freq="90d", train_window="360d")
    )
    return evaluator

lgbm_evaluator = create_evaluator(lgbm)
lgbm_train_result, lgbm_test_result = lgbm_evaluator.get_predict(train_vals=air_pass_ts_train, test_vals=air_pass_ts_test)

rmse = lgbm_evaluator.evaluate(
    ground_truth=air_pass_ts_test,
    predict=lgbm_test_result,
    metric=ForecastMetric.RMSE)

print(f"{type(lgbm).__name__} RMSE:  {rmse:.3f}")

在本例中,我们将间隔设置为 90d 意味着每 3 个月训练模型预测未来 6 个月(horizon = 180d)。其他的参数设定,包括模型每 3 个月重新训练一次(retrain_freq=90d) 并使用 12 个月(train_window=360)的训练数据。最后,我们计算 RMSE 来评估我们模型的性能。

💡 相关资源

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 💡 环境配置
  • 💡 工具库架构
  • 💡 数据加载
    • 切片和分割
      • 预处理
      • 💡 模型库
      • 💡 自动机器学习
      • 💡 模型选择与模型集成
      • 💡 存储和加载模型
      • 💡 评估管道(pipeline)
      • 💡 相关资源
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档