// This example shows spike detection as above, but demonstrates how to train a model // that can run predictions on streaming data, and how to persist the trained model and then re-load it. public static void SsaSpikeDetectorPrediction() { // 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 recurring pattern const int SeasonalitySize = 5; const int TrainingSeasons = 3; const int TrainingSize = SeasonalitySize * TrainingSeasons; var data = new List <SsaSpikeData>(); for (int i = 0; i < TrainingSeasons; i++) { for (int j = 0; j < SeasonalitySize; j++) { data.Add(new SsaSpikeData(j)); } } // Convert data to IDataView. var dataView = ml.Data.ReadFromEnumerable(data); // Setup IidSpikeDetector arguments var inputColumnName = nameof(SsaSpikeData.Value); var outputColumnName = nameof(SsaSpikePrediction.Prediction); var args = new SsaSpikeDetector.Arguments() { Source = inputColumnName, Name = outputColumnName, Confidence = 95, // The confidence for spike detection in the range [0, 100] PvalueHistoryLength = 8, // The size of the sliding window for computing the p-value; shorter windows are more sensitive to spikes. TrainingWindowSize = TrainingSize, // The number of points from the beginning of the sequence used for training. SeasonalWindowSize = SeasonalitySize + 1 // An upper bound on the largest relevant seasonality in the input time series." }; // Train the change point detector. ITransformer model = new SsaSpikeEstimator(ml, args).Fit(dataView); // Create a prediction engine from the model for feeding new data. var engine = model.CreateTimeSeriesPredictionFunction <SsaSpikeData, SsaSpikePrediction>(ml); // Start streaming new data points with no change point to the prediction engine. Console.WriteLine($"Output from spike predictions on new data:"); Console.WriteLine("Data\tAlert\tScore\tP-Value"); SsaSpikePrediction prediction = null; for (int j = 0; j < 2; j++) { for (int i = 0; i < 5; i++) { var value = i; prediction = engine.Predict(new SsaSpikeData(value)); Console.WriteLine("{0}\t{1}\t{2:0.00}\t{3:0.00}", value, prediction.Prediction[0], prediction.Prediction[1], prediction.Prediction[2]); } } // Now send a data point that reflects a spike. var newValue = 100; prediction = engine.Predict(new SsaSpikeData(newValue)); Console.WriteLine("{0}\t{1}\t{2:0.00}\t{3:0.00}", newValue, prediction.Prediction[0], prediction.Prediction[1], prediction.Prediction[2]); // Now we demonstrate saving and loading the model. // Save the model that exists within the prediction engine. // The engine has been updating this model with every new data point. var modelPath = "model.zip"; engine.CheckPoint(ml, modelPath); // Load the model. using (var file = File.OpenRead(modelPath)) model = TransformerChain.LoadFrom(ml, file); // We must create a new prediction engine from the persisted model. engine = model.CreateTimeSeriesPredictionFunction <SsaSpikeData, SsaSpikePrediction>(ml); // Run predictions on the loaded model. for (int i = 0; i < 5; i++) { var value = i; prediction = engine.Predict(new SsaSpikeData(value)); Console.WriteLine("{0}\t{1}\t{2:0.00}\t{3:0.00}", value, prediction.Prediction[0], prediction.Prediction[1], prediction.Prediction[2]); } // Output from spike predictions on new data: // Data Alert Score P-Value // 0 0 - 1.01 0.50 // 1 0 - 0.24 0.22 // 2 0 - 0.31 0.30 // 3 0 0.44 0.01 // 4 0 2.16 0.00 // 0 0 - 0.78 0.27 // 1 0 - 0.80 0.30 // 2 0 - 0.84 0.31 // 3 0 0.33 0.31 // 4 0 2.21 0.07 // 100 1 86.17 0.00 <-- alert is on, predicted spike // 0 0 - 2.74 0.40 <-- saved to disk, re-loaded, and running new predictions // 1 0 - 1.47 0.42 // 2 0 - 17.50 0.24 // 3 0 - 30.82 0.16 // 4 0 - 23.24 0.28 }
private static void PrintPrediction(float value, SsaSpikePrediction prediction) => Console.WriteLine("{0}\t{1}\t{2:0.00}\t{3:0.00}", value, prediction.Prediction[0], prediction.Prediction[1], prediction.Prediction[2]);