Initial commit
This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
using Microsoft.ML;
|
||||
using Microsoft.ML.Data;
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
using System.Linq;
|
||||
using AutoBet.Learn.Extensions;
|
||||
using Microsoft.ML.Trainers;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AutoBet.Learn
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Learn();
|
||||
Console.WriteLine("Hello World!");
|
||||
}
|
||||
public static DateTime DateToPredict = DateTime.Now.Date.AddDays(-3);
|
||||
private static void Learn()
|
||||
{
|
||||
var daysAgo = DateToPredict.AddMonths(-3);
|
||||
daysAgo = new DateTime(daysAgo.Year, daysAgo.Month, 1);
|
||||
while (DateToPredict != daysAgo)
|
||||
{
|
||||
var mlContext = new MLContext();
|
||||
var model = Train(mlContext);
|
||||
Evaluate(mlContext, model);
|
||||
UpdatePredictions(mlContext, model);
|
||||
DateToPredict = DateToPredict.AddDays(-1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdatePredictions(MLContext mlContext, ITransformer model)
|
||||
{
|
||||
using (var db = new Db.HorseRacingDataContext())
|
||||
{
|
||||
var races = db.Races.Where(e => e.RaceDate == DateToPredict.Date).ToList();
|
||||
foreach (var race in races)
|
||||
{
|
||||
var runners = db.Runners.Where(e => e.RaceId == race.RaceId && e.DecimalOdds != null).ToList();
|
||||
foreach (var runner in runners)
|
||||
{
|
||||
var fixture = db.Fixtures.FirstOrDefault(e => e.FixtureId == race.FixtureId);
|
||||
if (fixture == null)
|
||||
continue;
|
||||
var prediction = TestSinglePrediction(mlContext, model, new HorseOddsTrainingData()
|
||||
{
|
||||
AgeYears = runner.AgeYears,
|
||||
CourseName = fixture.CourseName,
|
||||
FixtureType = (int)fixture.FixtureType,
|
||||
BhaRating = String.IsNullOrWhiteSpace(runner.BhaRating) ? 0 : int.Parse(runner.BhaRating),
|
||||
CourseWinner = runner.CourseWinner,
|
||||
DecimalOdds = (float)runner.DecimalOdds.Value,
|
||||
DistanceValue = race.DistanceValue,
|
||||
DistanceWinner = runner.DistanceWinner,
|
||||
DivisionSequence = race.DivisionSequence,
|
||||
DrawnStall = runner.DrawnStall ?? 0,
|
||||
FinishTimeInMilliseconds = 0,
|
||||
HeadGearWearingCode = runner.HeadGearWearingCode ?? "Unknown",
|
||||
HeadGearWearingSheepSkin = runner.HeadGearWearingSheepSkin,
|
||||
JockeyName = runner.JockeyName,
|
||||
OwnerName = runner.OwnerName,
|
||||
PenaltyValue = runner.PenaltyValue,
|
||||
PrizeAmount = race.PrizeAmount,
|
||||
RaceClass = race.RaceClass,
|
||||
RaceCriteriaRaceType = race.RaceCriteriaRaceType,
|
||||
RaceDateTime = race.RaceDate + race.RaceTime,
|
||||
RacehorseName = runner.RaceHorseNameWithoutCountry,
|
||||
SexType = (int)runner.SexType,
|
||||
TrainerName = runner.TrainerName,
|
||||
WeightInGrams = (float)runner.WeightInGrams,
|
||||
WeightsJockeyClaiming = runner.WeightsJockeyClaiming,
|
||||
WeightValue = runner.WeightValue,
|
||||
RaceDay = (float)race.RaceDate.Day,
|
||||
RaceMonth = (float)race.RaceDate.Month,
|
||||
RaceYear = (float)race.RaceDate.Year
|
||||
});
|
||||
runner.Prediction = prediction;
|
||||
}
|
||||
}
|
||||
db.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
private static IDataView LoadData(MLContext mlContext, string filter = "")
|
||||
{
|
||||
var loader = mlContext.Data.CreateDatabaseLoader<HorseOddsTrainingData>();
|
||||
|
||||
var sqlCommand = @"SELECT
|
||||
[CourseName]
|
||||
,[FixtureType]
|
||||
,[RaceCriteriaRaceType]
|
||||
,[DistanceValue]
|
||||
,[RaceClass]
|
||||
,[PrizeAmount]
|
||||
,[HeadGearWearingCode]
|
||||
,[HeadGearWearingSheepSkin]
|
||||
,[CourseWinner]
|
||||
,[DistanceWinner]
|
||||
,[RacehorseName]
|
||||
,[TrainerName]
|
||||
,[OwnerName]
|
||||
,[JockeyName]
|
||||
,[WeightsJockeyClaiming]
|
||||
,[DecimalOdds]
|
||||
,[DivisionSequence]
|
||||
,[AgeYears]
|
||||
,[DrawnStall]
|
||||
,[BhaRating]
|
||||
,[WeightValue]
|
||||
,[PenaltyValue]
|
||||
,[SexType]
|
||||
,ISNULL([FinishTimeInMilliseconds],0) as FinishTimeInMilliseconds
|
||||
,[RaceDateTime]
|
||||
,[RaceMonth]
|
||||
,[RaceYear]
|
||||
,[RaceDay]
|
||||
,[WeightInGrams]
|
||||
FROM [dbo].[ResultsView] WHERE DecimalOdds IS NOT NULL " + filter;
|
||||
|
||||
var dbSource = new DatabaseSource(SqlClientFactory.Instance, Db.HorseRacingDataContext.ConnectionString, sqlCommand);
|
||||
var data = loader.Load(dbSource);
|
||||
return data;
|
||||
}
|
||||
|
||||
public static ITransformer Train(MLContext mlContext)
|
||||
{
|
||||
var data = LoadData(mlContext, $"AND FinishTimeInMilliseconds IS NOT NULL AND RaceDate < '{DateToPredict.AddDays(-1).ToString("yyyy/MM/dd", null)}'");
|
||||
//var trainers = new Dictionary<string, ITrainerEstimator<ISingleFeaturePredictionTransformer<object>, object>>()
|
||||
//{
|
||||
// { "FastForest", mlContext.Regression.Trainers.FastForest() },
|
||||
// { "FastTree", mlContext.Regression.Trainers.FastTree() },
|
||||
// { "FastTreeTweedie", mlContext.Regression.Trainers.FastTreeTweedie() },
|
||||
// { "LbfgsPoissonRegression", mlContext.Regression.Trainers.LbfgsPoissonRegression() },
|
||||
// { "Scda", mlContext.Regression.Trainers.Sdca() }
|
||||
//};
|
||||
|
||||
//foreach (var trainer in trainers)
|
||||
//{
|
||||
// var modelPipeline = DataTransform(mlContext);
|
||||
// var pipelineWithTrainer = modelPipeline.Append(trainer.Value);
|
||||
|
||||
// var model = pipelineWithTrainer.Fit(data);
|
||||
// Console.WriteLine($">>>>>>> Evaluating algorithm: {trainer.Key} <<<<<<<");
|
||||
// Evaluate(mlContext, model);
|
||||
//}
|
||||
|
||||
|
||||
Console.WriteLine($"Loading data");
|
||||
var pipeline = DataTransform(mlContext);
|
||||
|
||||
//var pipelineWithTrainer = pipeline.Append(mlContext.Regression.Trainers.LbfgsPoissonRegression());
|
||||
|
||||
var selectedPipelineWithTrainer = pipeline.Append(pipeline.Append(mlContext.Regression.Trainers.LbfgsPoissonRegression()));
|
||||
var finalModel = selectedPipelineWithTrainer.Fit(data);
|
||||
|
||||
return finalModel;
|
||||
}
|
||||
|
||||
private static EstimatorChain<ColumnConcatenatingTransformer> DataTransform(MLContext mlContext)
|
||||
{
|
||||
var pipeline = mlContext.Transforms
|
||||
.CopyColumns(outputColumnName: "Label", inputColumnName: "FinishTimeInMilliseconds")
|
||||
.EncodeColumn(mlContext, "CourseName")
|
||||
.EncodeColumn(mlContext, "FixtureType")
|
||||
.EncodeColumn(mlContext, "RaceCriteriaRaceType")
|
||||
.EncodeColumn(mlContext, "HeadGearWearingCode")
|
||||
.EncodeColumn(mlContext, "RacehorseName")
|
||||
.EncodeColumn(mlContext, "TrainerName")
|
||||
.EncodeColumn(mlContext, "OwnerName")
|
||||
.EncodeColumn(mlContext, "JockeyName")
|
||||
.EncodeColumn(mlContext, "HeadGearWearingSheepSkin")
|
||||
.EncodeColumn(mlContext, "CourseWinner")
|
||||
.EncodeColumn(mlContext, "DistanceWinner")
|
||||
.EncodeColumn(mlContext, "WeightValue")
|
||||
.EncodeColumn(mlContext, "SexType")
|
||||
.Append(mlContext.Transforms.Concatenate("Features",
|
||||
"CourseNameEncoded",
|
||||
"FixtureTypeEncoded",
|
||||
"RaceCriteriaRaceTypeEncoded",
|
||||
"DistanceValue",
|
||||
"RaceClass",
|
||||
"PrizeAmount",
|
||||
"HeadGearWearingCodeEncoded",
|
||||
"HeadGearWearingSheepSkinEncoded",
|
||||
"CourseWinnerEncoded",
|
||||
"DistanceWinnerEncoded",
|
||||
"RacehorseNameEncoded",
|
||||
"TrainerNameEncoded",
|
||||
"OwnerNameEncoded",
|
||||
"JockeyNameEncoded",
|
||||
"WeightsJockeyClaiming",
|
||||
"DecimalOdds",
|
||||
"DivisionSequence",
|
||||
"AgeYears",
|
||||
"DrawnStall",
|
||||
"WeightValueEncoded",
|
||||
"PenaltyValue",
|
||||
"SexTypeEncoded",
|
||||
"RaceMonth",
|
||||
"RaceYear",
|
||||
"RaceDay"));
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
private static RegressionMetrics Evaluate(MLContext mlContext, ITransformer model)
|
||||
{
|
||||
var dataView = LoadData(mlContext, $"AND FinishTimeInMilliseconds IS NOT NULL AND RaceDate = '{DateToPredict.AddDays(-1).ToString("yyyy/MM/dd", null)}'");
|
||||
var predictions = model.Transform(dataView);
|
||||
var metrics = mlContext.Regression.Evaluate(predictions, "Label", "Score");
|
||||
Console.WriteLine();
|
||||
|
||||
|
||||
var result = $"* Model quality metrics evaluation R2: {metrics.RSquared:0.####} Root Mean Squared Error: {metrics.RootMeanSquaredError:#.####} *";
|
||||
var stars = String.Concat(Enumerable.Range(0, result.Length).Select(e => "*"));
|
||||
|
||||
Console.WriteLine(stars);
|
||||
Console.WriteLine(result);
|
||||
Console.WriteLine(stars);
|
||||
|
||||
Console.WriteLine();
|
||||
return metrics;
|
||||
}
|
||||
|
||||
private static float TestSinglePrediction(MLContext mlContext, ITransformer model, HorseOddsTrainingData values)
|
||||
{
|
||||
var predictionFunction = mlContext.Model.CreatePredictionEngine<HorseOddsTrainingData, HorseOddsTrainingPrediction>(model);
|
||||
var prediction = predictionFunction.Predict(values);
|
||||
Console.WriteLine($"Predicted time for {values.RacehorseName}: {prediction.FinishTimeInMilliseconds}");
|
||||
return prediction.FinishTimeInMilliseconds;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user