時間序列分解和異常檢測方法應用案例
原文?http://tecdat.cn/?p=3232
?
我們最近有一個很棒的機會與一位偉大的客戶合作,要求Business Science構建一個適合他們需求的開源異常檢測算法。業(yè)務目標是準確地檢測各種營銷數據的異常情況,這些數據包括跨多個客戶和Web源跨越數千個時間序列的網站操作和營銷反饋。輸入anomalize:一個整潔的異常檢測算法,該算法基于時間(建立在之上tibbletime)并可從一個到多個時間序列進行擴展!我們非常高興能夠為其他人提供這個開源R軟件包以使其受益。在這篇文章中,我們將概述anomalize它的作用和方式。
案例研究:當開源利益調整時
我們與許多教授數據科學的客戶合作,并利用我們的專業(yè)知識加速業(yè)務發(fā)展。然而,很少有客戶的需求和他們愿意讓其他人受益于我們推動數據科學界限的利益。這是一個例外。
我們的客戶遇到了一個具有挑戰(zhàn)性的問題:按時間順序檢測每日或每周數據的時間序列異常。異常表示異常事件,可能是營銷域中的Web流量增加或IT域中的故障服務器。無論如何,標記這些不尋常的事件以確保業(yè)務順利運行非常重要。其中一個挑戰(zhàn)是客戶處理的不是一個時間序列,而是需要針對這些極端事件進行分析。
我們有機會開發(fā)一個開源軟件包,該軟件包符合我們的興趣,即構建Twitter AnomalyDetection軟件包的可擴展版本,以及我們的客戶希望獲得一個可以從開源數據科學社區(qū)隨著時間的推移而改進的軟件包的愿望。結果是anomalize!!!
anomalize
對于我們這些喜歡閱讀的人來說,這里有anomalize四個簡單步驟的工作要點。
第1步:安裝Anomalize
install.packages("anomalize")
第2步:加載Tidyverse和Anomalize
library(tidyverse)
library(anomalize)
第3步:收集時間序列數據
我們提供了一個數據集,tidyverse_cran_downloads以幫助您啟動和運行。該數據集包括15“tidyverse”包的每日下載次數。
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步:異?;?/code>
使用三個整齊的功能:time_decompose(),anomalize(),并time_recompose()及時發(fā)現(xiàn)異常情況。

異常工作流程
您剛剛實施了“異常檢測”(異常檢測)工作流程,其中包括:
用時間序列分解 time_decompose()
用余數檢測余數的異常 anomalize()
異常下限和上限轉換 time_recompose()
時間序列分解
第一步是使用時間序列分解time_decompose()?!坝嫈怠绷斜环纸鉃椤坝^察”,“季節(jié)”,“趨勢”和“剩余”列。時間序列分解的默認值是method = "stl",使用黃土平滑器進行季節(jié)性分解(參見stats::stl())。的frequency和trend參數是基于使用所述時間序列的時間尺度(或周期性)自動設置tibbletime在引擎蓋下基于函數。
## # 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自動為您選擇。如果要查看所選內容,請進行設置message = TRUE。此外,您可以通過輸入基于時間的周期(例如“1周”或“2個季度”)來更改選擇,這通常更直觀,可以確定有多少觀察屬于時間跨度。引擎蓋下,time_frequency()以及time_trend()基于時間段將這些使用數值tibbletime!
余數的異常檢測
下一步是對分解的數據執(zhí)行異常檢測,特別是“余數”列。我們使用了這個anomalize(),它產生了三個新列:“remainder_l1”(下限),“remainder_l2”(上限)和“異?!保ㄊ?否標志)。默認方法是method = "iqr",在檢測異常時快速且相對準確。alpha默認情況下alpha = 0.05,該參數設置為,但可以調整該參數以增加或減少異常頻段的高度,從而使數據更難或更難以變得異常。max_anoms默認情況下,該參數設置為max_anoms = 0.2可能異常的20%數據的最大值。這是可以調整的第二個參數。最后,verbose = FALSE默認情況下返回一個數據框。嘗試設置verbose = TRUE 以列表的形式獲取異常值報告。
## # 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
如果你想想象正在發(fā)生的事情,現(xiàn)在嘗試另一個繪圖功能是一個好點plot_anomaly_decomposition()。它只適用于單個時間序列,因此我們只需選擇一個即可查看。“季節(jié)”正在消除每周的循環(huán)季節(jié)性。趨勢是平滑的,這對于消除集中趨勢而不過度擬合是合乎需要的。最后,分析剩余部分以檢測最重要的異常值的異常。
tidyverse_cran_downloads %>%
# Anomalize
time_decompose(count, method = "stl", frequency = "auto", trend = "auto") %>%
anomalize(remainder, method = "iqr", alpha = 0.05, max_anoms = 0.2) %>%
# Plot Anomaly Decomposition
plot_anomaly_decomposition() +
ggtitle("Lubridate Downloads: Anomaly Decomposition")

