File: Dynamic\Transforms\TimeSeries\DetectIidChangePoint.cs
Web Access
Project: src\docs\samples\Microsoft.ML.Samples\Microsoft.ML.Samples.csproj (Microsoft.ML.Samples)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.ML;
using Microsoft.ML.Data;
using Microsoft.ML.Transforms.TimeSeries;
 
namespace Samples.Dynamic
{
    public static class DetectIidChangePoint
    {
        // This example creates a time series (list of Data with the i-th element
        // corresponding to the i-th time slot). The estimator is applied then to
        // identify points where data distribution changed.
        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 ml = new MLContext();
 
            // Generate sample series data with a change
            const int Size = 16;
            var data = new List<TimeSeriesData>(Size)
            {
                new TimeSeriesData(5),
                new TimeSeriesData(5),
                new TimeSeriesData(5),
                new TimeSeriesData(5),
                new TimeSeriesData(5),
                new TimeSeriesData(5),
                new TimeSeriesData(5),
                new TimeSeriesData(5),
 
                //Change point data.
                new TimeSeriesData(7),
                new TimeSeriesData(7),
                new TimeSeriesData(7),
                new TimeSeriesData(7),
                new TimeSeriesData(7),
                new TimeSeriesData(7),
                new TimeSeriesData(7),
                new TimeSeriesData(7),
            };
 
            // Convert data to IDataView.
            var dataView = ml.Data.LoadFromEnumerable(data);
 
            // Setup IidSpikeDetector arguments
            string outputColumnName = nameof(ChangePointPrediction.Prediction);
            string inputColumnName = nameof(TimeSeriesData.Value);
 
            // Time Series model.
            ITransformer model = ml.Transforms.DetectIidChangePoint(
                outputColumnName, inputColumnName, 95.0d, Size / 4).Fit(dataView);
 
            // Create a time series prediction engine from the model.
            var engine = model.CreateTimeSeriesEngine<TimeSeriesData,
                ChangePointPrediction>(ml);
 
            Console.WriteLine($"{outputColumnName} column obtained " +
                $"post-transformation.");
 
            Console.WriteLine("Data\tAlert\tScore\tP-Value\tMartingale value");
 
            // Data Alert      Score   P-Value Martingale value
 
            // Create non-anomalous data and check for change point.
            for (int index = 0; index < 8; index++)
            {
                // Anomaly change point detection.
                PrintPrediction(5, engine.Predict(new TimeSeriesData(5)));
            }
 
            // 5       0       5.00    0.50    0.00       <-- Time Series 1.
            // 5       0       5.00    0.50    0.00
            // 5       0       5.00    0.50    0.00
            // 5       0       5.00    0.50    0.00
            // 5       0       5.00    0.50    0.00
            // 5       0       5.00    0.50    0.00
            // 5       0       5.00    0.50    0.00
            // 5       0       5.00    0.50    0.00
 
            // Change point
            PrintPrediction(7, engine.Predict(new TimeSeriesData(7)));
 
            // 7       1       7.00    0.00    10298.67   <-- alert is on, predicted changepoint (and model is checkpointed).
 
            // Checkpoint the model.
            var modelPath = "temp.zip";
            engine.CheckPoint(ml, modelPath);
 
            // Reference to current time series engine because in the next step
            // "engine" will point to the
            // checkpointed model being loaded from disk.
            var timeseries1 = engine;
 
            // Load the model.
            using (var file = File.OpenRead(modelPath))
                model = ml.Model.Load(file, out DataViewSchema schema);
 
            // Create a time series prediction engine from the checkpointed model.
            engine = model.CreateTimeSeriesEngine<TimeSeriesData,
                ChangePointPrediction>(ml);
 
            for (int index = 0; index < 8; index++)
            {
                // Anomaly change point detection.
                PrintPrediction(7, engine.Predict(new TimeSeriesData(7)));
            }
 
            // 7       0       7.00    0.13    33950.16   <-- Time Series 2 : Model loaded back from disk and prediction is made.
            // 7       0       7.00    0.26    60866.34
            // 7       0       7.00    0.38    78362.04
            // 7       0       7.00    0.50    0.01
            // 7       0       7.00    0.50    0.00
            // 7       0       7.00    0.50    0.00
            // 7       0       7.00    0.50    0.00
 
            // Prediction from the original time series engine should match the
            // prediction from check pointed model.
            engine = timeseries1;
            for (int index = 0; index < 8; index++)
            {
                // Anomaly change point detection.
                PrintPrediction(7, engine.Predict(new TimeSeriesData(7)));
            }
 
            // 7       0       7.00    0.13    33950.16   <-- Time Series 1 and prediction is made.
            // 7       0       7.00    0.26    60866.34
            // 7       0       7.00    0.38    78362.04
            // 7       0       7.00    0.50    0.01
            // 7       0       7.00    0.50    0.00
            // 7       0       7.00    0.50    0.00
            // 7       0       7.00    0.50    0.00
        }
 
        private static void PrintPrediction(float value, ChangePointPrediction
            prediction) =>
            Console.WriteLine("{0}\t{1}\t{2:0.00}\t{3:0.00}\t{4:0.00}", value,
            prediction.Prediction[0], prediction.Prediction[1],
            prediction.Prediction[2], prediction.Prediction[3]);
 
        class ChangePointPrediction
        {
            [VectorType(4)]
            public double[] Prediction { get; set; }
        }
 
        class TimeSeriesData
        {
            public float Value;
 
            public TimeSeriesData(float value)
            {
                Value = value;
            }
        }
    }
}