diff --git a/Game1/Game1.csproj b/Game1/Game1.csproj index 109cb08..1783062 100644 --- a/Game1/Game1.csproj +++ b/Game1/Game1.csproj @@ -90,6 +90,9 @@ + + + diff --git a/Game1/Sources/ML_Joel/DataModel/Input.cs b/Game1/Sources/ML_Joel/DataModel/Input.cs new file mode 100644 index 0000000..5486a79 --- /dev/null +++ b/Game1/Sources/ML_Joel/DataModel/Input.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.ML.Data; + +namespace Game1.Sources.ML_Joel +{ + class Input + { + [ColumnName("Season"), LoadColumn(0)] + public String Season { get; set; } + + [ColumnName("Crop"), LoadColumn(1)] + public String Crop { get; set; } + + [ColumnName("Rainfall"), LoadColumn(2)] + public float Rainfall { get; set; } + + [ColumnName("Production"), LoadColumn(3)] + public float Production { get; set; } + } +} diff --git a/Game1/Sources/ML_Joel/DataModel/Output.cs b/Game1/Sources/ML_Joel/DataModel/Output.cs new file mode 100644 index 0000000..96cc12f --- /dev/null +++ b/Game1/Sources/ML_Joel/DataModel/Output.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.ML.Data; + +namespace Game1.Sources.ML_Joel +{ + class Output + { + [ColumnName("PredictedLabel")] + public float Prediction { get; set; } + } +} diff --git a/Game1/Sources/ML_Joel/Model.cs b/Game1/Sources/ML_Joel/Model.cs new file mode 100644 index 0000000..063a637 --- /dev/null +++ b/Game1/Sources/ML_Joel/Model.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.ML; +using Microsoft.ML.Data; +using Microsoft.ML.Trainers.LightGbm; + +namespace Game1.Sources.ML_Joel +{ + class Model + { + private static MLContext mlContext = new MLContext(seed: 1); + private static string path = "C:/Users/Joel/source/repos/Oskars Repo/Game1/Content/ML/Rainfall.csv"; + private static string modelpath = "C:/Users/Joel/source/repos/Oskars Repo/Game1/Content/ML/MLmodel_Joel"; + private static string report = "C:/Users/Joel/source/repos/Oskars Repo/Game1/Content/ML/report_Joel"; + + // Loading data, creatin and saving ML model for smaller dataset (100) + public static void CreateModel() + { + + IDataView trainingDataView = mlContext.Data.LoadFromTextFile( + path: path, + hasHeader: true, + separatorChar: ',', + allowQuoting: true, + allowSparse: false); + + ModelInput sample = mlContext.Data.CreateEnumerable(trainingDataView, false).ElementAt(0); + ITransformer MLModel = BuildAndTrain(mlContext, trainingDataView, sample, report); + SaveModel(mlContext, MLModel, modelpath, trainingDataView.Schema); + } + + // Building and training ML model, very small dataset (100 entries) + public static ITransformer BuildAndTrain(MLContext mLContext, IDataView trainingDataView, ModelInput sample, string reportPath) + { + + var options = new LightGbmMulticlassTrainer.Options + { + MaximumBinCountPerFeature = 8, + LearningRate = 0.00025, + NumberOfIterations = 40000, + NumberOfLeaves = 10, + LabelColumnName = "Fertilizer_NameF", + FeatureColumnName = "Features", + + Booster = new DartBooster.Options() + { + MaximumTreeDepth = 10 + } + }; + + var pipeline = mlContext.Transforms + .Text.FeaturizeText("Soil_TypeF", "Soil_Type") + .Append(mlContext.Transforms.Text.FeaturizeText("Crop_TypeF", "Crop_Type")) + .Append(mlContext.Transforms.Concatenate("Features", "Temperature", "Humidity", "Moisture", "Soil_TypeF", "Crop_TypeF", "Nitrogen", "Potassium", "Phosphorous")) + .Append(mlContext.Transforms.Conversion.MapValueToKey("Fertilizer_NameF", "Fertilizer_Name"), TransformerScope.TrainTest) + .AppendCacheCheckpoint(mLContext) + .Append(mLContext.MulticlassClassification.Trainers.LightGbm(options)) + .Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel", "PredictedLabel")); + + Evaluate(mlContext, trainingDataView, pipeline, 10, reportPath, "Fertilizer_NameF"); + ITransformer MLModel = pipeline.Fit(trainingDataView); + + return MLModel; + } + + public static ITransformer TrainModel(MLContext mlContext, IDataView trainingDataView, IEstimator trainingPipeline) + { + ITransformer model = trainingPipeline.Fit(trainingDataView); + return model; + } + + // Evaluate and save results to a text file + public static void Evaluate(MLContext mlContext, IDataView trainingDataView, IEstimator trainingPipeline, int folds, string reportPath, string labelColumnName) + { + var crossVal = mlContext.MulticlassClassification.CrossValidate(trainingDataView, trainingPipeline, numberOfFolds: folds, labelColumnName: labelColumnName); + + var metricsInMultipleFolds = crossVal.Select(r => r.Metrics); + + var MicroAccuracyValues = metricsInMultipleFolds.Select(m => m.MicroAccuracy); + var LogLossValues = metricsInMultipleFolds.Select(m => m.LogLoss); + var LogLossReductionValues = metricsInMultipleFolds.Select(m => m.LogLossReduction); + string MicroAccuracyAverage = MicroAccuracyValues.Average().ToString("0.######"); + string LogLossAvg = LogLossValues.Average().ToString("0.######"); + string LogLossReductionAvg = LogLossReductionValues.Average().ToString("0.######"); + + var report = File.CreateText(reportPath); + report.Write("Micro Accuracy: " + MicroAccuracyAverage + '\n' + "LogLoss Average: " + LogLossAvg + '\n' + "LogLoss Reduction: " + LogLossReductionAvg, 0, 0); + report.Flush(); + report.Close(); + } + + + public static void SaveModel(MLContext mlContext, ITransformer Model, string modelPath, DataViewSchema modelInputSchema) + { + mlContext.Model.Save(Model, modelInputSchema, modelPath); + } + + public static ITransformer LoadModel(bool isBig) + { + return mlContext.Model.Load(modelpath, out DataViewSchema inputSchema); + } + + public static Microsoft.ML.PredictionEngine CreateEngine() + { + ITransformer mlModel = LoadModel(false); + return mlContext.Model.CreatePredictionEngine(mlModel); + } + + } +}