Lewati ke konten utama

Deteksi Anomali dengan Anomalize di R

Pelajari cara mendeteksi anomali dalam kumpulan data deret waktu berukuran besar dan menyajikan wawasan dengan cara yang jauh lebih sederhana.
· 9 mnt Baca

Jelajahi bersama AI

Anaomalize: Deskripsi Singkat

Saat membahas anomali, kita mempertimbangkan titik data yang merupakan pencilan atau kejadian luar biasa. Mengidentifikasi kejadian tersebut mudah pada kumpulan data kecil dan dapat dilakukan dengan grafik analisis sederhana seperti boxplot. Namun, kasusnya menjadi rumit saat beralih ke kumpulan data besar, terutama pada deret waktu. Deret waktu adalah data yang ditangkap pada interval waktu tetap selama suatu periode; saat dianalisis, biasanya menunjukkan tren atau musiman. Mengidentifikasi anomali dalam kasus seperti ini cukup pelik.

Lalu hadir paket anomalize untuk deteksi anomali dalam analisis deret waktu; ini adalah algoritme deteksi anomali yang rapi, berbasis waktu, dan dapat diskalakan dari satu hingga banyak deret waktu.

Ada beberapa paket dan metode yang membantu pengembangannya, atau bisa dikatakan ini adalah kombinasi sumber daya yang tersedia dengan pendekatan yang dapat diskalakan.

Karya open source yang membantu antara lain:

  • Paket AnomalyDetection dari Twitter: Tersedia di Github (cran anaomalyDetection adalah karya yang berbeda).
  • Fungsi forecast::tsoutliers() dari Rob Hyndman yang tersedia melalui paket forecast.
  • Paket tsoutliers dari Javier Lopez-de-lacalle di CRAN.

Semua paket dan fungsi ini digunakan untuk diintegrasikan ke dalam alur kerja yang dapat diskalakan.

Mengenai alur kerja anomalize, prosesnya dibagi menjadi tiga bagian:

  • Dekomposisi deret waktu dengan time_decompose().
  • Deteksi anomali pada remainder dengan anomalize().
  • Transformasi batas bawah dan atas anomali dengan time_recompose().

Alur Kerja Deteksi Anomali

Dekomposisi Deret Waktu

Langkah pertama adalah dekomposisi deret waktu menggunakan time_decompose(). Nilai terukur atau nilai numerik yang perlu dideteksi untuk suatu grup tertentu diuraikan menjadi empat kolom yaitu observed, season, trend, dan remainder. Metode default yang digunakan untuk dekomposisi adalah stl, yaitu dekomposisi musiman yang memanfaatkan penghalus Loess.

Regresi Loess adalah metode paling umum untuk menghaluskan deret waktu yang volatil; metode ini memasangkan beberapa regresi pada lingkungan lokal—bisa juga dikatakan datanya dibagi dan regresi diterapkan pada setiap bagian—yang bermanfaat dalam deret waktu karena kita mengetahui batas waktu sebagai variabel X dalam kasus ini. Metode ini bekerja baik ketika tren mendominasi musiman dalam deret waktu.

Di sini, tren adalah pertumbuhan jangka panjang yang terjadi selama banyak pengamatan, dan musiman adalah pola siklik yang terjadi dalam siklus harian per menit atau per jam atau mingguan.

Ada teknik kedua yang dapat digunakan untuk dekomposisi musiman pada deret waktu berbasis median, yaitu metode Twitter yang juga digunakan oleh paket AnomalyDetection. Metode ini identik dengan STL untuk menghilangkan komponen musiman. Perbedaannya dalam menghilangkan tren adalah penggunaan median potong per bagian dari data (satu atau beberapa median yang dipisah pada interval tertentu) alih-alih memasang penghalus. Metode ini bekerja baik ketika musiman mendominasi tren dalam deret waktu.

Mari bahas keluaran dari fungsi time_decompose(). Seperti dijelaskan di atas, fungsi ini menghasilkan 4 kolom:

  • observed: Nilai aktual.
  • season: Tren musiman atau siklik. Default-nya adalah musiman mingguan.
  • trend: Tren jangka panjang. Default-nya adalah rentang 3 bulan.
  • remainder: Digunakan untuk menganalisis pencilan. Ini hanyalah observed dikurangi season dan trend.

Fungsi time_decompose() memiliki argumen merge; dengan menyetelnya ke TRUE kita dapat mempertahankan data asli beserta kolom yang dihasilkan.

