Bagikan melalui


Tutorial: Mendeteksi anomali dalam penjualan produk dengan ML.NET

Pelajari cara membuat aplikasi deteksi anomali untuk data penjualan produk. Tutorial ini membuat aplikasi konsol .NET Core menggunakan C# di Visual Studio.

Dalam tutorial ini, Anda akan mempelajari cara:

  • Muat data
  • Membuat transformasi untuk deteksi anomali lonjakan
  • Mendeteksi anomali lonjakan dengan transformasi
  • Membuat transformasi untuk deteksi anomali titik perubahan
  • Mendeteksi anomali titik perubahan dengan transformasi

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

Prasyarat

Catatan

Format data di product-sales.csv didasarkan pada himpunan data "Penjualan Sampo Selama Periode Tiga Tahun" yang awalnya bersumber dari DataMarket dan disediakan oleh Time Series Data Library (TSDL), yang dibuat oleh Rob Hyndman. Himpunan Data "Penjualan Sampo Selama Periode Tiga Tahun" Dilisensikan Di Bawah Lisensi Terbuka Default DataMarket.

Membuat aplikasi konsol

  1. Buat Aplikasi Konsol C# yang disebut "ProductSalesAnomalyDetection". Klik tombol Berikutnya.

  2. Pilih .NET 6 sebagai kerangka kerja yang akan digunakan. Klik tombol Buat.

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

  4. Instal Paket Microsoft.ML NuGet:

    Catatan

    Sampel ini menggunakan versi stabil terbaru dari paket NuGet yang disebutkan kecuali dinyatakan lain.

    Di Penjelajah Solusi, klik kanan proyek Anda dan pilih Kelola Paket NuGet. Pilih "nuget.org" sebagai sumber Paket, pilih tab Telusuri, cari Microsoft.ML dan pilih tombol Instal . 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.

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

    using Microsoft.ML;
    using ProductSalesAnomalyDetection;
    

Unduh data Anda

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

    • Klik kanan padaproduct-sales.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 menjadi Salin jika lebih baru.

Tabel berikut ini adalah pratinjau data dari file *.csv Anda:

Bulan ProductSales
1-Jan 271
2-Jan 150.9
..... .....
1-Feb 199,3
..... .....

Membuat kelas dan menentukan jalur

Selanjutnya, tentukan struktur data kelas input dan prediksi Anda.

Tambahkan kelas baru ke proyek Anda:

  1. Di Penjelajah Solusi, klik kanan proyek, lalu pilih Tambahkan > Item Baru.

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

    File ProductSalesData.cs terbuka di editor kode.

  3. Tambahkan pernyataan berikut using ke bagian atas ProductSalesData.cs:

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

    public class ProductSalesData
    {
        [LoadColumn(0)]
        public string? Month;
    
        [LoadColumn(1)]
        public float numSales;
    }
    
    public class ProductSalesPrediction
    {
        //vector to hold alert,score,p-value values
        [VectorType(3)]
        public double[]? Prediction { get; set; }
    }
    

    ProductSalesData menentukan kelas data input. Atribut LoadColumn menentukan kolom mana (menurut indeks kolom) dalam himpunan data yang harus dimuat.

    ProductSalesPrediction menentukan kelas data prediksi. Untuk deteksi anomali, prediksi terdiri dari pemberitahuan untuk menunjukkan apakah ada anomali, skor mentah, dan nilai p. Semakin dekat nilai p menjadi 0, semakin besar kemungkinan anomali telah terjadi.

  5. Buat dua bidang global untuk menyimpan jalur file himpunan data yang baru diunduh dan jalur file model yang disimpan:

    • _dataPath memiliki jalur ke himpunan data yang digunakan untuk melatih model.
    • _docsize memiliki jumlah rekaman dalam file himpunan data. Anda akan menggunakan _docSize untuk menghitung pvalueHistoryLength.
  6. Tambahkan kode berikut ke baris tepat di bawah pernyataan penggunaan untuk menentukan jalur tersebut:

    string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "product-sales.csv");
    //assign the Number of records in dataset file to constant variable
    const int _docsize = 36;
    

Inisialisasi variabel

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

    MLContext mlContext = new MLContext();
    

    Kelas MLContext adalah titik awal untuk semua operasi ML.NET, dan menginisialisasi mlContext membuat lingkungan ML.NET baru yang dapat dibagikan di seluruh objek alur kerja pembuatan model. Ini mirip, secara konseptual, ke DBContext dalam Kerangka Kerja Entitas.

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 IDataView objek.

  1. Tambahkan kode berikut setelah membuat mlContext variabel:

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

    LoadFromTextFile() mendefinisikan skema data dan membaca dalam file. Dibutuhkan variabel jalur data dan mengembalikan IDataView.

Deteksi anomali rangkaian waktu

