Tutorial: Mendeteksi anomali dalam rangkaian waktu dengan ML.NET

Pelajari cara membuat aplikasi deteksi anomali untuk data rangkaian waktu. Tutorial ini membuat aplikasi konsol .NET menggunakan C# di Visual Studio 2019.

Dalam tutorial ini, Anda mempelajari cara:

  • Muat data
  • Mendeteksi periode untuk rangkaian waktu
  • Mendeteksi anomali untuk rangkaian waktu berkala

Anda dapat menemukan kode sumber untuk tutorial ini di repositori dotnet/samples .

Prasyarat

Membuat aplikasi konsol

  1. Buat Aplikasi Konsol C# yang disebut "PhoneCallsAnomalyDetection". Pilih Selanjutnya.

  2. Pilih .NET 8 sebagai kerangka kerja target. Pilih Buat.

  3. Buat direktori bernama Data di proyek Anda untuk menyimpan file himpunan data Anda.

  4. Instal Microsoft.ML NuGet Package versi 1.5.2:

    1. Di Penjelajah Solusi, klik kanan proyek Anda dan pilih Kelola Paket NuGet.
    2. Pilih "nuget.org" sebagai sumber Paket.
    3. Pilih tab Telusuri.
    4. Cari Microsoft.ML.
    5. Pilih Microsoft.ML dari daftar paket dan pilih versi 1.5.2 dari menu dropdown Versi .
    6. Pilih tombol Instal.
    7. Pilih tombol OK pada dialog Pratinjau Perubahan lalu pilih tombol Saya Terima pada dialog Penerimaan Lisensi jika Anda setuju dengan ketentuan lisensi untuk paket yang tercantum.

    Ulangi langkah-langkah ini untuk Microsoft.ML.TimeSeries versi 1.5.2.

  5. Tambahkan arahan using berikut di bagian atas file Program.cs Anda:

    using Microsoft.ML;
    using Microsoft.ML.TimeSeries;
    using PhoneCallsAnomalyDetection;
    

Mengunduh data Anda

  1. Unduh himpunan data dan simpan ke folder Data yang sebelumnya Anda buat:

    Klik kanan pada phone-calls.csv dan pilih "Simpan Tautan (atau Target) Sebagai..."

    Pastikan Anda menyimpan file *.csv ke folder Data , atau setelah Anda menyimpannya di tempat lain, pindahkan file *.csv ke folder Data .

  2. Di Penjelajah Solusi, klik kanan file *.csv dan pilih properti . Di bawah Tingkat Lanjut, ubah nilai Salin ke Direktori Output ke Salin jika yang lebih baru.

Tabel berikut adalah tampilan awal data dari file.csv Anda:

stempel waktu nilai
2018/9/3 36.69670857
2018/9/4 35.74160571
..... .....
2018/10/3 34.49893429
... ....

File ini mewakili rangkaian waktu. Setiap baris dalam file adalah titik data. Setiap titik data memiliki dua atribut, yaitu, timestamp dan value, untuk mewakili jumlah panggilan telepon setiap hari. Jumlah panggilan telepon diubah untuk mengurangi sensitivitas data.

Membuat kelas dan menentukan jalur

Selanjutnya, tentukan struktur data kelas input dan prediksi Anda.