# Using data package provided in the anomalize package and taking single time series of package purrr

purrr_package = tidyverse_cran_downloads%>%
  filter(package == "purrr")%>%
  ungroup()

purrr_anomaly  = purrr_package %>%
  time_decompose(count)

purrr_anomaly%>% glimpse()
 ## Observations: 425
## Variables: 5
## $ date      <date> 2017-01-01, 2017-01-02, 2017-01-03, 2017-01-04, 201...
## $ observed  <dbl> 550, 1012, 1515, 1702, 1696, 1613, 860, 796, 2008, 2...
## $ season    <dbl> -2158.8893, 692.6571, 1087.5708, 1052.3294, 939.9377...
## $ trend     <dbl> 1496.712, 1511.009, 1525.307, 1539.604, 1553.901, 15...
## $ remainder <dbl> 1212.1777, -1191.6661, -1097.8773, -889.9334, -797.8...

Mendeteksi anomali pada remainder

Setelah analisis deret waktu selesai dan remainder memiliki karakteristik yang diinginkan untuk melakukan deteksi anomali, proses ini kembali membuat tiga kolom baru.

  • remainder_l1: Batas bawah remainder.
  • remainder_l2: Batas atas remainder.
  • anaomaly: Kolom yang menyatakan apakah suatu observasi merupakan anomali atau tidak.

Anomali adalah titik berpengaruh tinggi yang mendistorsi distribusi. Paket anomalize menerapkan dua metode yang tahan terhadap titik berpengaruh tinggi:

  • IQR: Inner Quartile Range
  • GESD: Generalized Extreme Studentized Deviate Test

IQR

Ini adalah metode serupa yang digunakan dalam fungsi tsoutliers() pada paket forecast. Dalam IQR, diambil suatu distribusi dan rentang kuartil dalam 25% dan 75% untuk menetapkan distribusi remainder. Batas ditetapkan secara default pada faktor 3 kali di atas dan di bawah rentang kuartil dalam; setiap remainder yang melampaui batas dianggap sebagai anomali.

GESD

Dalam GESD, anomali dievaluasi secara progresif dengan menghapus pelanggar terburuk dan menghitung ulang statistik uji serta nilai kritis; atau lebih sederhana, rentang dihitung ulang setelah mengidentifikasi anomali secara iteratif.

Keduanya, IQR dan GESD, memiliki kelebihan dan kekurangan. IQR relatif lebih cepat karena tidak ada loop yang terlibat, tetapi tidak seakurat GESD karena anomali membuat median bias, yang diatasi dalam GESD.

purrr_anomaly = purrr_anomaly%>%
  anomalize(remainder)

purrr_anomaly%>% glimpse()
## Observations: 425
## Variables: 8
## $ date         <date> 2017-01-01, 2017-01-02, 2017-01-03, 2017-01-04, ...
## $ observed     <dbl> 550, 1012, 1515, 1702, 1696, 1613, 860, 796, 2008...
## $ season       <dbl> -2158.8893, 692.6571, 1087.5708, 1052.3294, 939.9...
## $ trend        <dbl> 1496.712, 1511.009, 1525.307, 1539.604, 1553.901,...
## $ remainder    <dbl> 1212.1777, -1191.6661, -1097.8773, -889.9334, -79...
## $ remainder_l1 <dbl> -4330.511, -4330.511, -4330.511, -4330.511, -4330...
## $ remainder_l2 <dbl> 4400.459, 4400.459, 4400.459, 4400.459, 4400.459,...
## $ anomaly      <chr> "No", "No", "No", "No", "No", "No", "No", "No", "...

Transformasi batas bawah dan atas anomali

Langkah terakhir alur kerja adalah membuat batas bawah dan atas di sekitar nilai observed dengan time_recompose. Fungsi ini menyusun kembali season, trend, remainder_l1, dan remainder_l2 menjadi batas baru yaitu:

  • recomposed_l1: Batas bawah pencilan di sekitar nilai observed.
  • recomposed_l2: Batas atas pencilan di sekitar nilai observed.
purrr_anomaly = purrr_anomaly%>%
  time_recompose()

