ML.Net Прогнозирование результата Возвращение NaN - PullRequest
0 голосов
/ 31 марта 2019

ML.Net Prediction Score всегда возвращает NaN (ноль).

Идея состоит в том, чтобы научить регрессивный альгротимн изучать ежедневные рутины моих семей.Я попробовал несколько вариантов пакетов Nuget ML.Net и примеров кода, но с тем же результатом: Score == NaN.Ниже приведен некоторый код и часть набора данных, которые зарегистрированы в моей домашней автоматизации.

Это изменение примеров регрессии Рекомендации по фильмам из MSDN:

        public class AutomationData
        {

            [LoadColumn(0)]
            //0 - 6
            public int Day; 
            [LoadColumn(1)]
            //example: 0947 == 9:47am
            public int TimeOfDay; 
            //Device Id
            [LoadColumn(2)]
            public int Device; 
            //This is the State of the device (0 OFF - 1 ON) 
            // Seems it has to be float? (Vector R4)
            [LoadColumn(3)]
            public float Label; 
        }
        public class AutomationPrediction
        {
            public float Label;

            public float Score;
        }

        public static void  Regression()
        {
            MLContext mlContext = new MLContext();
            IDataView trainingDataView = LoadData(mlContext).training;
            IDataView testDataView = LoadData(mlContext).test;

            ITransformer model = BuildAndTrainModel(mlContext, trainingDataView);
            EvaluateModel(mlContext, testDataView, model);

            UseModelForSinglePrediction(mlContext, model);

        }

        public static (IDataView training, IDataView test) LoadData(MLContext mlContext)
        {
            var trainingDataPath = Path.Combine(Environment.CurrentDirectory, "MachineLearning/Data", "data.csv");
            var testDataPath = Path.Combine(Environment.CurrentDirectory, "MachineLearning/Data", "data.csv");
            IDataView trainingDataView = mlContext.Data.LoadFromTextFile<AutomationData>(trainingDataPath, hasHeader: true, separatorChar: ',');
            IDataView testDataView = mlContext.Data.LoadFromTextFile<AutomationData>(testDataPath, hasHeader: true, separatorChar: ',');
            return (trainingDataView, testDataView); 
        }

        public static ITransformer BuildAndTrainModel(MLContext mlContext, IDataView trainingDataView)
        {
            IEstimator<ITransformer> estimator = mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "deviceEncoded", inputColumnName: "Device")
           .Append(mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "timeOfDayEncoded", inputColumnName: "TimeOfDay"))
            .Append(mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "dayEncoded", inputColumnName: "Day"));

            var options = new MatrixFactorizationTrainer.Options
            {
                MatrixColumnIndexColumnName = "deviceEncoded",
                MatrixRowIndexColumnName = "timeOfDayEncoded",
                LabelColumnName = "Label",
                NumberOfIterations = 20,
                ApproximationRank = 100
            };

            var trainerEstimator = estimator.Append(mlContext.Recommendation().Trainers.MatrixFactorization(options));


            ITransformer model = trainerEstimator.Fit(trainingDataView);
            return model; 
        }

        public static void EvaluateModel(MLContext mlContext, IDataView testDataView, ITransformer model)
        {

            var prediction = model.Transform(testDataView);
            var metrics = mlContext.Regression.Evaluate(prediction, label: DefaultColumnNames.Label, score: DefaultColumnNames.Score);

            Console.WriteLine("Rms: " + metrics.Rms.ToString());
            Console.WriteLine("RSquared: " + metrics.RSquared.ToString());

        }

        public static void UseModelForSinglePrediction(MLContext mlContext, ITransformer model)
        {

            var predictionEngine = model.CreatePredictionEngine<AutomationData, AutomationPrediction>(mlContext);
            var testInput = new AutomationData { Device = 117, TimeOfDay = 0945 };
            var automationPrediction = predictionEngine.Predict(testInput);
            Console.WriteLine("Prediction Score: " + Math.Round(automationPrediction.Score, 1)); //Is Always 'NaN' (null)
            if (Math.Round(automationPrediction.Score, 1) > 3.5)
            {
                Console.WriteLine("State: " + testInput.Label);
            }
            else
            {
                Console.WriteLine("State " + testInput.Label);
            }
        }

    }

Вот фрагмент файла data.csv, который пытается использовать алгоритм регрессии.

Day,TimeOfDay,Device,State
6,0827,999,1
6,0827,117,1
6,0827,117,0
6,0838,18,1
6,0838,79,1
6,0838,6,1
6,0901,117,1
6,0908,999,0
6,0910,73,0
6,0913,72,1
6,0914,72,0
6,0915,79,0
6,0915,6,0
6,0915,5,0
6,0915,4,0
6,0915,18,0
6,1015,18,1
6,1015,79,1
6,1015,6,1
6,1015,5,1
6,1015,4,1
6,1726,18,1
6,1726,79,1
6,1726,51,0
6,1726,128,0
6,1726,69,0

Я ожидаю, что состояние предсказания вернет значение 0 или 1 (вкл. Или выкл.)и также Score (float), который показывает, насколько регрессия считает правильным.

1 Ответ

1 голос
/ 01 апреля 2019

Возвращает Нан , потому что не хватает данных, чтобы сделать прогноз.Я имею в виду, что матричная факторизация сделает прогноз в виде аппроксимации схожих значений.

В вашем примере вы используете только столбцы TimeOfDay и Device в матричной факторизации, поэтому с единственным прогнозом, который вы хотите использовать (новыйAutomationData {Device = 117, TimeOfDay = 0945}), модель возвращает Nan в виде оценки, поскольку она не может реально предсказать значение из изученной модели.

Выполнить тест, предсказатьуже известное значение, такое как

new AutomationData { Device = 73, TimeOfDay = 0910 };

, вы получите реальную оценку.

Кроме того, вы не должны использовать те же данные о поездах, что и при тестировании, это делает вашу оценку модели ненужной.

В конце концов, возможно, матричная факторизация не идеальный вариант для вашего случая использования.

...