異常下限和上限
最后一步是圍繞“觀察”值創(chuàng)建下限和上限。這是工作time_recompose(),它重新組合觀察值周圍的異常的下限和上限。創(chuàng)建了兩個新列:“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
讓我們看一下“l(fā)ubridate”數據。我們可以使用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 Anomaly Decomposition
plot_anomalies(time_recomposed = TRUE) +
ggtitle("Lubridate Downloads: Anomalies Detected")

?
預測tsoutliers()函數
包 中的tsoutliers()功能forecast是在執(zhí)行預測之前有效收集異常值以進行清潔的好方法。它使用基于STL的離群值檢測方法,其具有圍繞時間序列分解的余數的3X內四分位數范圍。它非常快,因為最多有兩次迭代來確定異常值帶。但是,它沒有設置整潔的工作流程。也不允許調整3X。一些時間序列可能需要更多或更少,這取決于剩余部分的方差的大小與異常值的大小的關系。
tsoutliers包
該tsoutliers軟件包非常有效地用于檢測異常的許多傳統(tǒng)預測時間序列。但是,速度是一個問題,特別是在嘗試擴展到多個時間序列或分鐘或秒時間戳數據時。
?在審查可用的軟件包時,我們從中了解到所有軟件包的最佳組合:
分解方法:我們包括兩個時間序列分解方法:( "stl"使用Loess的傳統(tǒng)季節(jié)分解)和"twitter"(使用中間跨度的季節(jié)分解)。
異常檢測方法:我們包括兩種異常檢測方法:( "iqr"使用類似于3X IQR的方法forecast::tsoutliers())和"gesd"(使用Twitter使用的GESD方法AnomalyDetection)。
另外,我們對自己做了一些改進:
Anomalize Scales Well:工作流程整潔,可與dplyr群組進行縮放。這些函數按分組時間序列按預期運行,這意味著您可以輕松地將500個時間序列數據集異常化為單個數據集。
用于分析異常的視覺效果:
我們提供了一種方法來圍繞分離異常值的“正?!睌祿?。人是視覺的,樂隊在確定方法的工作方式或是否需要進行調整時非常有用。
我們包括兩個繪圖函數因此很容易看到“anomalize工作流程”期間發(fā)生了什么事,并提供一種方法來評估的“調節(jié)旋鈕”驅動的影響time_decompose()和anomalize()。
基于時間:
整個工作流程使用tibbletime基于時間的索引設置數據。這很好,因為根據我們的經驗,幾乎所有時間數據都帶有日期或日期時間戳,這對數據的特征非常重要。
無需計算在頻率跨度或趨勢跨度內有多少觀測值。我們設置time_decompose()處理frequency和trend使用基于時間的跨度,例如“1周”或“2季度”(由...提供tibbletime)。
結論
?我們的客戶對此非常滿意,看到我們可以繼續(xù)構建每個人都可以享受的新功能和功能令人興奮。
有問題歡迎下方留言!