Модель двоичной классификации ML.NET не работает - PullRequest
0 голосов
/ 11 ноября 2018

В ML.Net не так много документации, так как она выглядит относительно новой. Я сталкивался с проблемой за проблемой, пытаясь понять, как ее использовать, и, наконец, я понял, что этого достаточно, чтобы он хотя бы работал без ошибки; Однако, похоже, проблема с моей моделью. Всегда возвращает 0 с вероятностью 50%. Я включил свой код ниже. Кто-нибудь знает какие-либо хорошие ресурсы для самой последней версии ML.Net, которые я могу исследовать? Предполагается, что приведенный ниже код создает бинарную классификационную модель, которая может предсказать, выйдет ли команда в плей-офф или нет. Данные являются только окончательными результатами прошлого сезона, при этом большинство данных было удалено, поэтому единственными оставшимися столбцами являются средний возраст, выигрыши, проигрыши и статус плей-офф (1 = плей-офф & 0 = нет плей-офф).

Program.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.ML;
using Microsoft.ML.Core.Data;
using Microsoft.ML.Runtime.Api;
using Microsoft.ML.Runtime.Data;

namespace MachineLearning2
{
    class Program
    {
        static readonly string _trainDataPath = Path.Combine(Environment.CurrentDirectory, "trainingNHL.txt");
        static readonly string _testDataPath = Path.Combine(Environment.CurrentDirectory, "testingNHL.txt");
        static readonly string _modelPath = Path.Combine(Environment.CurrentDirectory, "Model.zip");
        static TextLoader _textLoader;

        static void Main(string[] args)
        {
            MLContext mlContext = new MLContext(seed: 0);
            _textLoader = mlContext.Data.TextReader(new TextLoader.Arguments()
            {
                Separator = ",",
                HasHeader = false,
                Column = new[]
                    {
                        new TextLoader.Column("Age", DataKind.R4, 0),
                        new TextLoader.Column("Wins", DataKind.R4, 1),
                        new TextLoader.Column("Losses", DataKind.R4, 2),
                        new TextLoader.Column("Label", DataKind.R4, 3)
                    }
            });
            var model = Train(mlContext, _trainDataPath);
            Evaluate(mlContext, model);
            Predict(mlContext, model);
            PredictWithModelLoadedFromFile(mlContext);

        }

        public static ITransformer Train(MLContext mlContext, string dataPath)
        {
            IDataView dataView = _textLoader.Read(dataPath);
            var pipeline = mlContext.Transforms.Concatenate("Features","Age", "Wins", "Losses")
                .Append(mlContext.BinaryClassification.Trainers.FastTree(numLeaves: 50, numTrees: 50, minDatapointsInLeafs: 20));
            Console.WriteLine("=============== Create and Train the Model ===============");
            var model = pipeline.Fit(dataView);
            Console.WriteLine("=============== End of training ===============");
            Console.WriteLine();
            return model;
        }

        public static void Evaluate(MLContext mlContext, ITransformer model)
        {
            IDataView dataView = _textLoader.Read(_testDataPath);
            Console.WriteLine("=============== Evaluating Model accuracy with Test data===============");
            var predictions = model.Transform(dataView);
            var metrics = mlContext.BinaryClassification.Evaluate(predictions, "Label");
            Console.WriteLine();
            Console.WriteLine("Model quality metrics evaluation");
            Console.WriteLine("--------------------------------");
            Console.WriteLine($"Accuracy: {metrics.Accuracy:P2}");
            Console.WriteLine($"Auc: {metrics.Auc:P2}");
            Console.WriteLine($"F1Score: {metrics.F1Score:P2}");
            Console.WriteLine("=============== End of model evaluation ===============");
            SaveModelAsFile(mlContext, model);
        }

        private static void SaveModelAsFile(MLContext mlContext, ITransformer model)
        {
            using (var fs = new FileStream(_modelPath, FileMode.Create, FileAccess.Write, FileShare.Write))
                mlContext.Model.Save(model, fs);
            Console.WriteLine("The model is saved to {0}", _modelPath);

        }

