Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
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 DetectAnomalyBySrCnn
{
// 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 spiking points in the series.
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 an anomaly
var data = new List<TimeSeriesData>();
for (int index = 0; index < 20; index++)
{
data.Add(new TimeSeriesData(5));
}
data.Add(new TimeSeriesData(10));
for (int index = 0; index < 5; index++)
{
data.Add(new TimeSeriesData(5));
}

// Convert data to IDataView.
var dataView = ml.Data.LoadFromEnumerable(data);

// Setup the estimator arguments
string outputColumnName = nameof(SrCnnAnomalyDetection.Prediction);
string inputColumnName = nameof(TimeSeriesData.Value);

// The transformed model.
ITransformer model = ml.Transforms.DetectAnomalyBySrCnn(outputColumnName, inputColumnName, 16, 5, 5, 3, 8, 0.35).Fit(dataView);

// Create a time series prediction engine from the model.
var engine = model.CreateTimeSeriesPredictionFunction<TimeSeriesData, SrCnnAnomalyDetection>(ml);

Console.WriteLine($"{outputColumnName} column obtained post-transformation.");
Console.WriteLine("Data\tAlert\tScore\tMag");

// Prediction column obtained post-transformation.
// Data Alert Score Mag

// Create non-anomalous data and check for anomaly.
for (int index = 0; index < 20; index++)
{
// Anomaly detection.
PrintPrediction(5, engine.Predict(new TimeSeriesData(5)));
}

//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.03 0.18
//5 0 0.03 0.18
//5 0 0.03 0.18
//5 0 0.03 0.18
//5 0 0.03 0.18

// Anomaly.
PrintPrediction(10, engine.Predict(new TimeSeriesData(10)));

//10 1 0.47 0.93 <-- alert is on, predicted anomaly

// Checkpoint the model.
var modelPath = "temp.zip";
engine.CheckPoint(ml, modelPath);

// Load the model.
using (var file = File.OpenRead(modelPath))
model = ml.Model.Load(file, out DataViewSchema schema);

for (int index = 0; index < 5; index++)
{
// Anomaly detection.
PrintPrediction(5, engine.Predict(new TimeSeriesData(5)));
}

//5 0 0.31 0.50
//5 0 0.05 0.30
//5 0 0.01 0.23
//5 0 0.00 0.21
//5 0 0.01 0.25
}

private static void PrintPrediction(float value, SrCnnAnomalyDetection prediction) =>
Console.WriteLine("{0}\t{1}\t{2:0.00}\t{3:0.00}", value, prediction.Prediction[0],
prediction.Prediction[1], prediction.Prediction[2]);

