我们最近有一个很棒的机会与一位客户合作,要求构建一个适合他们需求的异常检测算法。业务目标是准确地检测各种营销数据的异常情况,这些数据包括跨多个客户和Web源数千个时间序列的网站操作和营销反馈。异常检测算法,该算法基于时间并可从一个到多个时间序列进行扩展。
案例研究
我们与许多教授数据科学的客户合作,并利用我们的专业知识加速业务发展。
我们的客户遇到了一个具有挑战性的问题:按时间顺序检测每日或每周数据的时间序列异常。异常表示异常事件,可能是营销域中的Web流量增加或IT域中的故障服务器。无论如何,标记这些不寻常的事件确保业务顺利运行非常重要。其中一个挑战是客户处理的不是一个时间序列,而是需要针对这些极端事件进行分析。
anomalize
这里有四个简单步骤的工作要点。
第1步:安装 install.packages("tidyverse") 第2步:加载 library(tidyverse) 第3步:收集时间序列数据 tidyverse\_cran\_downloads ## # A tibble: 6,375 x 3 ## # Groups: package \[15\] ## date count package ## ## 1 2017-01-01 873. tidyr ## 2 2017-01-02 1840. tidyr ## 3 2017-01-03 2495. tidyr ## 4 2017-01-04 2906. tidyr ## 5 2017-01-05 2847. tidyr ## 6 2017-01-06 2756. tidyr ## 7 2017-01-07 1439. tidyr ## 8 2017-01-08 1556. tidyr ## 9 2017-01-09 3678. tidyr ## 10 2017-01-10 7086. tidyr ## # ... with 6,365 more rows 第4步:异常化 使用功能及时发现异常情况。
异常检测工作流程
其中包括:
- 用时间序列分解
- 用检测异常
- 异常下限和上限转换
时间序列分解
第一步是使用时间序列分解。“计数”列被分解为“观察”,“季节”,“趋势”和“剩余”列。时间序列分解的默认值是method = "stl",使用平滑器进行季节性分解。
## # A time tibble: 6,375 x 6 ## # Index: date ## # Groups: package \[15\] ## package date observed season trend remainder ## ## 1 tidyr 2017-01-01 873. -2761. 5053. -1418. ## 2 tidyr 2017-01-02 1840. 901. 5047. -4108. ## 3 tidyr 2017-01-03 2495. 1460. 5041. -4006. ## 4 tidyr 2017-01-04 2906. 1430. 5035. -3559. ## 5 tidyr 2017-01-05 2847. 1239. 5029. -3421. ## 6 tidyr 2017-01-06 2756. 367. 5024. -2635. ## 7 tidyr 2017-01-07 1439. -2635. 5018. -944. ## 8 tidyr 2017-01-08 1556. -2761. 5012. -695. ## 9 tidyr 2017-01-09 3678. 901. 5006. -2229. ## 10 tidyr 2017-01-10 7086. 1460. 5000. 626. ## # ... with 6,365 more rows
frequency并trend自动为您选择。此外,可以通过输入基于时间的周期(例如“1周”或“2个季度”)来更改选择,可以确定有多少观察属于时间跨度。
异常检测
下一步是对分解的数据执行异常检测。产生了三个新列:“remainder\_l1”(下限),“remainder\_l2”(上限)和“异常”(是/否标志)。默认方法是method = "iqr",在检测异常时快速且相对准确。
## # Groups: package \[15\] ## package date observed season trend remainder remainder_l1 ## ## 1 tidyr 2017-01-01 873. -2761. 5053. -1418. -3748. ## 2 tidyr 2017-01-02 1840. 901. 5047. -4108. -3748. ## 3 tidyr 2017-01-03 2495. 1460. 5041. -4006. -3748. ## 4 tidyr 2017-01-04 2906. 1430. 5035. -3559. -3748. ## 5 tidyr 2017-01-05 2847. 1239. 5029. -3421. -3748. ## 6 tidyr 2017-01-06 2756. 367. 5024. -2635. -3748. ## 7 tidyr 2017-01-07 1439. -2635. 5018. -944. -3748. ## 8 tidyr 2017-01-08 1556. -2761. 5012. -695. -3748. ## 9 tidyr 2017-01-09 3678. 901. 5006. -2229. -3748. ## 10 tidyr 2017-01-10 7086. 1460. 5000. 626. -3748. ## # ... with 6,365 more rows, and 2 more variables: remainder_l2 , ## # anomaly
现在尝试另一个绘图功能。它只适用于单个时间序列。“季节”消除每周的季节性。趋势是平滑的。最后,检测最重要的异常值。
tidyverse\_cran\_downloads %>% time_decompose(count, method = "stl", frequency = "auto", trend = "auto") %>% anomalize(remainder, method = "iqr", alpha = 0.05, max_anoms = 0.2) %>% plot\_anomaly\_decomposition() +
异常下限和上限
最后一步是围绕“观察”值创建下限和上限。创建了两个新列:“recomposed\_l1”(下限)和“recomposed\_l2”(上限)。
## # A time tibble: 6,375 x 11 ## # Index: date ## # Groups: package \[15\] ## package date observed season trend remainder remainder_l1 ## ## 1 tidyr 2017-01-01 873. -2761. 5053. -1418. -3748. ## 2 tidyr 2017-01-02 1840. 901. 5047. -4108. -3748. ## 3 tidyr 2017-01-03 2495. 1460. 5041. -4006. -3748. ## 4 tidyr 2017-01-04 2906. 1430. 5035. -3559. -3748. ## 5 tidyr 2017-01-05 2847. 1239. 5029. -3421. -3748. ## 6 tidyr 2017-01-06 2756. 367. 5024. -2635. -3748. ## 7 tidyr 2017-01-07 1439. -2635. 5018. -944. -3748. ## 8 tidyr 2017-01-08 1556. -2761. 5012. -695. -3748. ## 9 tidyr 2017-01-09 3678. 901. 5006. -2229. -3748. ## 10 tidyr 2017-01-10 7086. 1460. 5000. 626. -3748. ## # ... with 6,365 more rows, and 4 more variables: remainder_l2 , ## # anomaly , recomposed\_l1 , recomposed\_l2
让我们看一下“lubridate”数据。我们可以plot\_anomalies()和设置time\_recomposed = TRUE。此功能适用于单个和分组数据。
time_decompose(count, method = "stl", frequency = "auto", trend = "auto") %>% anomalize(remainder, method = "iqr", alpha = 0.05, max_anoms = 0.2) %>% time_recompose() %>% # 绘制异常分解 plot\_anomalies(time\_recomposed = TRUE) + ggtitle("Lubridate Downloads: Anomalies Detected")
预测
forecast是在执行预测之前有效收集异常值的好方法。它使用基于STL的离群值检测方法。它非常快,因为最多有两次迭代来确定异常值带。
结论
R软件非常有效地用于检测异常的许多传统预测时间序列。但是,速度是一个问题,特别是在尝试扩展到多个时间序列时。
我们从中了解到所有软件包的最佳组合:
- 分解方法:我们包括两个时间序列分解方法:( "stl"使用Loess的传统季节分解)和"twitter"(使用中间跨度的季节分解)。
- 异常检测方法:我们包括两种异常检测方法:( "iqr"使用类似于3X IQR的方法forecast::tsoutliers())和"gesd"(使用Twitter使用的GESD方法AnomalyDetection)。
有问题欢迎下方留言!