/// <summary>
        /// Build model for predicting next month's product unit sales using time series forecasting.
        /// </summary>
        /// <param name="mlContext">ML.NET context.</param>
        /// <param name="productDataSeries">ML.NET IDataView representing the loaded product data series.</param>
        /// <param name="outputModelPath">Model path.</param>
        private static void FitAndSaveModel(MLContext mlContext, IDataView productDataSeries, string outputModelPath)
        {
            ConsoleWriteHeader("Fitting product forecasting Time Series model");

            const int numSeriesDataPoints = 34; //The underlying data has a total of 34 months worth of data for each product

            // Create and add the forecast estimator to the pipeline.
            IEstimator <ITransformer> forecastEstimator = mlContext.Forecasting.ForecastBySsa(
                outputColumnName: nameof(ProductUnitTimeSeriesPrediction.ForecastedProductUnits),
                inputColumnName: nameof(ProductData.units),                                                // This is the column being forecasted.
                windowSize: 12,                                                                            // Window size is set to the time period represented in the product data cycle; our product cycle is based on 12 months, so this is set to a factor of 12, e.g. 3.
                seriesLength: numSeriesDataPoints,                                                         // This parameter specifies the number of data points that are used when performing a forecast.
                trainSize: numSeriesDataPoints,                                                            // This parameter specifies the total number of data points in the input time series, starting from the beginning.
                horizon: 2,                                                                                // Indicates the number of values to forecast; 2 indicates that the next 2 months of product units will be forecasted.
                confidenceLevel: 0.95f,                                                                    // Indicates the likelihood the real observed value will fall within the specified interval bounds.
                confidenceLowerBoundColumn: nameof(ProductUnitTimeSeriesPrediction.ConfidenceLowerBound),  //This is the name of the column that will be used to store the lower interval bound for each forecasted value.
                confidenceUpperBoundColumn: nameof(ProductUnitTimeSeriesPrediction.ConfidenceUpperBound)); //This is the name of the column that will be used to store the upper interval bound for each forecasted value.

            // Fit the forecasting model to the specified product's data series.
            ITransformer forecastTransformer = forecastEstimator.Fit(productDataSeries);

            // Create the forecast engine used for creating predictions.
            TimeSeriesPredictionEngine <ProductData, ProductUnitTimeSeriesPrediction> forecastEngine = forecastTransformer.CreateTimeSeriesEngine <ProductData, ProductUnitTimeSeriesPrediction>(mlContext);

            // Save the forecasting model so that it can be loaded within an end-user app.
            forecastEngine.CheckPoint(mlContext, outputModelPath);
        }
        /// <summary>
        /// Build model for predicting next month's product unit sales using time series forecasting.
        /// </summary>
        /// <param name="mlContext">ML.NET context.</param>
        /// <param name="productDataSeries">ML.NET IDataView representing the loaded product data series.</param>
        /// <param name="outputModelPath">Trained model path.</param>
        private static void TrainAndSaveModel(MLContext mlContext, IDataView productDataView, string outputModelPath)
        {
            ConsoleWriteHeader("Training product forecasting Time Series model");

            var supplementedProductDataSeries       = TimeSeriesDataGenerator.SupplementData(mlContext, productDataView);
            var supplementedProductDataSeriesLength = supplementedProductDataSeries.Count(); // 36
            var supplementedProductDataView         = mlContext.Data.LoadFromEnumerable(supplementedProductDataSeries, productDataView.Schema);

            // Create and add the forecast estimator to the pipeline.
            IEstimator <ITransformer> forecastEstimator = mlContext.Forecasting.ForecastBySsa(
                outputColumnName: nameof(ProductUnitTimeSeriesPrediction.ForecastedProductUnits),
                inputColumnName: nameof(ProductData.units),                                                // This is the column being forecasted.
                windowSize: 12,                                                                            // Window size is set to the time period represented in the product data cycle; our product cycle is based on 12 months, so this is set to a factor of 12, e.g. 3.
                seriesLength: supplementedProductDataSeriesLength,                                         // TODO: Need clarification on what this should be set to; assuming product series length for now.
                trainSize: supplementedProductDataSeriesLength,                                            // TODO: Need clarification on what this should be set to; assuming product series length for now.
                horizon: 2,                                                                                // Indicates the number of values to forecast; 2 indicates that the next 2 months of product units will be forecasted.
                confidenceLevel: 0.95f,                                                                    // TODO: Is this the same as prediction interval, where this indicates that we are 95% confidence that the forecasted value will fall within the interval range?
                confidenceLowerBoundColumn: nameof(ProductUnitTimeSeriesPrediction.ConfidenceLowerBound),  // TODO: See above comment.
                confidenceUpperBoundColumn: nameof(ProductUnitTimeSeriesPrediction.ConfidenceUpperBound)); // TODO: See above comment.

            // Train the forecasting model for the specified product's data series.
            ITransformer forecastTransformer = forecastEstimator.Fit(supplementedProductDataView);

            // Create the forecast engine used for creating predictions.
            TimeSeriesPredictionEngine <ProductData, ProductUnitTimeSeriesPrediction> forecastEngine = forecastTransformer.CreateTimeSeriesEngine <ProductData, ProductUnitTimeSeriesPrediction>(mlContext);

            // Save the forecasting model so that it can be loaded within an end-user app.
            forecastEngine.CheckPoint(mlContext, outputModelPath);
        }
