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
Visual Studio 2022 dengan beban kerja ".NET Desktop Development" terinstal.
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
Buat Aplikasi Konsol C# yang disebut "ProductSalesAnomalyDetection". Klik tombol Berikutnya.
Pilih .NET 6 sebagai kerangka kerja yang akan digunakan. Klik tombol Buat.
Buat direktori bernama Data dalam proyek Anda untuk menyimpan file himpunan data Anda.
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.
Tambahkan pernyataan berikut
using
di bagian atas file Program.cs Anda:using Microsoft.ML; using ProductSalesAnomalyDetection;
Unduh data Anda
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 .
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:
Di Penjelajah Solusi, klik kanan proyek, lalu pilih Tambahkan > Item Baru.
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.
Tambahkan pernyataan berikut
using
ke bagian atas ProductSalesData.cs:using Microsoft.ML.Data;
Hapus definisi kelas yang ada dan tambahkan kode berikut, yang memiliki dua kelas
ProductSalesData
danProductSalesPrediction
, 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.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 menghitungpvalueHistoryLength
.
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
Console.WriteLine("Hello World!")
Ganti baris dengan kode berikut untuk mendeklarasikan dan menginisialisasimlContext
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, keDBContext
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.
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?".
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 ProductSalesData
kosong .
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:
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.
DetectSpike()
Buat metode di bagian bawah file Program.cs menggunakan kode berikut:DetectSpike(MLContext mlContext, int docSize, IDataView productSales) { }
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);
Buat transformasi deteksi lonjakan dengan menambahkan yang berikut ini sebagai baris kode berikutnya dalam
DetectSpike()
metode :Tip
Parameter
confidence
danpvalueHistoryLength
memengaruhi bagaimana lonjakan terdeteksi.confidence
menentukan seberapa sensitif model Anda terhadap lonjakan. Semakin rendah kepercayaan diri, semakin besar kemungkinan algoritma mendeteksi lonjakan "lebih kecil". ParameterpvalueHistoryLength
menentukan jumlah titik data dalam jendela geser. Nilai parameter ini biasanya merupakan persentase dari seluruh himpunan data. Semakin rendahpvalueHistoryLength
, semakin cepat model lupa lonjakan besar sebelumnya.ITransformer iidSpikeTransform = iidSpikeEstimator.Fit(CreateEmptyDataView(mlContext));
Tambahkan baris kode berikut untuk mengubah
productSales
data sebagai baris berikutnya dalamDetectSpike()
metode :IDataView transformedData = iidSpikeTransform.Transform(productSales);
Kode sebelumnya menggunakan metode Transform() untuk membuat prediksi untuk beberapa baris input himpunan data.
Konversikan Anda
transformedData
menjadi jenis yang kuatIEnumerable
untuk tampilan yang lebih mudah menggunakan metode CreateEnumerable() dengan kode berikut:var predictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(transformedData, reuseRowObject: false);
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.Score
ProductSales
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.
Gunakan kode berikut untuk melakukan iterasi melalui
predictions
IEnumerable
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("");
Tambahkan panggilan ke metode di
DetectSpike()
bawah panggilan keLoadFromTextFile()
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:
Membuat metode DetectChangepoint()
Metode menjalankan DetectChangepoint()
tugas-tugas berikut:
- Membuat transformasi dari estimator.
- Mendeteksi titik perubahan berdasarkan data penjualan historis.
- Menampilkan hasilnya.
DetectChangepoint()
Buat metode , tepat setelahDetectSpike()
deklarasi metode , menggunakan kode berikut:void DetectChangepoint(MLContext mlContext, int docSize, IDataView productSales) { }
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);
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));
Transform()
Gunakan metode untuk mengubah data dengan menambahkan kode berikut keDetectChangePoint()
:IDataView transformedData = iidChangePointTransform.Transform(productSales);
Seperti yang Anda lakukan sebelumnya, konversikan anda
transformedData
menjadi tipe yang kuatIEnumerable
untuk tampilan yang lebih mudah menggunakanCreateEnumerable()
metode dengan kode berikut:var predictions = mlContext.Data.CreateEnumerable<ProductSalesPrediction>(transformedData, reuseRowObject: false);
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.Score
ProductSales
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.
Ulangi
predictions
IEnumerable
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("");
Tambahkan panggilan berikut ke
DetectChangepoint()
metode setelah panggilan keDetectSpike()
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.