Skip to content

Forecasting model framework for time series. #1900

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Jun 3, 2019
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using Microsoft.ML;
using Microsoft.ML.Transforms.TimeSeries;
using Microsoft.ML.TimeSeries;

namespace Samples.Dynamic
{
public static class Forecasting
{
// This example creates a time series (list of Data with the i-th element corresponding to the i-th time slot) and then
// does forecasting.
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 recurring pattern
const int SeasonalitySize = 5;
var data = new List<TimeSeriesData>()
{
new TimeSeriesData(0),
new TimeSeriesData(1),
new TimeSeriesData(2),
new TimeSeriesData(3),
new TimeSeriesData(4),

new TimeSeriesData(0),
new TimeSeriesData(1),
new TimeSeriesData(2),
new TimeSeriesData(3),
new TimeSeriesData(4),

new TimeSeriesData(0),
new TimeSeriesData(1),
new TimeSeriesData(2),
new TimeSeriesData(3),
new TimeSeriesData(4),
};

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

// Setup arguments.
var inputColumnName = nameof(TimeSeriesData.Value);

// Instantiate the forecasting model.
var model = ml.Forecasting.AdaptiveSingularSpectrumSequenceModeler(inputColumnName, data.Count, SeasonalitySize + 1, SeasonalitySize,
1, AdaptiveSingularSpectrumSequenceModeler.RankSelectionMethod.Exact, null, SeasonalitySize / 2, false, false);

// Train.
model.Train(dataView);

// Forecast next five values.
var forecast = model.Forecast(5);
Console.WriteLine($"Forecasted values:");
Console.WriteLine("[{0}]", string.Join(", ", forecast));
// Forecasted values:
// [2.452744, 2.589339, 2.729183, 2.873005, 3.028931]

// Update with new observations.
dataView = ml.Data.LoadFromEnumerable(new List<TimeSeriesData>() { new TimeSeriesData(0), new TimeSeriesData(0), new TimeSeriesData(0), new TimeSeriesData(0) });
model.Update(dataView);

// Checkpoint.
ml.Model.SaveForecastingModel(model, "model.zip");

// Load the checkpointed model from disk.
var modelCopy = ml.Model.LoadForecastingModel<float>("model.zip");

// Forecast with the checkpointed model loaded from disk.
forecast = modelCopy.Forecast(5);
Console.WriteLine("[{0}]", string.Join(", ", forecast));
// [0.8681176, 0.8185108, 0.8069275, 0.84405, 0.9455081]

// Forecast with the original model(that was checkpointed to disk).
forecast = model.Forecast(5);
Console.WriteLine("[{0}]", string.Join(", ", forecast));
// [0.8681176, 0.8185108, 0.8069275, 0.84405, 0.9455081]

}

class TimeSeriesData
{
public float Value;

public TimeSeriesData(float value)
{
Value = value;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using Microsoft.ML;
using Microsoft.ML.Transforms.TimeSeries;
using Microsoft.ML.TimeSeries;

namespace Samples.Dynamic
{
public static class ForecastingWithConfidenceInternal
{
// This example creates a time series (list of Data with the i-th element corresponding to the i-th time slot) and then
// does forecasting.
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 recurring pattern
const int SeasonalitySize = 5;
var data = new List<TimeSeriesData>()
{
new TimeSeriesData(0),
new TimeSeriesData(1),
new TimeSeriesData(2),
new TimeSeriesData(3),
new TimeSeriesData(4),

new TimeSeriesData(0),
new TimeSeriesData(1),
new TimeSeriesData(2),
new TimeSeriesData(3),
new TimeSeriesData(4),

new TimeSeriesData(0),
new TimeSeriesData(1),
new TimeSeriesData(2),
new TimeSeriesData(3),
new TimeSeriesData(4),
};

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

// Setup arguments.
var inputColumnName = nameof(TimeSeriesData.Value);

// Instantiate forecasting model.
var model = ml.Forecasting.AdaptiveSingularSpectrumSequenceModeler(inputColumnName, data.Count, SeasonalitySize + 1, SeasonalitySize,
1, AdaptiveSingularSpectrumSequenceModeler.RankSelectionMethod.Exact, null, SeasonalitySize / 2, shouldComputeForecastIntervals: true, false);

// Train.
model.Train(dataView);

// Forecast next five values with confidence internal.
float[] forecast;
float[] confidenceIntervalLowerBounds;
float[] confidenceIntervalUpperBounds;
model.ForecastWithConfidenceIntervals(5, out forecast, out confidenceIntervalLowerBounds, out confidenceIntervalUpperBounds);
PrintForecastValuesAndIntervals(forecast, confidenceIntervalLowerBounds, confidenceIntervalUpperBounds);
// Forecasted values:
// [2.452744, 2.589339, 2.729183, 2.873005, 3.028931]
// Confidence intervals:
// [-0.2235315 - 5.12902] [-0.08777174 - 5.266451] [0.05076938 - 5.407597] [0.1925406 - 5.553469] [0.3469928 - 5.71087]

// Update with new observations.
dataView = ml.Data.LoadFromEnumerable(new List<TimeSeriesData>() { new TimeSeriesData(0), new TimeSeriesData(0), new TimeSeriesData(0), new TimeSeriesData(0) });
model.Update(dataView);

// Checkpoint.
ml.Model.SaveForecastingModel(model, "model.zip");

// Load the checkpointed model from disk.
var modelCopy = ml.Model.LoadForecastingModel<float>("model.zip");

// Forecast with the checkpointed model loaded from disk.
modelCopy.ForecastWithConfidenceIntervals(5, out forecast, out confidenceIntervalLowerBounds, out confidenceIntervalUpperBounds);
PrintForecastValuesAndIntervals(forecast, confidenceIntervalLowerBounds, confidenceIntervalUpperBounds);
// Forecasted values:
// [0.8681176, 0.8185108, 0.8069275, 0.84405, 0.9455081]
// Confidence intervals:
// [-1.808158 - 3.544394] [-1.8586 - 3.495622] [-1.871486 - 3.485341] [-1.836414 - 3.524514] [-1.736431 - 3.627447]

// Forecast with the original model(that was checkpointed to disk).
model.ForecastWithConfidenceIntervals(5, out forecast, out confidenceIntervalLowerBounds, out confidenceIntervalUpperBounds);
PrintForecastValuesAndIntervals(forecast, confidenceIntervalLowerBounds, confidenceIntervalUpperBounds);
// Forecasted values:
// [0.8681176, 0.8185108, 0.8069275, 0.84405, 0.9455081]
// Confidence intervals:
// [-1.808158 - 3.544394] [-1.8586 - 3.495622] [-1.871486 - 3.485341] [-1.836414 - 3.524514] [-1.736431 - 3.627447]
}

static void PrintForecastValuesAndIntervals(float[] forecast, float[] confidenceIntervalLowerBounds, float[] confidenceIntervalUpperBounds)
{
Console.WriteLine($"Forecasted values:");
Console.WriteLine("[{0}]", string.Join(", ", forecast));
Console.WriteLine($"Confidence intervals:");
for (int index = 0; index < forecast.Length; index++)
Console.Write($"[{confidenceIntervalLowerBounds[index]} - {confidenceIntervalUpperBounds[index]}] ");
Console.WriteLine();
}

class TimeSeriesData
{
public float Value;

public TimeSeriesData(float value)
{
Value = value;
}
}
}
}
6 changes: 6 additions & 0 deletions src/Microsoft.ML.Data/MLContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ public sealed class MLContext : IHostEnvironment
/// </summary>
public AnomalyDetectionCatalog AnomalyDetection { get; }

/// <summary>
/// Trainers and tasks specific to forecasting problems.
/// </summary>
public ForecastingCatalog Forecasting { get; }

/// <summary>
/// Data processing operations.
/// </summary>
Expand Down Expand Up @@ -89,6 +94,7 @@ public MLContext(int? seed = null)
Clustering = new ClusteringCatalog(_env);
Ranking = new RankingCatalog(_env);
AnomalyDetection = new AnomalyDetectionCatalog(_env);
Forecasting = new ForecastingCatalog(_env);
Transforms = new TransformsCatalog(_env);
Model = new ModelOperationsCatalog(_env);
Data = new DataOperationsCatalog(_env);
Expand Down
27 changes: 27 additions & 0 deletions src/Microsoft.ML.Data/TrainCatalog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -704,4 +704,31 @@ public AnomalyDetectionMetrics Evaluate(IDataView data, string labelColumnName =
return eval.Evaluate(data, labelColumnName, scoreColumnName, predictedLabelColumnName);
}
}

/// <summary>
/// Class used by <see cref="MLContext"/> to create instances of forecasting components.
/// </summary>
public sealed class ForecastingCatalog : TrainCatalogBase
{
/// <summary>
/// The list of trainers for performing forecasting.
/// </summary>
public Forecasters Trainers { get; }

internal ForecastingCatalog(IHostEnvironment env) : base(env, nameof(ForecastingCatalog))
{
Trainers = new Forecasters(this);
}

/// <summary>
/// Class used by <see cref="MLContext"/> to create instances of forecasting trainers.
/// </summary>
public sealed class Forecasters : CatalogInstantiatorBase
{
internal Forecasters(ForecastingCatalog catalog)
: base(catalog)
{
}
}
}
}
Loading