#c# #ml.net
#c# #ml.net
Вопрос:
ML.Net Результат прогнозирования всегда возвращает NaN (null).
Идея состоит в том, чтобы научить регрессионный алгротимн изучать повседневные процедуры моей семьи. Я попробовал несколько вариантов ML.Net пакеты nuget и примеры кода, но с тем же результатом: оценка == 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 (включено или выключено), а также оценку (с плавающей точкой), которая показала бы, насколько близко регрессия считает, что это правильно.
Ответ №1:
Он возвращает Nan, потому что данных недостаточно для выполнения прогноза. Я имею в виду, что матричная факторизация сделает прогноз как приближение аналогичных значений.
В вашем примере вы используете только столбцы TimeOfDay и Device при факторизации матрицы, поэтому с единственным прогнозом, который вы хотите использовать (new AutomationData { Device = 117, TimeOfDay = 0945 }), модель возвращает Nan в виде оценки, потому что она не может реально предсказать значение из изученной модели.
Сделайте тест, предсказайте уже известное значение, например
new AutomationData { Device = 73, TimeOfDay = 0910 };
вы получите фактический результат.
Кроме того, вы не должны использовать те же данные поезда, что и test, это делает ненужной оценку вашей модели.
В конце концов, возможно, факторизация матрицы не является идеальным вариантом для вашего варианта использования.
Комментарии:
1. Спасибо, я удивился, что мой набор данных слишком мал. Я решил попробовать новый подход к коду. Я попробовал пример MSDN для тарифов на такси. Следовать этому было немного проще, чем примеру с рекомендацией фильма. Он также использует FastTree для составления своих прогнозов. Возможно, я заполню свой набор данных еще на пару недель и снова протестирую трейнер. Вы упомянули другой подход к моей ситуации. Какой вариант лучше подошел бы моему проекту. Спасибо.
2. @user2224583 предполагая, что это проблема мультиклассификации, вы можете использовать классификатор LogisticRegression, классификатор NaiveBayesClassifier или SDCAMULTICLASSSTRAINER
3. @user2224583 Это правильный ответ?