dotnet / docs

This repository contains .NET Documentation.
https://learn.microsoft.com/dotnet
Creative Commons Attribution 4.0 International
4.27k stars 5.9k forks source link

Error following tutorial #23484

Closed DuddyRosenberg closed 3 years ago

DuddyRosenberg commented 3 years ago

I’m trying to do this tutorial on forcasting with MLnet and it just blows up on Line 47 SsaForecastingTransformer forecaster = forecastingPipeline.Fit(firstYearData); in program.cs, error message just saying Exception has been thrown by the target of an invocation.. Am i the only one?

Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

luisquintanilla commented 3 years ago

Hi @DuddyRosenberg

Thanks for raising this issue. Looking into it.

luisquintanilla commented 3 years ago

@DuddyRosenberg

I was not able to reproduce. I created the app from scratch and got the expected output without errors. Can you try starting again and taking a look at what I've pasted below to see if there's differences between your code and mine.

Evaluation Metrics
---------------------
Mean Absolute Error: 726.416
Root Mean Squared Error: 987.658

Rental Forecast
---------------------
Date: 1/1/2012
Actual Rentals: 2294
Lower Estimate: 1197.8424
Forecast: 2334.4434
Upper Estimate: 3471.0442

Date: 1/2/2012
Actual Rentals: 1951
Lower Estimate: 1148.4125
Forecast: 2360.8608
Upper Estimate: 3573.309

Date: 1/3/2012
Actual Rentals: 2236
Lower Estimate: 1068.5067
Forecast: 2373.2764
Upper Estimate: 3678.046

Date: 1/4/2012
Actual Rentals: 2368
Lower Estimate: 984.98376
Forecast: 2382.2546
Upper Estimate: 3779.5254

Date: 1/5/2012
Actual Rentals: 3272
Lower Estimate: 906.73895
Forecast: 2386.749
Upper Estimate: 3866.759

Date: 1/6/2012
Actual Rentals: 4098
Lower Estimate: 825.9437
Forecast: 2387.0024
Upper Estimate: 3948.0613

Date: 1/7/2012
Actual Rentals: 4521
Lower Estimate: 743.52264
Forecast: 2385.3787
Upper Estimate: 4027.2346

This is the code in my Program.cs.

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using Microsoft.ML;
using Microsoft.ML.Data;
using Microsoft.ML.Transforms.TimeSeries;

namespace BikeDemandForecasting
{
    class Program
    {
        static void Main(string[] args)
        {
            string rootDir = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../../../"));
            string dbFilePath = Path.Combine(rootDir, "Data", "DailyDemand.mdf");
            string modelPath = Path.Combine(rootDir, "MLModel.zip");
            var connectionString = $"Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename={dbFilePath};Integrated Security=True;Connect Timeout=30;";

            MLContext mlContext = new MLContext();

            DatabaseLoader loader = mlContext.Data.CreateDatabaseLoader<ModelInput>();

            string query = "SELECT RentalDate, CAST(Year as REAL) as Year, CAST(TotalRentals as REAL) as TotalRentals FROM Rentals";

            DatabaseSource dbSource = new DatabaseSource(SqlClientFactory.Instance,
                                connectionString,
                                query);

            IDataView dataView = loader.Load(dbSource);

            IDataView firstYearData = mlContext.Data.FilterRowsByColumn(dataView, "Year", upperBound: 1);
            IDataView secondYearData = mlContext.Data.FilterRowsByColumn(dataView, "Year", lowerBound: 1);

            var forecastingPipeline = mlContext.Forecasting.ForecastBySsa(
                outputColumnName: "ForecastedRentals",
                inputColumnName: "TotalRentals",
                windowSize: 7,
                seriesLength: 30,
                trainSize: 365,
                horizon: 7,
                confidenceLevel: 0.95f,
                confidenceLowerBoundColumn: "LowerBoundRentals",
                confidenceUpperBoundColumn: "UpperBoundRentals");

            SsaForecastingTransformer forecaster = forecastingPipeline.Fit(firstYearData);

            Evaluate(secondYearData, forecaster, mlContext);

            var forecastEngine = forecaster.CreateTimeSeriesEngine<ModelInput, ModelOutput>(mlContext);

            forecastEngine.CheckPoint(mlContext, modelPath);

            Forecast(secondYearData, 7, forecastEngine, mlContext);
        }

        static void Evaluate(IDataView testData, ITransformer model, MLContext mlContext)
        {
            IDataView predictions = model.Transform(testData);

            IEnumerable<float> actual =
                mlContext.Data.CreateEnumerable<ModelInput>(testData, true)
                    .Select(observed => observed.TotalRentals);

            IEnumerable<float> forecast =
                mlContext.Data.CreateEnumerable<ModelOutput>(predictions, true)
                    .Select(prediction => prediction.ForecastedRentals[0]);

            var metrics = actual.Zip(forecast, (actualValue, forecastValue) => actualValue - forecastValue);

            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

            Console.WriteLine("Evaluation Metrics");
            Console.WriteLine("---------------------");
            Console.WriteLine($"Mean Absolute Error: {MAE:F3}");
            Console.WriteLine($"Root Mean Squared Error: {RMSE:F3}\n");
        }

        static void Forecast(IDataView testData, int horizon, TimeSeriesPredictionEngine<ModelInput, ModelOutput> forecaster, MLContext mlContext)
        {
            ModelOutput forecast = forecaster.Predict();

            IEnumerable<string> forecastOutput =
                mlContext.Data.CreateEnumerable<ModelInput>(testData, reuseRowObject: false)
                    .Take(horizon)
                    .Select((ModelInput rental, int index) =>
                    {
                        string rentalDate = rental.RentalDate.ToShortDateString();
                        float actualRentals = rental.TotalRentals;
                        float lowerEstimate = Math.Max(0, forecast.LowerBoundRentals[index]);
                        float estimate = forecast.ForecastedRentals[index];
                        float upperEstimate = forecast.UpperBoundRentals[index];
                        return $"Date: {rentalDate}\n" +
                        $"Actual Rentals: {actualRentals}\n" +
                        $"Lower Estimate: {lowerEstimate}\n" +
                        $"Forecast: {estimate}\n" +
                        $"Upper Estimate: {upperEstimate}\n";
                    });

            Console.WriteLine("Rental Forecast");
            Console.WriteLine("---------------------");
            foreach (var prediction in forecastOutput)
            {
                Console.WriteLine(prediction);
            }
        }
    }

    public class ModelInput
    {
        public DateTime RentalDate { get; set; }

        public float Year { get; set; }

        public float TotalRentals { get; set; }
    }

    public class ModelOutput
    {
        public float[] ForecastedRentals { get; set; }

        public float[] LowerBoundRentals { get; set; }

        public float[] UpperBoundRentals { get; set; }
    }
}

Here is the project structure and package versions I'm using:

image

luisquintanilla commented 3 years ago

@DuddyRosenberg were you able to get your application running?

luisquintanilla commented 3 years ago

Closing this issue due to no response and being unable to reproduce the error. @DuddyRosenberg please feel free to open an issue if you run into other errors.