        public static void Predict(MLContext mlContext, ITransformer model)
        {
            var predictionFunction = model.MakePredictionFunction<NHLData, NHLPrediction>(mlContext);
            NHLData sampleTeam = new NHLData
            {
                Age = 29,
                Wins = 60,
                Losses = 22
            };
            var resultprediction = predictionFunction.Predict(sampleTeam);
            Console.WriteLine();
            Console.WriteLine("=============== Prediction Test of model with a single sample and test dataset ===============");

            Console.WriteLine();
            Console.WriteLine($"Age: {sampleTeam.Age} | Wins: {sampleTeam.Wins} | Losses: {sampleTeam.Losses} | Prediction: {(Convert.ToBoolean(resultprediction.Prediction) ? "Yes" : "No")} | Probability: {resultprediction.Probability} ");
            Console.WriteLine("=============== End of Predictions ===============");
            Console.WriteLine();
        }

        public static void PredictWithModelLoadedFromFile(MLContext mlContext)
        {
            IEnumerable<NHLData> teams = new[]
            {
                new NHLData
                {
                    Age = 29,
                    Wins = 30,
                    Losses = 52
                },
                new NHLData
                {
                    Age = 35,
                    Wins = 80,
                    Losses = 2
                }
            };
            ITransformer loadedModel;
            using (var stream = new FileStream(_modelPath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                loadedModel = mlContext.Model.Load(stream);
            }
            // Create prediction engine
            var nhlStreamingDataView = mlContext.CreateStreamingDataView(teams);
            var predictions = loadedModel.Transform(nhlStreamingDataView);

            // Use the model to predict whether comment data is toxic (1) or nice (0).
            var predictedResults = predictions.AsEnumerable<NHLPrediction>(mlContext, reuseRowObject: false);
            Console.WriteLine();

            Console.WriteLine("=============== Prediction Test of loaded model with a multiple samples ===============");
            var teamsAndPredictions = teams.Zip(predictedResults, (team, prediction) => (team, prediction));
            foreach (var item in teamsAndPredictions)
            {
                Console.WriteLine($"Age: {item.team.Age} | Wins: {item.team.Wins} | Losses: {item.team.Losses} | Prediction: {(Convert.ToBoolean(item.prediction.Prediction) ? "Yes" : "No")} | Probability: {item.prediction.Probability} ");
            }
            Console.WriteLine("=============== End of predictions ===============");
        }
    }
}

NHLData.cs

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.ML.Runtime.Api;

namespace MachineLearning2
{
    public class NHLData
    {
        [Column(ordinal: "0")]
        public float Age;
        [Column(ordinal: "1")]
        public float Wins;
        [Column(ordinal: "2")]
        public float Losses;
        [Column(ordinal: "3", name: "Label")]
        public float Playoffs;
    }

    public class NHLPrediction
    {
        [ColumnName("PredictedLabel")]
        public bool Prediction { get; set; }

        [ColumnName("Probability")]
        public float Probability { get; set; }

        [ColumnName("Score")]
        public float Score { get; set; }
    }
}

trainingNHL.txt (столбцы: возраст, выигрыши, поражения, плей-офф)

28.4,53,18,1
27.5,54,23,1
28,51,24,1
28.3,49,26,1
29.5,45,26,1
28.8,45,27,1
29.1,45,29,1
27.7,44,29,1
26.4,43,30,1
28.5,42,32,0
27,36,35,0
26.8,36,40,0
28,33,39,0
30.2,30,39,0
26.5,29,41,0
27.1,25,45,0

testingNHL.txt (столбцы: возраст, выигрыши, поражения, плей-офф)

26.8,52,20,1
28.6,50,20,1
28.4,49,26,1
28.7,44,25,1
27.7,47,29,1
27.4,42,26,1
26.4,45,30,1
27.8,44,30,0
28.5,44,32,0
28.4,37,35,0
28.4,35,37,0
28.7,34,39,0
28.2,31,40,0
27.8,29,40,0
29.3,28,43,0

1 Ответ

0 голосов
/ 11 ноября 2018

Является ли trainingNHL.txt полным набором данных, который вы используете, или только его образцом? Я только что попробовал обучиться этому с помощью FastTree и вижу: «Предупреждение: 50 ускоряющих итераций не смогли вырастить дерево. Обычно это связано с тем, что минимальный размер документов в листовом гиперпараметре был слишком велик для этого набора данных».

Учитывая параметры, заданные вами в FastTree, вам потребуется больше данных для обучения содержательной модели. Когда я изменяю minDatapointsInLeafs на 2, я могу обучить нетривиальной модели (хотя результаты все еще не заслуживают особого доверия из-за количества данных). Вы также можете попробовать использовать что-то вроде AveragedPerceptron или SDCA.

...