Home / Artikel / ML.NET Series: Deteksi Anomali Suhu

ML.NET Series: Deteksi Anomali Suhu

Hai rekan developer apa kabar ? Semoga di masa pandemi ini tetap bisa berpikir positif dan tetap semangat berkarya.

Image time series data example

Temen-temen pasti pernah ada pengalaman mengolah data time series, yaitu data point yang memiliki waktu, entah waktu saat direlease, waktu saat terjadi, atau waktu apapun. Data seperti ini contohnya adalah data jumlah kunjungan pasien, data pengukuran suhu, data penjualan dari tahun ke tahun, data kualitas udara, dsb.

Dengan ML.NET kita bisa mengolah data ini dengan 2 pendekatan yaitu :

  1. Prediksi, melakukan estimasi nilai selanjutnya berdasarkan data-data diwaktu terdahulu
  2. Deteksi Anomali, melakukan analisa jika terjadi peak, atau penurunan yang tidak normal terhadap data. Misal data sensor panas mencatatkan panas yang berlebihan pada mesin.

Kali ini kita akan mencoba fitur baru dari ML.NET 1.5.1 yaitu mendeteksi anomali dengan dataset secara keseluruhan dengan  DetectEntireAnomalyBySrCnn. Sebelumnya penulis pernah membahas juga deteksi anomali dengan DetectAnomalyBySrCnn yang mendeteksi anomali dalam sub bagian dataset saja misal bagian data yang diterima dari streaming data sensor.

Kelebihan dari algoritma yang baru ini adalah lebih cepat tapi membutuhkan memori lebih banyak karena semua dataset akan di load di memory.  Jika rekan-rekan tidak memiliki dataset secara keseluruhan gunakan saja algoritma deteksi anomali yang terdahulu pada post yang terdahulu.

Ikuti langkah berikut,

  1. pastikan rekan-rekan sudah install extension ML.NET dari sini : https://marketplace.visualstudio.com/items?itemName=MLNET.07
  2. Setelah itu buatlah project baru dengan tipe console .net core : file > new > project > Console App (.NET Core)
  3. Kemudian masukan kode berikut :
  4. using System;
    using System.Collections.Generic;
    using Microsoft.Data.Analysis;
    using Microsoft.ML;
    using Microsoft.ML.Data;
    using Microsoft.ML.TimeSeries;
    namespace DetectWeatherAnomaly
    {
        class Program
        {
            static void Main(string[] args)
            {
               
                // Create a new ML context, for ML.NET operations. It can be used for
                // exception tracking and logging, 
                // as well as the source of randomness.
                var ml = new MLContext();
    
                var ds = DataFrame.LoadCsv("../../../Dataset/weather.csv", ',', true);
                // Generate sample series data with an anomaly
                var data = new List<TimeSeriesData>();
                foreach (var dr in ds.Rows)
                {
                    data.Add(new TimeSeriesData { Value = Convert.ToDouble(dr[10]) });
    
                }
    
    
                // Convert data to IDataView.
                var dataView = ml.Data.LoadFromEnumerable(data);
    
                // Setup the detection arguments
                string outputColumnName = nameof(SrCnnAnomalyDetection.Prediction);
                string inputColumnName = nameof(TimeSeriesData.Value);
    
                // Do batch anomaly detection
                var outputDataView = ml.AnomalyDetection.DetectEntireAnomalyBySrCnn(dataView, outputColumnName, inputColumnName,
                    threshold: 0.35, batchSize: 512, sensitivity: 90.0, detectMode: SrCnnDetectMode.AnomalyAndMargin);
    
                // Getting the data of the newly created column as an IEnumerable of
                // SrCnnAnomalyDetection.
                var predictionColumn = ml.Data.CreateEnumerable<SrCnnAnomalyDetection>(
                    outputDataView, reuseRowObject: false);
    
                Console.WriteLine("Index\tData\tAnomaly\tAnomalyScore\tMag\tExpectedValue\tBoundaryUnit\tUpperBoundary\tLowerBoundary");
    
                int k = 0;
                foreach (var prediction in predictionColumn)
                {
                    PrintPrediction(k, data[k].Value, prediction);
                    k++;
                }
                //Index Data    Anomaly AnomalyScore    Mag ExpectedValue   BoundaryUnit UpperBoundary   LowerBoundary
                //0       5.00    0               0.00    0.21            5.00            5.00            5.01            4.99
                //25      5.00    0               0.00    0.19            5.00            5.00            5.01            4.99
            }
    
            private static void PrintPrediction(int idx, double value, SrCnnAnomalyDetection prediction) 
                {
                if (prediction.Prediction[0] == 0)
                    Console.ForegroundColor = ConsoleColor.White;
                else
                    Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("{0}\t{1:0.00}\t{2}\t\t{3:0.00}\t{4:0.00}\t\t{5:0.00}\t\t{6:0.00}\t\t{7:0.00}\t\t{8:0.00}",
                    idx, value, prediction.Prediction[0], prediction.Prediction[1], prediction.Prediction[2],
                    prediction.Prediction[3], prediction.Prediction[4], prediction.Prediction[5], prediction.Prediction[6]);
                }
            private class TimeSeriesData
            {
                public double Value { get; set; }
            }
    
            private class SrCnnAnomalyDetection
            {
                [VectorType]
                public double[] Prediction { get; set; }
            }
        
        }
    }
  5. datasetnya bisa di download dari sini : https://github.com/mifmasterz/MLNETSeries/tree/master/DetectWeatherAnomaly/DetectWeatherAnomaly/Dataset filenya : weather.csv
  6. Nah disitu rekan-rekan bisa lihat jika terjadi anomali warna font akan berwarna merah.