purrr_anomaly%>% glimpse()
## Observations: 425
## Variables: 10
## $ date          <date> 2017-01-01, 2017-01-02, 2017-01-03, 2017-01-04,...
## $ observed      <dbl> 550, 1012, 1515, 1702, 1696, 1613, 860, 796, 200...
## $ season        <dbl> -2158.8893, 692.6571, 1087.5708, 1052.3294, 939....
## $ trend         <dbl> 1496.712, 1511.009, 1525.307, 1539.604, 1553.901...
## $ remainder     <dbl> 1212.1777, -1191.6661, -1097.8773, -889.9334, -7...
## $ remainder_l1  <dbl> -4330.511, -4330.511, -4330.511, -4330.511, -433...
## $ remainder_l2  <dbl> 4400.459, 4400.459, 4400.459, 4400.459, 4400.459...
## $ anomaly       <chr> "No", "No", "No", "No", "No", "No", "No", "No", ...
## $ recomposed_l1 <dbl> -4992.689, -2126.845, -1717.634, -1738.578, -183...
## $ recomposed_l2 <dbl> 3738.281, 6604.125, 7013.336, 6992.392, 6894.298...

Memplot Anomali

purrr_anomaly%>%
  plot_anomaly_decomposition()+
  ggtitle("Plotting Anomalies")
memplot anomali

Penyetelan parameter

Memodelkan pendeteksi anomali tidak lengkap tanpa menyesuaikan parameter, yang sepenuhnya bergantung pada data.

Mari masuk ke penyesuaian parameter. Parameter pada setiap level alur kerja berbeda karena tiap level menjalankan tugasnya sendiri.

Menyesuaikan parameter dekomposisi

Seperti dibahas sebelumnya, tren dan musiman adalah hal mendasar untuk menguraikan deret waktu, maka penyesuaian juga perlu dilakukan pada frekuensi dan tren pada fungsi time_decompose. Secara default, nilainya ditetapkan otomatis yaitu 7 hari untuk frekuensi pada kedua metode (STL, Twitter), dan untuk tren adalah 91 hari untuk STL dan 85 hari untuk Twitter.

Anda dapat menyetel kedua atau salah satu argumen sesuai kebutuhan, tetapi perhatikan dengan saksama sebelum menyesuaikan karena perubahan tanpa pengamatan dapat menyebabkan dekomposisi terlalu pas atau kurang pas.

purrr_package %>%
  time_decompose(count, frequency = "auto", trend = "2 weeks")%>%
  anomalize(remainder)%>%
  plot_anomaly_decomposition()+
  ggtitle("Trend = 2 Weeks / Frequency = auto ")
deret waktu

Menyesuaikan parameter untuk Deteksi Anomali

Seperti dibahas di atas, di sini anomali ditentukan menurut nilai remainder dengan menghitung batas untuk mengkategorikan pencilan. Parameter alpha dan max_anoms adalah dua parameter yang mengendalikan fungsi anomalize(). Secara sederhana, alpha mengontrol lebar pita batas; default-nya 0,05. Menurunkan nilainya akan memperlebar pita sehingga membuat suatu titik lebih sulit menjadi anomali.

purrr_package%>%
  time_decompose(count)%>%
  anomalize(remainder, alpha = 0.05)%>%
  time_recompose()%>%
  plot_anomalies(time_recompose = T)+
  ggtitle("alpha = 0.05")
deret waktu
purrr_package%>%
  time_decompose(count)%>%
  anomalize(remainder, alpha = 0.025)%>%
  time_recompose()%>%
  plot_anomalies(time_recompose = T)+
  ggtitle("alpha = 0.025")
deret waktu

Parameter max_anom mengontrol persentase data yang boleh menjadi anomali. Parameter ini berguna ketika alpha sulit disetel, dan Anda ingin berfokus pada anomali yang paling agresif.

purrr_package%>%
  time_decompose(count)%>%
  anomalize(remainder, alpha = 0.2, max_anoms = 0.2)%>%
  time_recompose()%>%
  plot_anomalies(time_recompose = T)+
  ggtitle("20% anomaly Allowed")
deret waktu
purrr_package%>%
  time_decompose(count)%>%
  anomalize(remainder, alpha = 0.2, max_anoms = 0.05)%>%
  time_recompose()%>%
  plot_anomalies(time_recompose = T)+
  ggtitle("5% anomaly Allowed")
deret waktu

Referensi

Jika Anda ingin mempelajari lebih lanjut tentang R, ikuti kursus Introduction to Time Series Analysis dari DataCamp.

Lihat juga Time Series Analysis using R: Tutorial kami.

Topik

Terkait

blogs

Tutorial Korelasi di R

blogs

Spaghetti Plot dan Jalur Badai

blogs

40 Pertanyaan Wawancara DBMS Teratas di 2026