pip install statsforecast -U异常检测
在本笔记中,我们将实现时间序列数据中的异常检测
本教程假设您对 StatsForecast 有基本的了解。有关最简示例,请访问 快速入门
引言
异常检测是时间序列预测中的一个关键任务。它涉及识别不符合预期数据集模式的异常观察值。异常值,也称为离群点,可以由多种因素引起,例如数据收集过程中的错误、数据潜在模式的突变或意外事件。它们可能对许多预测模型造成问题,因为它们可能扭曲趋势、季节性模式或自相关估计。因此,异常值可能对预测的准确性产生重大影响,这也是能够识别它们的必要原因。此外,异常检测在不同的行业中有许多应用,例如检测金融数据中的欺诈、监控在线服务的性能或识别能源使用中的常见模式。
在本教程结束时,您将对如何使用 StatsForecast 的概率模型在时间序列数据中检测异常有一个很好的理解。
大纲:
- 安装库
- 加载和探索数据
- 训练模型
- 恢复样本内预测并识别异常值
一旦识别出异常,我们必须决定如何处理它。例如,我们可以将其移除或替换为其他值。正确的处理方法依赖于具体背景,并超出了本笔记本的范围。移除异常可能会提高预测的准确性,但也可能低估数据中的随机性。
安装库
我们假设您已经安装了StatsForecast。如果没有,请查看本指南了解如何安装StatsForecast 的说明。
使用 pip install statsforecast 安装必要的包。
加载和探索数据
在这个例子中,我们将使用M4竞赛的每小时数据集。我们首先从datasetsforecast导入数据,您可以使用pip install datasetsforecast进行安装。
pip install datasetsforecast -U from datasetsforecast.m4 import M4 加载数据的函数是 M4.load。它需要以下两个参数:
directory: (字符串)数据将被下载的目录。group: (字符串)组名,可以是Yearly、Quarterly、Monthly、Weekly、Daily或Hourly。
此函数返回多个输出,但只需要第一个带有目标序列的输出。
df_total, *_ = M4.load('./data', 'Hourly')
df_total.head()| unique_id | ds | y | |
|---|---|---|---|
| 0 | H1 | 1 | 605.0 |
| 1 | H1 | 2 | 586.0 |
| 2 | H1 | 3 | 586.0 |
| 3 | H1 | 4 | 559.0 |
| 4 | H1 | 5 | 511.0 |
Stats
df_total['ds'] = df_total['ds'].astype(int)从这个数据集中,我们将选择前8个时间序列以减少总执行时间。您可以通过更改 n_series 的值来选择任意数量的时间序列。
n_series = 8
uids = df_total['unique_id'].unique()[:n_series]
df = df_total.query('unique_id in @uids')我们可以使用StatsForecast类中的plot方法绘制这些系列。该方法有多个参数,生成此笔记本中图表所需的参数如下所述。
df: 一个包含 [unique_id, ds, y] 列的 pandas 数据框。forecasts_df: 一个包含 [unique_id, ds] 和模型的 pandas 数据框。unique_ids: (list[str]) 一个包含我们想要绘制的时间序列的ID列表。plot_random: (bool = True) 随机绘制时间序列。plot_anomalies: (bool = False) 绘制每个预测区间的异常值。engine: (str = plotly) 用于生成图表的库。静态图表也可以使用matplotlib。
from statsforecast import StatsForecast StatsForecast.plot(df, plot_random = False) 训练模型
为了生成预测,我们将使用MSTL模型,该模型非常适合像这里使用的低频数据。我们首先需要从statsforecast.models导入它,然后需要实例化它。由于我们使用的是每小时的数据,因此我们有两个季节周期:每24小时(每小时)和每24*7小时(每日)。因此,我们需要设置season_length = [24, 24*7]。
from statsforecast.models import MSTL
# 创建一个模型及其实例化参数的列表
models = [MSTL(season_length = [24, 24*7])]要实例化一个新的 StatsForecast 对象,我们需要以下参数:
df:包含训练数据的数据框。models:在上一步中定义的模型列表。freq:一个字符串,指示数据的频率。请参阅pandas 的可用频率。n_jobs:一个整数,指示并行处理使用的作业数量。使用 -1 选择所有核心。
sf = StatsForecast(
df = df,
models = models,
freq = 'H',
n_jobs = -1
)我们现在将预测接下来的48小时。为此,我们将使用forecast方法,该方法需要以下参数:
h: (int) 预测的时间范围。level: (list[float]) 预测区间的置信水平。fitted: (bool = False) 返回样本内预测值。
选择一个level并将fitted设置为True非常重要,因为我们需要样本内预测及其预测区间来检测异常。
horizon = 48
levels = [99]
fcst = sf.forecast(h = 48, level = levels, fitted = True)
fcst = fcst.reset_index()
fcst.head()| unique_id | ds | MSTL | MSTL-lo-99 | MSTL-hi-99 | |
|---|---|---|---|---|---|
| 0 | H1 | 749 | 615.943970 | 597.662170 | 634.225708 |
| 1 | H1 | 750 | 559.297791 | 531.316650 | 587.278931 |
| 2 | H1 | 751 | 515.693542 | 479.151337 | 552.235718 |
| 3 | H1 | 752 | 480.719269 | 436.241547 | 525.197021 |
| 4 | H1 | 753 | 467.146484 | 415.199738 | 519.093262 |
我们可以使用之前的 plot 方法绘制预测图。
StatsForecast.plot(df, fcst, plot_random = False) 恢复样本内预测并识别异常
在这个例子中,异常是指在给定置信水平(这里选择了99%)的样本内预测的预测区间之外的任何观测值。因此,我们首先需要使用 forecast_fitted_values 方法来恢复样本内的预测。
insample_forecasts = sf.forecast_fitted_values().reset_index()
insample_forecasts.head()| unique_id | ds | y | MSTL | MSTL-lo-99 | MSTL-hi-99 | |
|---|---|---|---|---|---|---|
| 0 | H1 | 1 | 605.0 | 604.924500 | 588.010376 | 621.838623 |
| 1 | H1 | 2 | 586.0 | 585.221802 | 568.307678 | 602.135925 |
| 2 | H1 | 3 | 586.0 | 589.740723 | 572.826599 | 606.654846 |
| 3 | H1 | 4 | 559.0 | 557.778076 | 540.863953 | 574.692200 |
| 4 | H1 | 5 | 511.0 | 506.747009 | 489.832886 | 523.661133 |
我们现在可以找到所有在样本预测中超过或低于99%预测区间的观察值。
anomalies = insample_forecasts.loc[(insample_forecasts['y'] >= insample_forecasts['MSTL-hi-99']) | (insample_forecasts['y'] <= insample_forecasts['MSTL-lo-99'])]
anomalies.head()| unique_id | ds | y | MSTL | MSTL-lo-99 | MSTL-hi-99 | |
|---|---|---|---|---|---|---|
| 168 | H1 | 169 | 813.0 | 779.849792 | 762.935669 | 796.763916 |
| 279 | H1 | 280 | 692.0 | 672.638123 | 655.723999 | 689.552246 |
| 289 | H1 | 290 | 770.0 | 792.015442 | 775.101318 | 808.929565 |
| 308 | H1 | 309 | 844.0 | 867.809387 | 850.895203 | 884.723511 |
| 336 | H1 | 337 | 853.0 | 822.427002 | 805.512878 | 839.341187 |
我们可以通过在plot方法中添加plot_anomalies = True参数来绘制异常值。
StatsForecast.plot(insample_forecasts, plot_random = False, plot_anomalies = True)如果我们想更仔细地观察,可以使用 unique_ids 参数来选择一个特定的时间序列,例如 H10。
StatsForecast.plot(insample_forecasts, unique_ids = ['H10'], plot_anomalies = True) 在这里,我们使用MSTL模型识别了数据中的异常,但可以使用StatsForecast中的任何概率模型。我们还选择了样本预测的99%预测区间,但也可以使用其他置信水平。
Give us a ⭐ on Github