Seasonality

Kadang data time series yang kita miliki punya kecenderungan berulang sebagai contoh data penjualan saat lebaran atau tahun baru, biasanya diwaktu-waktu tersebut akan terjadi anomali yang sudah biasa, dan akhirnya tidak menjadi sesuatu yang kita kategorikan sebagai anomali lagi. Untuk itu ML.NET punya fitur seasonality detection yang bisa mendeteksi anomali yang berulang ini dan melakukan normalisasi agar tidak lagi di deteksi sebagai anomali, berikut adalah contohnya:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.ML;
using Microsoft.ML.TimeSeries;

namespace DetectWeatherAnomaly
{
    public class DetectSeasonality
    {
        public static void Example()
        {
            /* Create a new ML context, for ML.NET operations. It can be used for
             exception tracking and logging, as well as the source of randomness.*/
            var mlContext = new MLContext();

            // Create a seasonal data as input: y = sin(2 * Pi + x)
            var seasonalData = Enumerable.Range(0, 100).Select(x => new TimeSeriesData(Math.Sin(2 * Math.PI + x)));

            // Load the input data as a DataView.
            var dataView = mlContext.Data.LoadFromEnumerable(seasonalData);

            /* Two option parameters:
             * seasonalityWindowSize: Default value is -1. When set to -1, use the whole input to fit model; 
             * when set to a positive integer, only the first windowSize number of values will be considered.
             * randomnessThreshold: Randomness threshold that specifies how confidence the input values follows 
             * a predictable pattern recurring as seasonal data. By default, it is set as 0.99. 
             * The higher the threshold is set, the more strict recurring pattern the 
             * input values should follow to be determined as seasonal data.
             */
            int period = mlContext.AnomalyDetection.DetectSeasonality(
                dataView,
                nameof(TimeSeriesData.Value),
                seasonalityWindowSize: 40);

            // Print the Seasonality Period result.
            Console.WriteLine($"Seasonality Period: #{period}");
        }

        private class TimeSeriesData
        {
            public double Value;

            public TimeSeriesData(double value)
            {
                Value = value;
            }
        }
    }
}

Dan setelah kita sudah dapatkan titik-titik terjadinya anomali pada data kita, kita bisa analisa juga apa features yang menyebabkan anomali. Contohnya sebagai berikut:

using System;
using System.Collections.Generic;
using Microsoft.ML;
using Microsoft.ML.TimeSeries;