private class TimeSeriesData
{
public float Value;

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

private class SrCnnAnomalyDetection
{
[VectorType(3)]
public double[] Prediction { get; set; }
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using Microsoft.ML;
using Microsoft.ML.Data;

namespace Samples.Dynamic
{
public static class DetectAnomalyBySrCnnBatchPrediction
{
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 an anomaly
var data = new List<TimeSeriesData>();
for (int index = 0; index < 20; index++)
{
data.Add(new TimeSeriesData(5));
}
data.Add(new TimeSeriesData(10));
for (int index = 0; index < 5; index++)
{
data.Add(new TimeSeriesData(5));
}

// Convert data to IDataView.
var dataView = ml.Data.LoadFromEnumerable(data);

// Setup the estimator arguments
string outputColumnName = nameof(SrCnnAnomalyDetection.Prediction);
string inputColumnName = nameof(TimeSeriesData.Value);

// The transformed data.
var transformedData = ml.Transforms.DetectAnomalyBySrCnn(outputColumnName, inputColumnName, 16, 5, 5, 3, 8, 0.35).Fit(dataView).Transform(dataView);

// Getting the data of the newly created column as an IEnumerable of SrCnnAnomalyDetection.
var predictionColumn = ml.Data.CreateEnumerable<SrCnnAnomalyDetection>(transformedData, reuseRowObject: false);

Console.WriteLine($"{outputColumnName} column obtained post-transformation.");
Console.WriteLine("Data\tAlert\tScore\tMag");

int k = 0;
foreach (var prediction in predictionColumn)
PrintPrediction(data[k++].Value, prediction);

//Prediction column obtained post-transformation.
//Data Alert Score Mag
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.00 0.00
//5 0 0.03 0.18
//5 0 0.03 0.18
//5 0 0.03 0.18
//5 0 0.03 0.18
//5 0 0.03 0.18
//10 1 0.47 0.93
//5 0 0.31 0.50
//5 0 0.05 0.30
//5 0 0.01 0.23
//5 0 0.00 0.21
//5 0 0.01 0.25
}

private static void PrintPrediction(float value, SrCnnAnomalyDetection prediction) =>
Console.WriteLine("{0}\t{1}\t{2:0.00}\t{3:0.00}", value, prediction.Prediction[0],
prediction.Prediction[1], prediction.Prediction[2]);

private class TimeSeriesData
{
public float Value;

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

private class SrCnnAnomalyDetection
{
[VectorType(3)]
public double[] Prediction { get; set; }
}
}
}
24 changes: 24 additions & 0 deletions src/Microsoft.ML.TimeSeries/ExtensionsCatalog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,5 +121,29 @@ public static SsaChangePointEstimator DetectChangePointBySsa(this TransformsCata
public static SsaSpikeEstimator DetectSpikeBySsa(this TransformsCatalog catalog, string outputColumnName, string inputColumnName, int confidence, int pvalueHistoryLength,
int trainingWindowSize, int seasonalityWindowSize, AnomalySide side = AnomalySide.TwoSided, ErrorFunction errorFunction = ErrorFunction.SignedDifference)
=> new SsaSpikeEstimator(CatalogUtils.GetEnvironment(catalog), outputColumnName, confidence, pvalueHistoryLength, trainingWindowSize, seasonalityWindowSize, inputColumnName, side, errorFunction);

/// <summary>
/// Create <see cref="SrCnnAnomalyEstimator"/>, which detects timeseries anomalies using SRCNN algorithm.
/// </summary>
/// <param name="catalog">The transform's catalog.</param>
/// <param name="outputColumnName">Name of the column resulting from the transformation of <paramref name="inputColumnName"/>.
/// The column data is a vector of <see cref="System.Double"/>. The vector contains 3 elements: alert (1 means anomaly while 0 means normal), raw score, and magnitude of spectual residual.</param>
/// <param name="inputColumnName">Name of column to transform. The column data must be <see cref="System.Single"/>.</param>
/// <param name="windowSize">The size of the sliding window for computing spectral residual.</param>
/// <param name="backAddWindowSize">The number of points to add back of training window. No more than windowSize, usually keep default value.</param>
/// <param name="lookaheadWindowSize">The number of pervious points used in prediction. No more than windowSize, usually keep default value.</param>
/// <param name="averageingWindowSize">The size of sliding window to generate a saliency map for the series. No more than windowSize, usually keep default value.</param>
/// <param name="judgementWindowSize">The size of sliding window to calculate the anomaly score for each data point. No more than windowSize.</param>
/// <param name="threshold">The threshold to determine anomaly, score larger than the threshold is considered as anomaly. Should be in (0,1)</param>
/// <example>
/// <format type="text/markdown">
/// <![CDATA[
/// [!code-csharp[DetectAnomalyBySrCnn](~/../docs/samples/docs/samples/Microsoft.ML.Samples/Dynamic/Transforms/TimeSeries/DetectAnomalyBySrCnn.cs)]
/// ]]>
/// </format>
/// </example>
public static SrCnnAnomalyEstimator DetectAnomalyBySrCnn(this TransformsCatalog catalog, string outputColumnName, string inputColumnName,
int windowSize=64, int backAddWindowSize=5, int lookaheadWindowSize=5, int averageingWindowSize=3, int judgementWindowSize=21, double threshold=0.3)
=> new SrCnnAnomalyEstimator(CatalogUtils.GetEnvironment(catalog), outputColumnName, windowSize, backAddWindowSize, lookaheadWindowSize, averageingWindowSize, judgementWindowSize, threshold, inputColumnName);
}
}
Loading