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