Beispiel #3
0
        static void Main(string[] args)
        {
            var mlContext = new MLContext();


            int   c = 0;
            float predictedPrice = 0;

            while (c < 10)
            {
                IEnumerable <BTC_TimeSeries> data = GetTrainingData(mlContext);


                IDataView trainingData = mlContext.Data.LoadFromEnumerable <BTC_TimeSeries>(data);
                var       offset       = TimeSpan.FromSeconds(data.Last().TimeStamp);
                var       epoch        = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
                DateTime  lastTime     = epoch.Add(offset).ToLocalTime();

                int seriesLength = data.Count();

                var estimator = mlContext.Forecasting.ForecastBySsa(outputColumnName: nameof(PredictedSeries.ForecastedPrice),
                                                                    inputColumnName: nameof(BTC_TimeSeries.Price),
                                                                    windowSize: 360,
                                                                    seriesLength: seriesLength,
                                                                    trainSize: seriesLength,
                                                                    horizon: 5,
                                                                    confidenceLevel: 0.95f,
                                                                    confidenceLowerBoundColumn: nameof(PredictedSeries.ConfidenceLowerBound),
                                                                    confidenceUpperBoundColumn: nameof(PredictedSeries.ConfidenceUpperBound)
                                                                    );

                Console.WriteLine("Training model");
                ITransformer forecastTransformer = estimator.Fit(trainingData);

                TimeSeriesPredictionEngine <BTC_TimeSeries, PredictedSeries> forecastEngine = forecastTransformer.CreateTimeSeriesEngine <BTC_TimeSeries, PredictedSeries>(mlContext);

                PredictedSeries predictions = forecastEngine.Predict();
                Console.WriteLine("last read time {0}: last read price {1}", lastTime, data.Last().Price);
                for (int i = 0; i < predictions.ForecastedPrice.Count(); i++)
                {
                    lastTime = lastTime.AddMinutes(15);
                    Console.WriteLine("{0} price: {1}, low: {2}, high: {3}", lastTime, predictions.ForecastedPrice[i].ToString(), predictions.ConfidenceLowerBound[i].ToString(), predictions.ConfidenceUpperBound[i].ToString());
                }

                float delta = predictedPrice - data.Last().Price;
                Console.WriteLine("Delta, {0}", delta);
                predictedPrice = predictions.ForecastedPrice[0];
                forecastEngine.CheckPoint(mlContext, "forecastmodel.zip");

                System.Threading.Thread.Sleep(300000);
                c++;
            }


            Console.Read();
        }
        /// <summary>
        /// Predict samples using saved model.
        /// </summary>
        /// <param name="mlContext">ML.NET context.</param>
        /// <param name="lastMonthProductData">The last month of product data in the monthly data series.</param>
        /// <param name="outputModelPath">Model file path</param>
        private static void TestPrediction(MLContext mlContext, ProductData lastMonthProductData, string outputModelPath)
        {
            ConsoleWriteHeader("Testing product unit sales forecast Time Series model");

            // Load the forecast engine that has been previously saved.
            ITransformer forecaster;

            using (var file = File.OpenRead(outputModelPath))
            {
                forecaster = mlContext.Model.Load(file, out DataViewSchema schema);
            }

            // We must create a new prediction engine from the persisted model.
            TimeSeriesPredictionEngine <ProductData, ProductUnitTimeSeriesPrediction> forecastEngine = forecaster.CreateTimeSeriesEngine <ProductData, ProductUnitTimeSeriesPrediction>(mlContext);

            // Get the prediction; this will include the forecasted product units sold for the next 2 months since this the time period specified in the `horizon` parameter when the forecast estimator was originally created.
            Console.WriteLine("\n** Original prediction **");
            ProductUnitTimeSeriesPrediction originalSalesPrediction = forecastEngine.Predict();

            // Compare the units of the first forecasted month to the actual units sold for the next month.
            var predictionMonth = lastMonthProductData.month == 12 ? 1 : lastMonthProductData.month + 1;
            var predictionYear  = predictionMonth < lastMonthProductData.month ? lastMonthProductData.year + 1 : lastMonthProductData.year;

            Console.WriteLine($"Product: {lastMonthProductData.productId}, Month: {predictionMonth}, Year: {predictionYear} " +
                              $"- Real Value (units): {lastMonthProductData.next}, Forecasted (units): {originalSalesPrediction.ForecastedProductUnits[0]}");

            // Get the first forecasted month's confidence interval bounds.
            Console.WriteLine($"Confidence interval: [{originalSalesPrediction.ConfidenceLowerBound[0]} - {originalSalesPrediction.ConfidenceUpperBound[0]}]\n");

            // Get the units of the second forecasted month.
            Console.WriteLine($"Product: {lastMonthProductData.productId}, Month: {lastMonthProductData.month + 2}, Year: {lastMonthProductData.year}, " +
                              $"Forecasted (units): {originalSalesPrediction.ForecastedProductUnits[1]}");

            // Get the second forecasted month's confidence interval bounds.
            Console.WriteLine($"Confidence interval: [{originalSalesPrediction.ConfidenceLowerBound[1]} - {originalSalesPrediction.ConfidenceUpperBound[1]}]\n");

            // Update the forecasting model with the next month's actual product data to get an updated prediction; this time, only forecast product sales for 1 month ahead.
            Console.WriteLine("** Updated prediction **");
            ProductData newProductData = SampleProductData.MonthlyData.Where(p => p.productId == lastMonthProductData.productId).Single();
            ProductUnitTimeSeriesPrediction updatedSalesPrediction = forecastEngine.Predict(newProductData, horizon: 1);

            // Save the updated forecasting model.
            forecastEngine.CheckPoint(mlContext, outputModelPath);

            // Get the units of the updated forecast.
            predictionMonth = lastMonthProductData.month >= 11 ? (lastMonthProductData.month + 2) % 12 : lastMonthProductData.month + 2;
            predictionYear  = predictionMonth < lastMonthProductData.month ? lastMonthProductData.year + 1 : lastMonthProductData.year;
            Console.WriteLine($"Product: {lastMonthProductData.productId}, Month: {predictionMonth}, Year: {predictionYear}, " +
                              $"Forecasted (units): {updatedSalesPrediction.ForecastedProductUnits[0]}");

            // Get the updated forecast's confidence interval bounds.
            Console.WriteLine($"Confidence interval: [{updatedSalesPrediction.ConfidenceLowerBound[0]} - {updatedSalesPrediction.ConfidenceUpperBound[0]}]\n");
        }