namespace DetectWeatherAnomaly
{
public class RootCauseDetect
{
// In the root cause detection input, this string identifies an aggregation as opposed to a dimension value"
private static string AGG_SYMBOL = "##SUM##";
public static void Example()
{
// Create a new ML context, for ML.NET operations. It can be used for
// exception tracking and logging, as well as the source of randomness.
var mlContext = new MLContext();

// Create an root cause localization input instance.
DateTime timestamp = GetTimestamp();
var data = new RootCauseLocalizationInput(timestamp, GetAnomalyDimension(), new List<MetricSlice>() { new MetricSlice(timestamp, GetPoints()) }, AggregateType.Sum, AGG_SYMBOL);

// Get the root cause localization result.
RootCause prediction = mlContext.AnomalyDetection.LocalizeRootCause(data);

// Print the localization result.
int count = 0;
foreach (RootCauseItem item in prediction.Items)
{
count++;
Console.WriteLine($"Root cause item #{count} ...");
Console.WriteLine($"Score: {item.Score}, Path: {String.Join(" ", item.Path)}, Direction: {item.Direction}, Dimension:{String.Join(" ", item.Dimension)}");
}

//Item #1 ...
//Score: 0.26670448876705927, Path: Lokasi, Direction: Up, Dimension:[Negara, UK] [JenisAlat, ##SUM##] [Lokasi, DC1]
}

private static List<TimeSeriesPoint> GetPoints()
{
List<TimeSeriesPoint> points = new List<TimeSeriesPoint>();

Dictionary<string, Object> dic1 = new Dictionary<string, Object>();
dic1.Add("Negara", "Garut");
dic1.Add("JenisAlat", "Laptop");
dic1.Add("Lokasi", "DC1");
points.Add(new TimeSeriesPoint(200, 100, true, dic1));

Dictionary<string, Object> dic2 = new Dictionary<string, Object>();
dic2.Add("Negara", "Garut");
dic2.Add("JenisAlat", "Mobile");
dic2.Add("Lokasi", "DC1");
points.Add(new TimeSeriesPoint(1000, 100, true, dic2));

Dictionary<string, Object> dic3 = new Dictionary<string, Object>();
dic3.Add("Negara", "Garut");
dic3.Add("JenisAlat", AGG_SYMBOL);
dic3.Add("Lokasi", "DC1");
points.Add(new TimeSeriesPoint(1200, 200, true, dic3));

Dictionary<string, Object> dic4 = new Dictionary<string, Object>();
dic4.Add("Negara", "Garut");
dic4.Add("JenisAlat", "Laptop");
dic4.Add("Lokasi", "DC2");
points.Add(new TimeSeriesPoint(100, 100, false, dic4));

Dictionary<string, Object> dic5 = new Dictionary<string, Object>();
dic5.Add("Negara", "Garut");
dic5.Add("JenisAlat", "Mobile");
dic5.Add("Lokasi", "DC2");
points.Add(new TimeSeriesPoint(200, 200, false, dic5));

Dictionary<string, Object> dic6 = new Dictionary<string, Object>();
dic6.Add("Negara", "Garut");
dic6.Add("JenisAlat", AGG_SYMBOL);
dic6.Add("Lokasi", "DC2");
points.Add(new TimeSeriesPoint(300, 300, false, dic6));

Dictionary<string, Object> dic7 = new Dictionary<string, Object>();
dic7.Add("Negara", "Garut");
dic7.Add("JenisAlat", AGG_SYMBOL);
dic7.Add("Lokasi", AGG_SYMBOL);
points.Add(new TimeSeriesPoint(1500, 500, true, dic7));

Dictionary<string, Object> dic8 = new Dictionary<string, Object>();
dic8.Add("Negara", "Garut");
dic8.Add("JenisAlat", "Laptop");
dic8.Add("Lokasi", AGG_SYMBOL);
points.Add(new TimeSeriesPoint(300, 200, true, dic8));

Dictionary<string, Object> dic9 = new Dictionary<string, Object>();
dic9.Add("Negara", "Garut");
dic9.Add("JenisAlat", "Mobile");
dic9.Add("Lokasi", AGG_SYMBOL);
points.Add(new TimeSeriesPoint(1200, 300, true, dic9));

return points;
}

private static Dictionary<string, Object> GetAnomalyDimension()
{
Dictionary<string, Object> dim = new Dictionary<string, Object>();
dim.Add("Negara", "Garut");
dim.Add("JenisAlat", AGG_SYMBOL);
dim.Add("Lokasi", AGG_SYMBOL);

return dim;
}

private static DateTime GetTimestamp()
{
return new DateTime(2020, 3, 23, 0, 0, 0);
}

}
}

Silakan rekan-rekan coba dengan data time series sendiri. Projectnya sendiri bisa rekan-rekan unduh disini : https://github.com/mifmasterz/MLNETSeries/tree/master/DetectWeatherAnomaly

Semoga bermanfaat dan selamat berkarya.

Salam developer

98 total views, 4 views today

About Muhammad Ibnu Fadhil

Penulis kode, pedagang aplikasi perkantoran, implementator integrasi sistem, memiliki UKM yaitu gravicode.com, mendirikan komunitas kecil gadgeteer Indonesia, mendedikasikan diri untuk membangun produk dan jasa yang bermanfaat untuk ummat terutama di bidang teknologi informasi.

Check Also

ML.NET Series: Membuat Model Klasifikasi Gambar dengan Model Builder

Hi Makers, Kali ini kita akan membahas bagaimana kita dapat membuat model ML untuk melakukan …