時間序列分解和異常檢測方法應用案例

原文 http://tecdat.cn/?p=3232


咱們最近有一個很棒的機會與一位偉大的客戶合做,要求Business Science構建一個適合他們需求的開源異常檢測算法。業務目標是準確地檢測各類營銷數據的異常狀況,這些數據包括跨多個客戶和Web源跨越數千個時間序列的網站操做和營銷反饋。輸入anomalize:一個整潔的異常檢測算法,該算法基於時間(創建在之上tibbletime)並可從一個到多個時間序列進行擴展!咱們很是高興可以爲其餘人提供這個開源R軟件包以使其受益。在這篇文章中,咱們將概述anomalize它的做用和方式。算法

案例研究:當開源利益調整時

咱們與許多教授數據科學的客戶合做,並利用咱們的專業知識加速業務發展。然而,不多有客戶的需求和他們願意讓其餘人受益於咱們推進數據科學界限的利益。這是一個例外。服務器

咱們的客戶遇到了一個具備挑戰性的問題:按時間順序檢測每日或每週數據的時間序列異常。異常表示異常事件,多是營銷域中的Web流量增長或IT域中的故障服務器。不管如何,標記這些不尋常的事件以確保業務順利運行很是重要。其中一個挑戰是客戶處理的不是一個時間序列,而是須要針對這些極端事件進行分析函數

咱們有機會開發一個開源軟件包,該軟件包符合咱們的興趣,即構建Twitter AnomalyDetection軟件包的可擴展版本,以及咱們的客戶但願得到一個能夠從開源數據科學社區隨着時間的推移而改進的軟件包的願望。結果是anomalize!!!網站

anomalize

對於咱們這些喜歡閱讀的人來講,這裏有anomalize四個簡單步驟的工做要點。spa

第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步:異常化

使用三個整齊的功能:time_decompose(),anomalize(),並time_recompose()及時發現異常狀況。

異常工做流程

您剛剛實施了「異常檢測」(異常檢測)工做流程,其中包括:code

  • 用時間序列分解 time_decompose()
  • 用餘數檢測餘數的異常 anomalize()
  • 異常下限和上限轉換 time_recompose()

時間序列分解

第一步是使用時間序列分解time_decompose()。「計數」列被分解爲「觀察」,「季節」,「趨勢」和「剩餘」列。時間序列分解的默認值是method = "stl",使用黃土平滑器進行季節性分解(參見stats::stl())。的frequency和trend參數是基於使用所述時間序列的時間尺度(或週期性)自動設置tibbletime在引擎蓋下基於函數。blog

## # 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!索引

餘數的異常檢測

下一步是對分解的數據執行異常檢測,特別是「餘數」列。咱們使用了這個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

若是你想一想象正在發生的事情,如今嘗試另外一個繪圖功能是一個好點plot_anomaly_decomposition()。它只適用於單個時間序列,所以咱們只需選擇一個便可查看。「季節」正在消除每週的循環季節性。趨勢是平滑的,這對於消除集中趨勢而不過分擬合是合乎須要的。最後,分析剩餘部分以檢測最重要的異常值的異常。ci

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")

異常下限和上限

最後一步是圍繞「觀察」值建立下限和上限。這是工做time_recompose(),它從新組合觀察值周圍的異常的下限和上限。建立了兩個新列:「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 Anomaly Decomposition

plot_anomalies(time_recomposed = TRUE) +

ggtitle("Lubridate Downloads: Anomalies Detected")

預測tsoutliers()函數

包 中的tsoutliers()功能forecast是在執行預測以前有效收集異常值以進行清潔的好方法。它使用基於STL的離羣值檢測方法,其具備圍繞時間序列分解的餘數的3X內四分位數範圍。它很是快,由於最多有兩次迭代來肯定異​​常值帶。可是,它沒有設置整潔的工做流程。也不容許調整3X。一些時間序列可能須要更多或更少,這取決於剩餘部分的方差的大小與異常值的大小的關係。

tsoutliers包

該tsoutliers軟件包很是有效地用於檢測異常的許多傳統預測時間序列。可是,速度是一個問題,特別是在嘗試擴展到多個時間序列或分鐘或秒時間戳數據時。

 在審查可用的軟件包時,咱們從中瞭解到全部軟件包的最佳組合:

  • 分解方法:咱們包括兩個時間序列分解方法:( "stl"使用Loess的傳統季節分解)和"twitter"(使用中間跨度的季節分解)。
  • 異常檢測方法:咱們包括兩種異常檢測方法:( "iqr"使用相似於3X IQR的方法forecast::tsoutliers())和"gesd"(使用Twitter使用的GESD方法AnomalyDetection)。

另外,咱們對本身作了一些改進:

  • Anomalize Scales Well:工做流程整潔,可與dplyr羣組進行縮放。這些函數按分組時間序列按預期運行,這意味着您能夠輕鬆地將500個時間序列數據集異常化爲單個數據集
  • 用於分析異常的視覺效果
  • 咱們提供了一種方法來圍繞分離異常值的「正常」數據。人是視覺的,樂隊在肯定方法的工做方式或是否須要進行調整時很是有用。
  • 咱們包括兩個繪圖函數所以很容易看到「anomalize工做流程」期間發生了什麼事,並提供一種方法來評估的「調節旋鈕」驅動的影響time_decompose()和anomalize()。
  • 基於時間
  • 整個工做流程使用tibbletime基於時間的索引設置數據。這很好,由於根據咱們的經驗,幾乎全部時間數據都帶有日期或日期時間戳,這對數據的特徵很是重要。
  • 無需計算在頻率跨度或趨勢跨度內有多少觀測值。咱們設置time_decompose()處理frequency和trend使用基於時間的跨度,例如「1周」或「2季度」(由...提供tibbletime)。

結論

 咱們的客戶對此很是滿意,看到咱們能夠繼續構建每一個人均可以享受的新功能和功能使人興奮。

有問題歡迎下方留言!

相關文章
相關標籤/搜索