Tambahkan kelas baru ke proyek Anda:

  1. PadaPenjelajah Solusi, klik kanan pada proyek, lalu pilih Tambahkan Item Baru.

  2. Dalam kotak dialog Tambahkan Item Baru , pilih Kelas dan ubah bidang Nama menjadi PhoneCallsData.cs. Kemudian, pilih Tambahkan.

    File PhoneCallsData.cs terbuka di editor kode.

  3. Tambahkan arahan using berikut ke bagian atas PhoneCallsData.cs:

    using Microsoft.ML.Data;
    
  4. Hapus definisi kelas yang ada dan tambahkan kode berikut, yang memiliki dua kelas PhoneCallsData dan PhoneCallsPrediction, ke file PhoneCallsData.cs:

    public class PhoneCallsData
    {
        [LoadColumn(0)]
        public string? timestamp;
    
        [LoadColumn(1)]
        public double value;
    }
    
    public class PhoneCallsPrediction
    {
        // Vector to hold anomaly detection results, including isAnomaly, anomalyScore,
        // magnitude, expectedValue, boundaryUnits, upperBoundary and lowerBoundary.
        [VectorType(7)]
        public double[]? Prediction { get; set; }
    }
    

    PhoneCallsData menentukan kelas data input. Atribut LoadColumn menentukan kolom mana (menurut indeks kolom) dalam himpunan data yang harus dimuat. Ini memiliki dua atribut timestamp dan value yang sesuai dengan atribut yang sama dalam file data.

    PhoneCallsPrediction menentukan kelas data prediksi. Untuk detektor SR-CNN, prediksi tergantung pada mode deteksi ditentukan. Dalam sampel ini, Anda memilih mode AnomalyAndMargin. Output berisi tujuh kolom. Dalam kebanyakan kasus, IsAnomaly, ExpectedValue, UpperBoundary, dan LowerBoundary cukup informatif. Mereka memberi tahu Anda jika titik adalah anomali, nilai titik yang diharapkan, dan wilayah batas bawah dan atas titik tersebut.

  5. Tambahkan kode berikut ke baris tepat di bawah arahan using untuk menentukan jalur ke file data Anda:

    string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "phone-calls.csv");
    

Menginisialisasi variabel

  1. Ganti baris Console.WriteLine("Hello World!") dengan kode berikut untuk mendeklarasikan dan menginisialisasi variabel mlContext:

    MLContext mlContext = new MLContext();
    

    kelas MLContext adalah titik awal untuk semua operasi ML.NET, dan menginisialisasi membuat lingkungan ML.NET baru yang dapat dibagikan di seluruh objek alur kerja pembuatan model. Ini mirip, secara konseptual, untuk DBContext dalam Entity Framework.

Muat data

Data dalam ML.NET direpresentasikan sebagai antarmuka IDataView . IDataView adalah cara yang fleksibel dan efisien untuk menjelaskan data tabular (numerik dan teks). Data dapat dimuat dari file teks atau dari sumber lain (misalnya, database SQL atau file log) ke objek IDataView.

  1. Tambahkan kode berikut di bawah pembuatan variabel mlContext:

    IDataView dataView = mlContext.Data.LoadFromTextFile<PhoneCallsData>(path: _dataPath, hasHeader: true, separatorChar: ',');
    

    LoadFromTextFile() menentukan skema data dan baca dalam file. Menerima variabel jalur data dan mengembalikan IDataView.

Deteksi anomali rangkaian waktu

Deteksi anomali rangkaian waktu adalah proses mendeteksi outlier data rangkaian waktu; menunjuk pada rangkaian waktu input tertentu di mana perilaku tidak seperti yang diharapkan, atau "aneh". Anomali ini biasanya mengindikasikan beberapa peristiwa yang menarik dalam domain masalah: serangan cyber pada akun pengguna, pemadaman listrik, meledaknya RPS di server, kebocoran memori, dll.

Untuk menemukan anomali pada rangkaian waktu, Anda harus terlebih dahulu menentukan periode seri. Kemudian, rangkaian waktu dapat diurai menjadi beberapa komponen seperti Y = T + S + R, di mana Y adalah seri asli, T adalah komponen tren, S adalah komponen musiman, dan R adalah komponen sisa dari seri. Langkah ini disebut dekomposisi . Akhirnya, deteksi dilakukan pada komponen residu untuk menemukan anomali. Dalam ML.NET, algoritma SR-CNN adalah algoritma canggih dan baru yang didasarkan pada Spectral Residual (SR) dan Convolutional Neural Network (CNN) untuk mendeteksi anomali pada rangkaian waktu. Untuk informasi selengkapnya tentang algoritma ini, lihat Time-Series Layanan Deteksi Anomali di Microsoft.