Deteksi anomali menandai kejadian atau perilaku yang tidak terduga atau tidak biasa. Ini memberikan petunjuk di mana mencari masalah dan membantu Anda menjawab pertanyaan "Apakah ini aneh?".

Contoh deteksi anomali

Deteksi anomali adalah proses mendeteksi outlier data rangkaian waktu; menunjuk pada rangkaian waktu input tertentu di mana perilaku tidak seperti yang diharapkan, atau "aneh".

Deteksi anomali dapat berguna dalam banyak cara. Contohnya:

Jika Anda memiliki mobil, Anda mungkin ingin tahu: Apakah pembacaan alat ukur oli ini normal, atau apakah saya memiliki kebocoran? Jika Anda memantau konsumsi daya, Anda ingin tahu: Apakah ada pemadaman?

Ada dua jenis anomali rangkaian waktu yang dapat dideteksi:

  • Lonjakan menunjukkan ledakan sementara perilaku anomali dalam sistem.

  • Titik perubahan menunjukkan awal perubahan persisten dari waktu ke waktu dalam sistem.

Dalam ML.NET, algoritma Deteksi Lonjakan IID atau Deteksi titik Perubahan IID cocok untuk himpunan data independen dan terdistribusi secara identik. Mereka berasumsi bahwa data input Anda adalah urutan titik data yang diambil sampelnya secara independen dari satu distribusi stasium.

Tidak seperti model dalam tutorial lain, detektor anomali rangkaian waktu berubah beroperasi langsung pada data input. Metode IEstimator.Fit() ini tidak memerlukan data pelatihan untuk menghasilkan transformasi. Namun, Skema data diperlukan, yang disediakan oleh tampilan data yang dihasilkan dari daftar ProductSalesDatakosong .

Anda akan menganalisis data penjualan produk yang sama untuk mendeteksi lonjakan dan titik perubahan. Proses membangun dan melatih model sama untuk deteksi lonjakan dan deteksi titik perubahan; perbedaan utamanya adalah algoritma deteksi spesifik yang digunakan.

Deteksi lonjakan

Tujuan deteksi lonjakan adalah untuk mengidentifikasi ledakan tiba-tiba namun sementara yang secara signifikan berbeda dari sebagian besar nilai data rangkaian waktu. Penting untuk mendeteksi item, peristiwa, atau pengamatan langka yang mencurigakan ini secara tepat waktu untuk diminimalkan. Pendekatan berikut dapat digunakan untuk mendeteksi berbagai anomali seperti: pemadaman, serangan cyber, atau konten web viral. Gambar berikut adalah contoh lonjakan dalam himpunan data rangkaian waktu:

Cuplikan layar yang memperlihatkan dua deteksi lonjakan.

Menambahkan metode CreateEmptyDataView()

Tambahkan metode berikut ke Program.cs:

IDataView CreateEmptyDataView(MLContext mlContext) {
    // Create empty DataView. We just need the schema to call Fit() for the time series transforms
    IEnumerable<ProductSalesData> enumerableData = new List<ProductSalesData>();
    return mlContext.Data.LoadFromEnumerable(enumerableData);
}

CreateEmptyDataView() menghasilkan objek tampilan data kosong dengan skema yang benar untuk digunakan sebagai input ke IEstimator.Fit() metode .

Membuat metode DetectSpike()