Beispiel #5
0
        static void Predict()
        {
            //prediction engine based on our fitted model
            TimeSeriesPredictionEngine <BTCDataModel, PredictedSeriesDataModel> forecastEngine = forecastTransformer.CreateTimeSeriesEngine <BTCDataModel, PredictedSeriesDataModel>(mlContext);

            //call to predict the next 5 minutes
            PredictedSeriesDataModel predictions = forecastEngine.Predict();

            //write our predictions
            for (int i = 0; i < predictions.ForecastedPrice.Count(); i++)
            {
                lastTime = lastTime.AddMinutes(1);
                Console.WriteLine("{0} price: {1}, low: {2}, high: {3}, actual: {4}", lastTime, predictions.ForecastedPrice[i].ToString(), predictions.ConfidenceLowerBound[i].ToString(), predictions.ConfidenceUpperBound[i].ToString(), testingData[i].Amount);
            }


            //instead of saving, we use checkpoint. This allows us to continue training with updated data and not need to keep such a large data set
            //so we can append Jan. 2021 without having everythign before to train the model speeding up the process
            forecastEngine.CheckPoint(mlContext, fileName);
        }
Beispiel #6
0
        private static void Main(string[] args)
        {
            _mlContext = new MLContext();

            // Load data from db
            IDataView dataView       = LoadDataFromDB();
            var       firstYearData  = _mlContext.Data.FilterRowsByColumn(dataView, "Year", upperBound: 1);
            var       secondYearData = _mlContext.Data.FilterRowsByColumn(dataView, "Year", lowerBound: 1);

            // Create forecasting model
            var forecaster = ProcessData(firstYearData);

            // Evaluate forecasting model
            Evaluate(secondYearData, forecaster);

            // Save model to zip file
            _forecastEngine = forecaster.CreateTimeSeriesEngine <ModelInput, ModelOutput>(_mlContext);
            _forecastEngine.CheckPoint(_mlContext, modelPath);

            // Use model for forecast
            Forecast(secondYearData, 7, _forecastEngine);
        }
