异常检测是数据科学中的一个重要环节,它涉及到识别偏离数据集常规行为的数据点。异常数据可能表明关键事件,如金融欺诈、软件问题或潜在机会,比如用户购买模式的变化。
时间序列的异常检测过程分为三个步骤:将时间序列分解为底层变量(趋势、季节性、残差),创建带有某些阈值的上下阈值,并识别超出阈值的数据点作为异常。
将从新加坡政府网站下载数据集,该数据集展示了按住宅类型划分的家庭总电力消耗(以GWh为单位)。新加坡政府数据网站的数据非常容易下载。
该数据集由能源市场管理局管理,每年发布一次,遵循新加坡开放数据许可。
在这个练习中,将使用R中两个关键的时间序列异常检测包:anomalize和timetk。这些包要求对象被创建为时间tibble,因此还将加载tibble包。首先,安装并加载这些库。
pkg <- c('tidyverse','tibbletime','anomalize','timetk')
install.packages(pkg)
library(tidyverse)
library(tibbletime)
library(anomalize)
library(timetk)
在上一步中,已经从新加坡政府网站下载了按住宅类型划分的总电力消耗文件(以GWh为单位)。让将CSV文件加载到R数据框中。
df <- read.csv("C:/Anomaly Detection in R/total-household-electricity-consumption.csv")
head(df,5)
在应用任何异常算法之前,需要将数据转换为日期格式。原始的“月份”列是因子格式,有很多级别。让将其转换为日期类型,并在数据框中仅选择相关列。
df$month <- paste(df$month, "01", sep="-")
df$month <- as.Date(df$month,format="%Y-%m-%d")
df <- df %>% select(month,overall)
df <- as_tibble(df)
class(df)
R的‘anomalize’包支持数据中异常检测的工作流程。主要函数包括time_decompose()、anomalize()和time_recompose()。
df_anomalized <- df %>%
time_decompose(overall, merge = TRUE) %>%
anomalize(remainder) %>%
time_recompose()
df_anomalized %>% glimpse()
然后可以使用plot_anomalies()函数可视化异常。
df_anomalized %>% plot_anomalies(ncol = 3, alpha_dots = 0.75)
使用anomalize进行调整非常简单,因为一切都是通过日期或DateTime信息完成的,所以可以直观地选择有意义的时间跨度增量(例如“5分钟”或“1个月”)。
首先,注意频率和趋势为自动选择了。这是有意为之的。参数frequency = “auto”和trend = “auto”是默认值。可以使用plot_anomaly_decomposition()来可视化这种分解。
p1 <- df_anomalized %>%
plot_anomaly_decomposition() +
ggtitle("Freq/Trend = 'auto'")
p1
局部参数调整是通过调整函数内参数来执行的。下面调整趋势为“2周”,这将导致趋势过于拟合。
p2 <- df %>%
time_decompose(overall,
frequency = "auto",
trend = "2 weeks") %>%
anomalize(remainder) %>%
plot_anomaly_decomposition() +
ggtitle("Trend = 2 Weeks (Local)")
也可以通过使用set_time_scale_template()全局调整。将“3个月”的趋势更改为“2周”,用于时间尺度=“天”。使用time_scale_template()检索anomalize开始的默认模板,mutate()在所需位置更改趋势字段,并使用set_time_scale_template()更新全局选项中的模板。可以使用get_time_scale_template()检索更新后的模板,以验证更改是否已正确执行。
time_scale_template() %>%
mutate(trend = ifelse(time_scale == "day", "2 weeks", trend)) %>%
set_time_scale_template()
get_time_scale_template()
现在,可以提取实际的异常数据点。为此,可以运行以下代码。
df %>%
time_decompose(overall) %>%
anomalize(remainder) %>%
time_recompose() %>%
filter(anomaly == 'Yes')
alpha和max_anoms是控制anomalize()函数的两个参数。
Alpha
可以调整alpha,默认设置为0.05。默认情况下,带仅覆盖范围之外的部分。
p4 <- df %>%
time_decompose(overall) %>%
anomalize(remainder, alpha = 0.05, max_anoms = 0.2) %>%
time_recompose() %>%
plot_anomalies(time_recomposed = TRUE) +
ggtitle("alpha = 0.05")
如果减少alpha,它会增加带的大小,使得成为异常值更加困难。这里,可以看到带的大小已经翻倍。
p5 <- df %>%
time_decompose(overall) %>%
anomalize(remainder, alpha = 0.025, max_anoms = 0.2) %>%
time_recompose() %>%
plot_anomalies(time_recomposed = TRUE) +
ggtitle("alpha = 0.025")
Max Anoms
max_anoms参数用于控制数据中可以作为异常的最大百分比。让调整alpha = 0.3,以便几乎所有东西都是异常值。现在让尝试比较max_anoms = 0.2(允许20%的异常)和max_anoms = 0.05(允许5%的异常)。
p6 <- df %>%
time_decompose(overall) %>%
anomalize(remainder, alpha = 0.3, max_anoms = 0.2) %>%
time_recompose() %>%
plot_anomalies(time_recomposed = TRUE) +
ggtitle("20% Anomalies")
p7 <- df %>%
time_decompose(overall) %>%
anomalize(remainder, alpha = 0.3, max_anoms = 0.05) %>%
time_recompose() %>%
plot_anomalies(time_recomposed = TRUE) +
ggtitle("5% Anomalies")
这是一个用于在R中处理时间序列的工具包,用于绘制、整理和特征工程时间序列数据,以进行预测和机器学习预测。
交互式异常可视化
df %>% timetk::plot_anomaly_diagnostics(month,overall, .facet_ncol = 2)
df %>% timetk::tk_anomaly_diagnostics(month, overall) %>% filter(anomaly=='Yes')