Dalam tutorial ini, Anda akan melihat bahwa prosedur ini dapat diselesaikan menggunakan dua fungsi.

Deteksi Periode

Pada langkah pertama, Anda memanggil fungsi DetectSeasonality untuk menentukan periode seri.

Membuat metode DetectPeriod

  1. Buat metode DetectPeriod di bagian bawah file Program.cs menggunakan kode berikut:

    int DetectPeriod(MLContext mlContext, IDataView phoneCalls)
    {
    
    }
    
  2. Gunakan fungsi DetectSeasonality untuk mendeteksi periode. Tambahkan ke metode DetectPeriod dengan kode berikut:

    int period = mlContext.AnomalyDetection.DetectSeasonality(phoneCalls, nameof(PhoneCallsData.value));
    
  3. Tampilkan nilai periode dengan menambahkan yang berikut ini sebagai baris kode berikutnya dalam metode DetectPeriod:

    Console.WriteLine($"Period of the series is: {period}.");
    
  4. Kembalikan nilai periode.

    // <SnippetSetupSrCnnParameters>
    
  5. Tambahkan panggilan berikut ke metode DetectPeriod di bawah panggilan ke metode LoadFromTextFile():

    int period = DetectPeriod(mlContext, dataView);
    

Hasil pendeteksian siklus

Jalankan aplikasi. Hasil Anda harus mirip dengan yang berikut ini.

Period of the series is: 7.

Mendeteksi Anomali

Dalam langkah ini, Anda menggunakan metode DetectEntireAnomalyBySrCnn untuk menemukan anomali.

Buat metode DetectAnomaly

  1. Buat metode DetectAnomaly, tepat di bawah metode DetectPeriod, menggunakan kode berikut:

    void DetectAnomaly(MLContext mlContext, IDataView phoneCalls, int period)
    {
    
    }
    
  2. Siapkan SrCnnEntireAnomalyDetectorOptions dalam metode DetectAnomaly dengan kode berikut:

    var options = new SrCnnEntireAnomalyDetectorOptions()
    {
        Threshold = 0.3,
        Sensitivity = 64.0,
        DetectMode = SrCnnDetectMode.AnomalyAndMargin,
        Period = period,
    };
    
  3. Deteksi anomali dengan algoritma SR-CNN dengan menambahkan baris kode berikut dalam metode DetectAnomaly:

    var outputDataView = mlContext.AnomalyDetection.DetectEntireAnomalyBySrCnn(phoneCalls, nameof(PhoneCallsPrediction.Prediction), nameof(PhoneCallsData.value), options);
    
  4. Konversi tampilan data output menjadi IEnumerable yang ditik dengan kuat untuk tampilan yang lebih mudah menggunakan metode CreateEnumerable dengan kode berikut:

    var predictions = mlContext.Data.CreateEnumerable<PhoneCallsPrediction>(
        outputDataView, reuseRowObject: false);
    
  5. Buat header tampilan dengan kode berikut sebagai baris berikutnya dalam metode DetectAnomaly:

    Console.WriteLine("Index,Data,Anomaly,AnomalyScore,Mag,ExpectedValue,BoundaryUnit,UpperBoundary,LowerBoundary");
    

    Anda akan menampilkan informasi berikut dalam hasil deteksi titik perubahan:

    • Index adalah indeks dari setiap titik.
    • Anomaly adalah indikator apakah setiap titik terdeteksi sebagai anomali.
    • ExpectedValue adalah perkiraan nilai dari setiap titik.
    • LowerBoundary adalah nilai minimum yang harus dimiliki setiap titik agar tidak dianggap sebagai anomali.
    • UpperBoundary adalah nilai tertinggi setiap titik agar tidak dianggap sebagai anomali.
  6. Iterasi melalui predictionsIEnumerable dan tampilkan hasilnya dengan kode berikut:

    var index = 0;
    
    foreach (var p in predictions)
    {
        if (p.Prediction is not null)
        {
            string output;
            if (p.Prediction[0] == 1)
                output = "{0},{1},{2},{3},{4},  <-- alert is on! detected anomaly";
            else
                output = "{0},{1},{2},{3},{4}";
    
            Console.WriteLine(output, index, p.Prediction[0], p.Prediction[3], p.Prediction[5], p.Prediction[6]);
        }
        ++index;
    }
    
    Console.WriteLine("");
    
  7. Tambahkan panggilan berikut ke metode DetectAnomaly di bawah panggilan metode DetectPeriod():

    DetectAnomaly(mlContext, dataView, period);
    