Metode DetectSpike():

  • Membuat transformasi dari estimator.
  • Mendeteksi lonjakan berdasarkan data penjualan historis.
  • Menampilkan hasilnya.
  1. DetectSpike() Buat metode di bagian bawah file Program.cs menggunakan kode berikut:

    DetectSpike(MLContext mlContext, int docSize, IDataView productSales)
    {
    
    }
    
  2. Gunakan IidSpikeEstimator untuk melatih model untuk deteksi lonjakan. Tambahkan ke DetectSpike() metode dengan kode berikut:

    var iidSpikeEstimator = mlContext.Transforms.DetectIidSpike(outputColumnName: nameof(ProductSalesPrediction.Prediction), inputColumnName: nameof(ProductSalesData.numSales), confidence: 95d, pvalueHistoryLength: docSize / 4);
    
  3. Buat transformasi deteksi lonjakan dengan menambahkan yang berikut ini sebagai baris kode berikutnya dalam DetectSpike() metode :

    Tip

    Parameter confidence dan pvalueHistoryLength memengaruhi bagaimana lonjakan terdeteksi. confidence menentukan seberapa sensitif model Anda terhadap lonjakan. Semakin rendah kepercayaan diri, semakin besar kemungkinan algoritma mendeteksi lonjakan "lebih kecil". Parameter pvalueHistoryLength menentukan jumlah titik data dalam jendela geser. Nilai parameter ini biasanya merupakan persentase dari seluruh himpunan data. Semakin rendah pvalueHistoryLength, semakin cepat model lupa lonjakan besar sebelumnya.

    ITransformer iidSpikeTransform = iidSpikeEstimator.Fit(CreateEmptyDataView(mlContext));
    
  4. Tambahkan baris kode berikut untuk mengubah productSales data sebagai baris berikutnya dalam DetectSpike() metode :

    IDataView transformedData = iidSpikeTransform.Transform(productSales);
    

    Kode sebelumnya menggunakan metode Transform() untuk membuat prediksi untuk beberapa baris input himpunan data.

  5. Konversikan Anda transformedData menjadi jenis yang kuat IEnumerable untuk tampilan yang lebih mudah menggunakan metode CreateEnumerable() dengan kode berikut:

    var predictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(transformedData, reuseRowObject: false);
    
  6. Buat baris header tampilan menggunakan kode berikut Console.WriteLine() :

    Console.WriteLine("Alert\tScore\tP-Value");
    

    Anda akan menampilkan informasi berikut dalam hasil deteksi lonjakan Anda:

    • Alert menunjukkan pemberitahuan lonjakan untuk titik data tertentu.
    • ScoreProductSales adalah nilai untuk titik data tertentu dalam himpunan data.
    • P-Value "P" adalah singkatan dari probabilitas. Semakin dekat nilai p menjadi 0, semakin besar kemungkinan titik data adalah anomali.
  7. Gunakan kode berikut untuk melakukan iterasi melalui predictionsIEnumerable dan menampilkan hasilnya:

    foreach (var p in predictions)
    {
        if (p.Prediction is not null)
        {
            var results = $"{p.Prediction[0]}\t{p.Prediction[1]:f2}\t{p.Prediction[2]:F2}";
    
            if (p.Prediction[0] == 1)
            {
                results += " <-- Spike detected";
            }
    
            Console.WriteLine(results);
        }
    }
    Console.WriteLine("");
    
  8. Tambahkan panggilan ke metode di DetectSpike() bawah panggilan ke LoadFromTextFile() metode :

    DetectSpike(mlContext, _docsize, dataView);
    

Hasil deteksi lonjakan

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 temporary changes in pattern
=============== Training the model ===============
=============== End of training process ===============
Alert   Score   P-Value
0       271.00  0.50
0       150.90  0.00
0       188.10  0.41
0       124.30  0.13
0       185.30  0.47
0       173.50  0.47
0       236.80  0.19
0       229.50  0.27
0       197.80  0.48
0       127.90  0.13
1       341.50  0.00 <-- Spike detected
0       190.90  0.48
0       199.30  0.48
0       154.50  0.24
0       215.10  0.42
0       278.30  0.19
0       196.40  0.43
0       292.00  0.17
0       231.00  0.45
0       308.60  0.18
0       294.90  0.19
1       426.60  0.00 <-- Spike detected
0       269.50  0.47
0       347.30  0.21
0       344.70  0.27
0       445.40  0.06
0       320.90  0.49
0       444.30  0.12
0       406.30  0.29
0       442.40  0.21
1       580.50  0.00 <-- Spike detected
0       412.60  0.45
1       687.00  0.01 <-- Spike detected
0       480.30  0.40
0       586.30  0.20
0       651.90  0.14

Mengubah deteksi titik

Change points adalah perubahan persisten dalam distribusi nilai aliran peristiwa rangkaian waktu, seperti perubahan tingkat dan tren. Perubahan persisten ini berlangsung lebih lama daripada spikes dan dapat menunjukkan peristiwa bencana. Change points biasanya tidak terlihat oleh mata telanjang, tetapi dapat dideteksi dalam data Anda menggunakan pendekatan seperti dalam metode berikut. Gambar berikut adalah contoh deteksi titik perubahan:

Cuplikan layar yang memperlihatkan deteksi titik perubahan.

Membuat metode DetectChangepoint()