Beispiel #7
0
        /// <summary>
        /// Crea el modelo y lo guarda en el path entrado
        /// </summary>
        /// <param name="mlContext">ML.NET context.</param>
        /// <param name="productId">Id of the product series to forecast.</param>
        /// <param name="dataPath">Input data file path.</param>
        private static void CreateAndSaveModelTimeSeries(MLContext mlContext, string dataPath, float id)
        {
            var productModelPath = $"product{id}_month_timeSeriesSSA.zip";

            if (File.Exists(productModelPath))
            {
                File.Delete(productModelPath);
            }
            IDataView saleDataView            = LoadData(mlContext, dataPath, id);
            var       singleProductDataSeries = mlContext.Data.CreateEnumerable <SaleData>(saleDataView, false).OrderBy(p => p.ano).ThenBy(p => p.mes);
            SaleData  lastMonthSalesData      = singleProductDataSeries.Last();

            Console.WriteLine("Creando el modelo: Time Series Model");

            const int numSeriesDataPoints = 34;
            IEstimator <ITransformer> forecastEstimator = mlContext.Forecasting.ForecastBySsa(
                outputColumnName: nameof(ProductUnitTimeSeriesPrediction.ForecastedProductUnits),
                inputColumnName: nameof(SaleData.unidades),                                                // This is the column being forecasted.
                windowSize: 12,                                                                            // Window size is set to the time period represented in the product data cycle; our product cycle is based on 12 months, so this is set to a factor of 12, e.g. 3.
                seriesLength: numSeriesDataPoints,                                                         // This parameter specifies the number of data points that are used when performing a forecast.
                trainSize: numSeriesDataPoints,                                                            // This parameter specifies the total number of data points in the input time series, starting from the beginning.
                horizon: 2,                                                                                // Indicates the number of values to forecast; 2 indicates that the next 2 months of product units will be forecasted.
                confidenceLevel: 0.95f,                                                                    // Indicates the likelihood the real observed value will fall within the specified interval bounds.
                confidenceLowerBoundColumn: nameof(ProductUnitTimeSeriesPrediction.ConfidenceLowerBound),  //This is the name of the column that will be used to store the lower interval bound for each forecasted value.
                confidenceUpperBoundColumn: nameof(ProductUnitTimeSeriesPrediction.ConfidenceUpperBound)); //This is the name of the column that will be used to store the upper interval bound for each forecasted value.

            // Fit the forecasting model to the specified product's data series.
            ITransformer forecastTransformer = forecastEstimator.Fit(saleDataView);

            // Create the forecast engine used for creating predictions.
            TimeSeriesPredictionEngine <SaleData, ProductUnitTimeSeriesPrediction> forecastEngine = forecastTransformer.CreateTimeSeriesEngine <SaleData, ProductUnitTimeSeriesPrediction>(mlContext);

            // Save the forecasting model so that it can be loaded within an end-user app.
            forecastEngine.CheckPoint(mlContext, productModelPath);
            TestPrediction(mlContext, lastMonthSalesData, productModelPath);
        }
        private static void SaveModel(MLContext context, ITransformer model)
        {
            TimeSeriesPredictionEngine <ModelInput, ModelOutput> forecastEngine = model.CreateTimeSeriesEngine <ModelInput, ModelOutput>(context);

            forecastEngine.CheckPoint(context, MODEL_PATH);
        }