Hasil deteksi anomali

Jalankan aplikasi. Hasil Anda harus mirip dengan yang berikut ini. Selama pemrosesan, pesan ditampilkan. Anda mungkin melihat peringatan atau memproses pesan. Beberapa pesan telah dihapus dari hasil berikut untuk kejelasan.

Detect period of the series
Period of the series is: 7.
Detect anomaly points in the series
Index   Data    Anomaly AnomalyScore    Mag     ExpectedValue   BoundaryUnit    UpperBoundary   LowerBoundary
0,0,36.841787256739266,41.14206982401966,32.541504689458876
1,0,35.67303618137362,39.97331874865401,31.372753614093227
2,0,34.710132999891826,39.029491313022824,30.390774686760828
3,0,33.44765248883495,37.786086547816545,29.10921842985335
4,0,28.937110922276364,33.25646923540736,24.61775260914537
5,0,5.143895892785781,9.444178460066171,0.843613325505391
6,0,5.163325228419392,9.463607795699783,0.8630426611390014
7,0,36.76414836240396,41.06443092968435,32.46386579512357
8,0,35.77908590657007,40.07936847385046,31.478803339289676
9,0,34.547259536635245,38.847542103915636,30.246976969354854
10,0,33.55193524820608,37.871293561337076,29.23257693507508
11,0,29.091800129624648,33.392082696905035,24.79151756234426
12,0,5.154836630338823,9.455119197619213,0.8545540630584334
13,0,5.234332502492464,9.534615069772855,0.934049935212073
14,0,36.54992549471526,40.85020806199565,32.24964292743487
15,0,35.79526470980883,40.095547277089224,31.494982142528443
16,0,34.34099013096804,38.64127269824843,30.040707563687647
17,0,33.61201516582131,37.9122977331017,29.31173259854092
18,0,29.223563320561812,33.5238458878422,24.923280753281425
19,0,5.170512168851533,9.470794736131923,0.8702296015711433
20,0,5.2614938889462834,9.561776456226674,0.9612113216658926
21,0,36.37103858487317,40.67132115215356,32.07075601759278
22,0,35.813544599026855,40.113827166307246,31.513262031746464
23,0,34.05600492733225,38.356287494612644,29.755722360051863
24,0,33.65828319077884,37.95856575805923,29.358000623498448
25,0,29.381125690882463,33.681408258162854,25.080843123602072
26,0,5.261543539820418,9.561826107100808,0.9612609725400283
27,0,5.4873712582971805,9.787653825577571,1.1870886910167897
28,1,36.504694001629254,40.804976568909645,32.20441143434886  <-- alert is on, detected anomaly
...

Selamat! Anda sekarang telah berhasil membangun model pembelajaran mesin untuk mendeteksi periode dan anomali pada seri berkala.

Anda dapat menemukan kode sumber untuk tutorial ini di repositori dotnet/samples .

Dalam tutorial ini, Anda belajar cara:

  • Muat data
  • Mendeteksi periode pada data rangkaian waktu
  • Mendeteksi anomali pada data rangkaian waktu

Langkah berikutnya

Lihat repositori GitHub sampel Pembelajaran Mesin untuk menjelajahi sampel Deteksi Anomali Konsumsi Daya.