After 3/4 year into asp net, i'm trying since few weeks to learn ML.net but i'm having some trouble with forecasting time series.
Here is my main questions :
- I would like to predict price over the 7 next days but my data is not evenly distributed, how can i force the horizon to predict over the 7 next day and not just 7 occurrences ?
- Can i predict all 3 values ( unit price , price pack 10, price pack 100) in the same engine ?
- Each items getting their own "life"( the price of one item may go down while the other goes up) do i need to create a model for each item ?
- Even if my dataset is not big enough for now how can i get a beter prediction from these data ( result of the prediction at the end of post) ?
My final goal is to send to my ML core an item name with his current price ( unit, pack 10 ,pack 100) then the core predict an optimal sell price and date. Then with simple math i can choose to buy or not.
Here is all my process to build the model for times series prediction.
First, loading data.
string queryThisWeek = "SELECT * from Ressource where ressource ='" + ressourceToHandle.Ressource + "' and Date >= '" + startCurrentWeek + "' order by Date desc";
string queryBeforeThisWeek = "SELECT * from Ressource where ressource ='" + ressourceToHandle.Ressource + "' and Date < '" + startCurrentWeek + "' order by Date desc";
var connection = new SqliteConnection(ConnectionString);
var factory = DbProviderFactories.GetFactory(connection);
DatabaseSource dbSourceThisWeek = new DatabaseSource(factory, ConnectionString, queryThisWeek);
DatabaseSource dbSourceBeforeThisWeek = new DatabaseSource(factory, ConnectionString, queryBeforeThisWeek);
IDataView dataViewThisWeek = loader.Load(dbSourceThisWeek);
IDataView dataViewBeforeThisWeek = loader.Load(dbSourceBeforeThisWeek);
Maybe i should select more data from the past ? Yes my database is not big enough yet ( maybe 40-65 records per item from past 4 days) but each day i'm getting more data
Then i create 3 pipelines ( one for each type of Price ( Price of a unit , price of pack X10, price pack X100 )) :
forecastPipeline = mlContext.Forecasting.ForecastBySsa(
outputColumnName: "PriceForecasted",
inputColumnName: "Prix1",
windowSize: 7,
seriesLength: 30,
trainSize: 365,
horizon: 7,
confidenceLevel: 0.95f,
confidenceLowerBoundColumn: "LowerBoundPrice",
confidenceUpperBoundColumn: "UpperBoundPrice");
Is my setting correct here for my needs ?
Evaluate my 3 prediction for each prices:
actual = mlContext.Data.CreateEnumerable<Ressources>(testData, true)
.Select(observed => observed.Prix1);
forecast = mlContext.Data.CreateEnumerable<RessourceLot1Prediction>(predictions, true)
.Select(prediction => prediction.PriceForecasted[0]);
// Calculate error (actual - forecast)
var metrics = actual.Zip(forecast, (actualValue, forecastValue) => actualValue - forecastValue);
// Get metric averages
var MAE = metrics.Average(error => Math.Abs(error)); // Mean Absolute Error
var RMSE = Math.Sqrt(metrics.Average(error => Math.Pow(error, 2))); // Root Mean Squared Error
Creating my 3 engines for each prices i want to predict :
var forecastEngineLot1 = forecaster.CreateTimeSeriesEngine<Ressources, RessourceLot1Prediction>(core.mlContext);
forecastEngineLot1.CheckPoint(core.mlContext, modelPath);
Finally i predict my 3 prices :
IEnumerable<string> forecastOutput =
mlContext.Data.CreateEnumerable<Ressources>(testData, reuseRowObject: false)
.Take(horizon)
.Select((Ressources ress, int index) =>
{
string Date = ress.Date.ToString("dd-MM-yyyy hh:mm");
float actualPrice = ress.Prix1;
float lowerEstimate = Math.Max(0, forecast.LowerBoundPrice[index]);
float estimate = forecast.PriceForecasted[index];
float upperEstimate = forecast.UpperBoundPrice[index];
return $"Date: {Date}\n" +
$"Actual price: {actualPrice}\n" +
$"Lower Estimate: {lowerEstimate}\n" +
$"Forecast: {estimate}\n" +
$"Upper Estimate: {upperEstimate}\n";
});
I have these data:
- Item Name
- Unit Price
- Price of pack X10
- Price of pack X100
- Average Price
- Datetime when price captured
Here is my result and my dataset :

Class used :
public class Ressources
{
[LoadColumn(0)]
public string Ressource { get; set; }
[LoadColumn(1)]
public float Price1 { get; set; }
[LoadColumn(2)]
public float Price10 { get; set; }
[LoadColumn(3)]
public float Price100 { get; set; }
[LoadColumn(4)]
public float PriceAverage { get; set; }
[LoadColumn(5)]
public DateTime Date { get; set; }
}
public class RessourceLot1Prediction
{
public float[] PriceForecasted { get; set; }
public float[] LowerBoundPrice { get; set; }
public float[] UpperBoundPrice { get; set; }
}
public class RessourceLot10Prediction
{
public float[] PriceForecasted { get; set; }
public float[] LowerBoundPrice { get; set; }
public float[] UpperBoundPrice { get; set; }
}
public class RessourceLot100Prediction
{
public float[] PriceForecasted { get; set; }
public float[] LowerBoundPrice { get; set; }
public float[] UpperBoundPrice { get; set; }
}