Metode menjalankan DetectChangepoint() tugas-tugas berikut:

  • Membuat transformasi dari estimator.
  • Mendeteksi titik perubahan berdasarkan data penjualan historis.
  • Menampilkan hasilnya.
  1. DetectChangepoint() Buat metode , tepat setelah DetectSpike() deklarasi metode , menggunakan kode berikut:

    void DetectChangepoint(MLContext mlContext, int docSize, IDataView productSales)
    {
    
    }
    
  2. Buat iidChangePointEstimator dalam DetectChangepoint() metode dengan kode berikut:

    var iidChangePointEstimator = mlContext.Transforms.DetectIidChangePoint(outputColumnName: nameof(ProductSalesPrediction.Prediction), inputColumnName: nameof(ProductSalesData.numSales), confidence: 95d, changeHistoryLength: docSize / 4);
    
  3. Seperti yang Anda lakukan sebelumnya, buat transformasi dari estimator dengan menambahkan baris kode berikut dalam DetectChangePoint() metode :

    Tip

    Deteksi titik perubahan terjadi dengan sedikit penundaan karena model perlu memastikan penyimpangan saat ini adalah perubahan persisten dan bukan hanya beberapa lonjakan acak sebelum membuat pemberitahuan. Jumlah penundaan ini sama dengan changeHistoryLength parameter . Dengan meningkatkan nilai parameter ini, mengubah pemberitahuan deteksi pada perubahan yang lebih persisten, tetapi trade-off akan menjadi penundaan yang lebih lama.

    var iidChangePointTransform = iidChangePointEstimator.Fit(CreateEmptyDataView(mlContext));
    
  4. Transform() Gunakan metode untuk mengubah data dengan menambahkan kode berikut ke DetectChangePoint():

    IDataView transformedData = iidChangePointTransform.Transform(productSales);
    
  5. Seperti yang Anda lakukan sebelumnya, konversikan anda transformedData menjadi tipe yang kuat IEnumerable untuk tampilan yang lebih mudah menggunakan CreateEnumerable()metode dengan kode berikut:

    var predictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(transformedData, reuseRowObject: false);
    
  6. Buat header tampilan dengan kode berikut sebagai baris berikutnya dalam DetectChangePoint() metode :

    Console.WriteLine("Alert\tScore\tP-Value\tMartingale value");
    

    Anda akan menampilkan informasi berikut dalam hasil deteksi titik perubahan:

    • Alert menunjukkan pemberitahuan titik perubahan untuk titik data tertentu.
    • ScoreProductSales adalah nilai untuk titik data tertentu dalam himpunan data.
    • P-Value "P" adalah singkatan dari probabilitas. Semakin dekat nilai P menjadi 0, semakin besar kemungkinan poin data adalah anomali.
    • Martingale value digunakan untuk mengidentifikasi seberapa "aneh" titik data, berdasarkan urutan nilai P.
  7. Ulangi predictionsIEnumerable melalui dan tampilkan hasilnya dengan kode berikut:

    foreach (var p in predictions)
    {
        if (p.Prediction is not null)
        {
            var results = $"{p.Prediction[0]}\t{p.Prediction[1]:f2}\t{p.Prediction[2]:F2}\t{p.Prediction[3]:F2}";
    
            if (p.Prediction[0] == 1)
            {
                results += " <-- alert is on, predicted changepoint";
            }
            Console.WriteLine(results);
        }
    }
    Console.WriteLine("");
    
  8. Tambahkan panggilan berikut ke DetectChangepoint()metode setelah panggilan ke DetectSpike() metode :

    DetectChangepoint(mlContext, _docsize, dataView);
    

Mengubah hasil deteksi titik

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 Persistent changes in pattern
=============== Training the model Using Change Point Detection Algorithm===============
=============== End of training process ===============
Alert   Score   P-Value Martingale value
0       271.00  0.50    0.00
0       150.90  0.00    2.33
0       188.10  0.41    2.80
0       124.30  0.13    9.16
0       185.30  0.47    9.77
0       173.50  0.47    10.41
0       236.80  0.19    24.46
0       229.50  0.27    42.38
1       197.80  0.48    44.23 <-- alert is on, predicted changepoint
0       127.90  0.13    145.25
0       341.50  0.00    0.01
0       190.90  0.48    0.01
0       199.30  0.48    0.00
0       154.50  0.24    0.00
0       215.10  0.42    0.00
0       278.30  0.19    0.00
0       196.40  0.43    0.00
0       292.00  0.17    0.01
0       231.00  0.45    0.00
0       308.60  0.18    0.00
0       294.90  0.19    0.00
0       426.60  0.00    0.00
0       269.50  0.47    0.00
0       347.30  0.21    0.00
0       344.70  0.27    0.00
0       445.40  0.06    0.02
0       320.90  0.49    0.01
0       444.30  0.12    0.02
0       406.30  0.29    0.01
0       442.40  0.21    0.01
0       580.50  0.00    0.01
0       412.60  0.45    0.01
0       687.00  0.01    0.12
0       480.30  0.40    0.08
0       586.30  0.20    0.03
0       651.90  0.14    0.09

Selamat! Anda sekarang telah berhasil membangun model pembelajaran mesin untuk mendeteksi lonjakan dan anomali titik perubahan dalam data penjualan.

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

Di tutorial ini, Anda akan mempelajari cara:

  • Muat data
  • Melatih model untuk deteksi anomali lonjakan
  • Mendeteksi anomali lonjakan dengan model terlatih
  • Melatih model untuk deteksi anomali titik perubahan
  • Mendeteksi anomali titik perubahan dengan mode terlatih

Langkah berikutnya

Lihat repositori GitHub sampel Pembelajaran Mesin untuk menjelajahi sampel deteksi anomali data musiman.