diff --git a/.gitignore b/.gitignore index bb2a22d40..47e675a3a 100644 --- a/.gitignore +++ b/.gitignore @@ -246,11 +246,6 @@ UpgradeLog*.XML UpgradeLog*.htm ServiceFabricBackup/ -# SQL Server files -*.mdf -*.ldf -*.ndf - # Business Intelligence projects *.rdl.data *.bim.layout diff --git a/samples/csharp/getting-started/DatabaseLoader/DatabaseLoader.sln b/samples/csharp/getting-started/DatabaseLoader/DatabaseLoader.sln new file mode 100644 index 000000000..65fd8d094 --- /dev/null +++ b/samples/csharp/getting-started/DatabaseLoader/DatabaseLoader.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28803.452 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DatabaseLoaderConsoleApp", "DatabaseLoaderConsoleApp\DatabaseLoaderConsoleApp.csproj", "{9058A1BB-87A6-4A9A-A3B2-F2C81CB9B9EA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9058A1BB-87A6-4A9A-A3B2-F2C81CB9B9EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9058A1BB-87A6-4A9A-A3B2-F2C81CB9B9EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9058A1BB-87A6-4A9A-A3B2-F2C81CB9B9EA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9058A1BB-87A6-4A9A-A3B2-F2C81CB9B9EA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5B3ACA76-DA8A-40E8-A097-B51EF1BB9D12} + EndGlobalSection +EndGlobal diff --git a/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/Common/ConsoleHelper.cs b/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/Common/ConsoleHelper.cs new file mode 100644 index 000000000..2039c6f3a --- /dev/null +++ b/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/Common/ConsoleHelper.cs @@ -0,0 +1,293 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using Microsoft.ML.Data; +using Microsoft.ML; +using static Microsoft.ML.TrainCatalogBase; +using System.Diagnostics; + +namespace Common +{ + public static class ConsoleHelper + { + public static void PrintPrediction(string prediction) + { + Console.WriteLine($"*************************************************"); + Console.WriteLine($"Predicted : {prediction}"); + Console.WriteLine($"*************************************************"); + } + + public static void PrintRegressionPredictionVersusObserved(string predictionCount, string observedCount) + { + Console.WriteLine($"-------------------------------------------------"); + Console.WriteLine($"Predicted : {predictionCount}"); + Console.WriteLine($"Actual: {observedCount}"); + Console.WriteLine($"-------------------------------------------------"); + } + + public static void PrintRegressionMetrics(string name, RegressionMetrics metrics) + { + Console.WriteLine($"*************************************************"); + Console.WriteLine($"* Metrics for {name} regression model "); + Console.WriteLine($"*------------------------------------------------"); + Console.WriteLine($"* LossFn: {metrics.LossFunction:0.##}"); + Console.WriteLine($"* R2 Score: {metrics.RSquared:0.##}"); + Console.WriteLine($"* Absolute loss: {metrics.MeanAbsoluteError:#.##}"); + Console.WriteLine($"* Squared loss: {metrics.MeanSquaredError:#.##}"); + Console.WriteLine($"* RMS loss: {metrics.RootMeanSquaredError:#.##}"); + Console.WriteLine($"*************************************************"); + } + + public static void PrintBinaryClassificationMetrics(string name, CalibratedBinaryClassificationMetrics metrics) + { + Console.WriteLine($"************************************************************"); + Console.WriteLine($"* Metrics for {name} binary classification model "); + Console.WriteLine($"*-----------------------------------------------------------"); + Console.WriteLine($"* Accuracy: {metrics.Accuracy:P2}"); + Console.WriteLine($"* Area Under Curve: {metrics.AreaUnderRocCurve:P2}"); + Console.WriteLine($"* Area under Precision recall Curve: {metrics.AreaUnderPrecisionRecallCurve:P2}"); + Console.WriteLine($"* F1Score: {metrics.F1Score:P2}"); + Console.WriteLine($"* LogLoss: {metrics.LogLoss:#.##}"); + Console.WriteLine($"* LogLossReduction: {metrics.LogLossReduction:#.##}"); + Console.WriteLine($"* PositivePrecision: {metrics.PositivePrecision:#.##}"); + Console.WriteLine($"* PositiveRecall: {metrics.PositiveRecall:#.##}"); + Console.WriteLine($"* NegativePrecision: {metrics.NegativePrecision:#.##}"); + Console.WriteLine($"* NegativeRecall: {metrics.NegativeRecall:P2}"); + Console.WriteLine($"************************************************************"); + } + + public static void PrintMultiClassClassificationMetrics(string name, MulticlassClassificationMetrics metrics) + { + Console.WriteLine($"************************************************************"); + Console.WriteLine($"* Metrics for {name} multi-class classification model "); + Console.WriteLine($"*-----------------------------------------------------------"); + Console.WriteLine($" AccuracyMacro = {metrics.MacroAccuracy:0.####}, a value between 0 and 1, the closer to 1, the better"); + Console.WriteLine($" AccuracyMicro = {metrics.MicroAccuracy:0.####}, a value between 0 and 1, the closer to 1, the better"); + Console.WriteLine($" LogLoss = {metrics.LogLoss:0.####}, the closer to 0, the better"); + Console.WriteLine($" LogLoss for class 1 = {metrics.PerClassLogLoss[0]:0.####}, the closer to 0, the better"); + Console.WriteLine($" LogLoss for class 2 = {metrics.PerClassLogLoss[1]:0.####}, the closer to 0, the better"); + Console.WriteLine($" LogLoss for class 3 = {metrics.PerClassLogLoss[2]:0.####}, the closer to 0, the better"); + Console.WriteLine($"************************************************************"); + } + + public static void PrintRegressionFoldsAverageMetrics(string algorithmName, IReadOnlyList> crossValidationResults) + { + var L1 = crossValidationResults.Select(r => r.Metrics.MeanAbsoluteError); + var L2 = crossValidationResults.Select(r => r.Metrics.MeanSquaredError); + var RMS = crossValidationResults.Select(r => r.Metrics.RootMeanSquaredError); + var lossFunction = crossValidationResults.Select(r => r.Metrics.LossFunction); + var R2 = crossValidationResults.Select(r => r.Metrics.RSquared); + + Console.WriteLine($"*************************************************************************************************************"); + Console.WriteLine($"* Metrics for {algorithmName} Regression model "); + Console.WriteLine($"*------------------------------------------------------------------------------------------------------------"); + Console.WriteLine($"* Average L1 Loss: {L1.Average():0.###} "); + Console.WriteLine($"* Average L2 Loss: {L2.Average():0.###} "); + Console.WriteLine($"* Average RMS: {RMS.Average():0.###} "); + Console.WriteLine($"* Average Loss Function: {lossFunction.Average():0.###} "); + Console.WriteLine($"* Average R-squared: {R2.Average():0.###} "); + Console.WriteLine($"*************************************************************************************************************"); + } + + public static void PrintMulticlassClassificationFoldsAverageMetrics( + string algorithmName, + IReadOnlyList> crossValResults + ) + { + var metricsInMultipleFolds = crossValResults.Select(r => r.Metrics); + + var microAccuracyValues = metricsInMultipleFolds.Select(m => m.MicroAccuracy); + var microAccuracyAverage = microAccuracyValues.Average(); + var microAccuraciesStdDeviation = CalculateStandardDeviation(microAccuracyValues); + var microAccuraciesConfidenceInterval95 = CalculateConfidenceInterval95(microAccuracyValues); + + var macroAccuracyValues = metricsInMultipleFolds.Select(m => m.MacroAccuracy); + var macroAccuracyAverage = macroAccuracyValues.Average(); + var macroAccuraciesStdDeviation = CalculateStandardDeviation(macroAccuracyValues); + var macroAccuraciesConfidenceInterval95 = CalculateConfidenceInterval95(macroAccuracyValues); + + var logLossValues = metricsInMultipleFolds.Select(m => m.LogLoss); + var logLossAverage = logLossValues.Average(); + var logLossStdDeviation = CalculateStandardDeviation(logLossValues); + var logLossConfidenceInterval95 = CalculateConfidenceInterval95(logLossValues); + + var logLossReductionValues = metricsInMultipleFolds.Select(m => m.LogLossReduction); + var logLossReductionAverage = logLossReductionValues.Average(); + var logLossReductionStdDeviation = CalculateStandardDeviation(logLossReductionValues); + var logLossReductionConfidenceInterval95 = CalculateConfidenceInterval95(logLossReductionValues); + + Console.WriteLine($"*************************************************************************************************************"); + Console.WriteLine($"* Metrics for {algorithmName} Multi-class Classification model "); + Console.WriteLine($"*------------------------------------------------------------------------------------------------------------"); + Console.WriteLine($"* Average MicroAccuracy: {microAccuracyAverage:0.###} - Standard deviation: ({microAccuraciesStdDeviation:#.###}) - Confidence Interval 95%: ({microAccuraciesConfidenceInterval95:#.###})"); + Console.WriteLine($"* Average MacroAccuracy: {macroAccuracyAverage:0.###} - Standard deviation: ({macroAccuraciesStdDeviation:#.###}) - Confidence Interval 95%: ({macroAccuraciesConfidenceInterval95:#.###})"); + Console.WriteLine($"* Average LogLoss: {logLossAverage:#.###} - Standard deviation: ({logLossStdDeviation:#.###}) - Confidence Interval 95%: ({logLossConfidenceInterval95:#.###})"); + Console.WriteLine($"* Average LogLossReduction: {logLossReductionAverage:#.###} - Standard deviation: ({logLossReductionStdDeviation:#.###}) - Confidence Interval 95%: ({logLossReductionConfidenceInterval95:#.###})"); + Console.WriteLine($"*************************************************************************************************************"); + + } + + public static double CalculateStandardDeviation (IEnumerable values) + { + double average = values.Average(); + double sumOfSquaresOfDifferences = values.Select(val => (val - average) * (val - average)).Sum(); + double standardDeviation = Math.Sqrt(sumOfSquaresOfDifferences / (values.Count()-1)); + return standardDeviation; + } + + public static double CalculateConfidenceInterval95(IEnumerable values) + { + double confidenceInterval95 = 1.96 * CalculateStandardDeviation(values) / Math.Sqrt((values.Count()-1)); + return confidenceInterval95; + } + + public static void PrintClusteringMetrics(string name, ClusteringMetrics metrics) + { + Console.WriteLine($"*************************************************"); + Console.WriteLine($"* Metrics for {name} clustering model "); + Console.WriteLine($"*------------------------------------------------"); + Console.WriteLine($"* Average Distance: {metrics.AverageDistance}"); + Console.WriteLine($"* Davies Bouldin Index is: {metrics.DaviesBouldinIndex}"); + Console.WriteLine($"*************************************************"); + } + + public static void ShowDataViewInConsole(MLContext mlContext, IDataView dataView, int numberOfRows = 4) + { + string msg = string.Format("Show data in DataView: Showing {0} rows with the columns", numberOfRows.ToString()); + ConsoleWriteHeader(msg); + + var preViewTransformedData = dataView.Preview(maxRows: numberOfRows); + + foreach (var row in preViewTransformedData.RowView) + { + var ColumnCollection = row.Values; + string lineToPrint = "Row--> "; + foreach (KeyValuePair column in ColumnCollection) + { + lineToPrint += $"| {column.Key}:{column.Value}"; + } + Console.WriteLine(lineToPrint + "\n"); + } + } + + [Conditional("DEBUG")] + // This method using 'DebuggerExtensions.Preview()' should only be used when debugging/developing, not for release/production trainings + public static void PeekDataViewInConsole(MLContext mlContext, IDataView dataView, IEstimator pipeline, int numberOfRows = 4) + { + string msg = string.Format("Peek data in DataView: Showing {0} rows with the columns", numberOfRows.ToString()); + ConsoleWriteHeader(msg); + + //https://github.com/dotnet/machinelearning/blob/master/docs/code/MlNetCookBook.md#how-do-i-look-at-the-intermediate-data + var transformer = pipeline.Fit(dataView); + var transformedData = transformer.Transform(dataView); + + // 'transformedData' is a 'promise' of data, lazy-loading. call Preview + //and iterate through the returned collection from preview. + + var preViewTransformedData = transformedData.Preview(maxRows: numberOfRows); + + foreach (var row in preViewTransformedData.RowView) + { + var ColumnCollection = row.Values; + string lineToPrint = "Row--> "; + foreach (KeyValuePair column in ColumnCollection) + { + lineToPrint += $"| {column.Key}:{column.Value}"; + } + Console.WriteLine(lineToPrint + "\n"); + } + } + + [Conditional("DEBUG")] + // This method using 'DebuggerExtensions.Preview()' should only be used when debugging/developing, not for release/production trainings + public static void PeekVectorColumnDataInConsole(MLContext mlContext, string columnName, IDataView dataView, IEstimator pipeline, int numberOfRows = 4) + { + string msg = string.Format("Peek data in DataView: : Show {0} rows with just the '{1}' column", numberOfRows, columnName ); + ConsoleWriteHeader(msg); + + var transformer = pipeline.Fit(dataView); + var transformedData = transformer.Transform(dataView); + + // Extract the 'Features' column. + var someColumnData = transformedData.GetColumn(columnName) + .Take(numberOfRows).ToList(); + + // print to console the peeked rows + someColumnData.ForEach(row => { + String concatColumn = String.Empty; + foreach (float f in row) + { + concatColumn += f.ToString(); + } + Console.WriteLine(concatColumn); + }); + } + + public static void ConsoleWriteHeader(params string[] lines) + { + var defaultColor = Console.ForegroundColor; + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine(" "); + foreach (var line in lines) + { + Console.WriteLine(line); + } + var maxLength = lines.Select(x => x.Length).Max(); + Console.WriteLine(new string('#', maxLength)); + Console.ForegroundColor = defaultColor; + } + + public static void ConsoleWriterSection(params string[] lines) + { + var defaultColor = Console.ForegroundColor; + Console.ForegroundColor = ConsoleColor.Blue; + Console.WriteLine(" "); + foreach (var line in lines) + { + Console.WriteLine(line); + } + var maxLength = lines.Select(x => x.Length).Max(); + Console.WriteLine(new string('-', maxLength)); + Console.ForegroundColor = defaultColor; + } + + public static void ConsolePressAnyKey() + { + var defaultColor = Console.ForegroundColor; + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine(" "); + Console.WriteLine("Press any key to finish."); + Console.ReadKey(); + } + + public static void ConsoleWriteException(params string[] lines) + { + var defaultColor = Console.ForegroundColor; + Console.ForegroundColor = ConsoleColor.Red; + const string exceptionTitle = "EXCEPTION"; + Console.WriteLine(" "); + Console.WriteLine(exceptionTitle); + Console.WriteLine(new string('#', exceptionTitle.Length)); + Console.ForegroundColor = defaultColor; + foreach (var line in lines) + { + Console.WriteLine(line); + } + } + + public static void ConsoleWriteWarning(params string[] lines) + { + var defaultColor = Console.ForegroundColor; + Console.ForegroundColor = ConsoleColor.DarkMagenta; + const string warningTitle = "WARNING"; + Console.WriteLine(" "); + Console.WriteLine(warningTitle); + Console.WriteLine(new string('#', warningTitle.Length)); + Console.ForegroundColor = defaultColor; + foreach (var line in lines) + { + Console.WriteLine(line); + } + } + } +} diff --git a/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/DataModels/ClickPrediction.cs b/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/DataModels/ClickPrediction.cs new file mode 100644 index 000000000..731c2d590 --- /dev/null +++ b/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/DataModels/ClickPrediction.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace DatabaseLoaderConsoleApp.DataModels +{ + public class ClickPrediction + { + public bool PredictedLabel; + + public float Score; + } +} diff --git a/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/DataModels/UrlClick.cs b/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/DataModels/UrlClick.cs new file mode 100644 index 000000000..56d566a9c --- /dev/null +++ b/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/DataModels/UrlClick.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace DatabaseLoaderConsoleApp.DataModels +{ + public class UrlClick + { + public string Label { get; set; } + public string Feat01 { get; set; } + public string Feat02 { get; set; } + public string Feat03 { get; set; } + public string Feat04 { get; set; } + public string Feat05 { get; set; } + public string Feat06 { get; set; } + public string Feat07 { get; set; } + public string Feat08 { get; set; } + public string Feat09 { get; set; } + public string Feat10 { get; set; } + public string Feat11 { get; set; } + public string Feat12 { get; set; } + public string Feat13 { get; set; } + public string Cat14 { get; set; } + public string Cat15 { get; set; } + public string Cat16 { get; set; } + public string Cat17 { get; set; } + public string Cat18 { get; set; } + public string Cat19 { get; set; } + public string Cat20 { get; set; } + public string Cat21 { get; set; } + public string Cat22 { get; set; } + public string Cat23 { get; set; } + public string Cat24 { get; set; } + public string Cat25 { get; set; } + public string Cat26 { get; set; } + public string Cat27 { get; set; } + public string Cat28 { get; set; } + public string Cat29 { get; set; } + public string Cat30 { get; set; } + public string Cat31 { get; set; } + public string Cat32 { get; set; } + public string Cat33 { get; set; } + public string Cat34 { get; set; } + public string Cat35 { get; set; } + public string Cat36 { get; set; } + public string Cat37 { get; set; } + public string Cat38 { get; set; } + public string Cat39 { get; set; } + } +} diff --git a/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/DatabaseLoaderConsoleApp.csproj b/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/DatabaseLoaderConsoleApp.csproj new file mode 100644 index 000000000..ad21e6c6a --- /dev/null +++ b/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/DatabaseLoaderConsoleApp.csproj @@ -0,0 +1,32 @@ + + + + Exe + + $(RestoreSources); + + netcoreapp2.1 + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + + diff --git a/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/Program.cs b/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/Program.cs new file mode 100644 index 000000000..6228601da --- /dev/null +++ b/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/Program.cs @@ -0,0 +1,195 @@ +using Common; +using DatabaseLoaderConsoleApp.DataModels; +using Microsoft.ML; +using Microsoft.ML.Data; +using Microsoft.ML.Transforms; +using System; +using System.Collections; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; + +namespace DatabaseLoaderConsoleApp +{ + public class Program + { + public static void Main() + { + var mlContext = new MLContext(); + + // localdb SQL database connection string using a filepath to attach the database file into localdb + string dbFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SqlLocalDb", "Criteo-100k-rows.mdf"); + string connectionString = $"Data Source = (LocalDB)\\MSSQLLocalDB;AttachDbFilename={dbFilePath};Database=Criteo-100k-rows;Integrated Security = True"; + + // ConnString Example: localdb SQL database connection string for 'localdb default location' (usually files located at /Users/YourUser/) + //string connectionString = @"Data Source=(localdb)\MSSQLLocalDb;Initial Catalog=YOUR_DATABASE;Integrated Security=True;Pooling=False"; + // + // ConnString Example: on-premises SQL Server Database (Integrated security) + //string connectionString = @"Data Source=YOUR_SERVER;Initial Catalog=YOUR_DATABASE;Integrated Security=True;Pooling=False"; + // + // ConnString Example: Azure SQL Database connection string + //string connectionString = @"Server=tcp:yourserver.database.windows.net,1433; Initial Catalog = YOUR_DATABASE; Persist Security Info = False; User ID = YOUR_USER; Password = YOUR_PASSWORD; MultipleActiveResultSets = False; Encrypt = True; TrustServerCertificate = False; Connection Timeout = 60; ConnectRetryCount = 5; ConnectRetryInterval = 10;"; + + string commandText = "SELECT * from URLClicks"; + + DatabaseLoader loader = mlContext.Data.CreateDatabaseLoader(); + + DatabaseSource dbSource = new DatabaseSource(SqlClientFactory.Instance, + connectionString, + commandText); + + IDataView dataView = loader.Load(dbSource); + + var trainTestData = mlContext.Data.TrainTestSplit(dataView); + + //do the transformation in IDataView + //Transform categorical features into binary + var CatogoriesTranformer = mlContext.Transforms.Conversion.ConvertType(nameof(UrlClick.Label), outputKind:Microsoft.ML.Data.DataKind.Boolean). + Append(mlContext.Transforms.Categorical.OneHotEncoding(new[] { + new InputOutputColumnPair("Cat14Encoded", "Cat14"), + new InputOutputColumnPair("Cat15Encoded", "Cat15"), + new InputOutputColumnPair("Cat16Encoded", "Cat16"), + new InputOutputColumnPair("Cat17Encoded", "Cat17"), + new InputOutputColumnPair("Cat18Encoded", "Cat18"), + new InputOutputColumnPair("Cat19Encoded", "Cat19"), + new InputOutputColumnPair("Cat20Encoded", "Cat20"), + new InputOutputColumnPair("Cat21Encoded", "Cat21"), + new InputOutputColumnPair("Cat22Encoded", "Cat22"), + new InputOutputColumnPair("Cat23Encoded", "Cat23"), + new InputOutputColumnPair("Cat24Encoded", "Cat24"), + new InputOutputColumnPair("Cat25Encoded", "Cat25"), + new InputOutputColumnPair("Cat26Encoded", "Cat26"), + new InputOutputColumnPair("Cat27Encoded", "Cat27"), + new InputOutputColumnPair("Cat28Encoded", "Cat28"), + new InputOutputColumnPair("Cat29Encoded", "Cat29"), + new InputOutputColumnPair("Cat30Encoded", "Cat30"), + new InputOutputColumnPair("Cat31Encoded", "Cat31"), + new InputOutputColumnPair("Cat32Encoded", "Cat32"), + new InputOutputColumnPair("Cat33Encoded", "Cat33"), + new InputOutputColumnPair("Cat34Encoded", "Cat34"), + new InputOutputColumnPair("Cat35Encoded", "Cat35"), + new InputOutputColumnPair("Cat36Encoded", "Cat36"), + new InputOutputColumnPair("Cat37Encoded", "Cat37"), + new InputOutputColumnPair("Cat38Encoded", "Cat38"), + new InputOutputColumnPair("Cat39Encoded", "Cat39") + }, OneHotEncodingEstimator.OutputKind.Binary)); + + var featuresTransformer = CatogoriesTranformer.Append( + mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Feat01Featurized", inputColumnName: nameof(UrlClick.Feat01))) + .Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Feat02Featurized", inputColumnName: nameof(UrlClick.Feat02))) + .Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Feat03Featurized", inputColumnName: nameof(UrlClick.Feat03))) + .Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Feat04Featurized", inputColumnName: nameof(UrlClick.Feat04))) + .Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Feat05Featurized", inputColumnName: nameof(UrlClick.Feat05))) + .Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Feat06Featurized", inputColumnName: nameof(UrlClick.Feat06))) + .Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Feat07Featurized", inputColumnName: nameof(UrlClick.Feat07))) + .Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Feat08Featurized", inputColumnName: nameof(UrlClick.Feat08))) + .Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Feat09Featurized", inputColumnName: nameof(UrlClick.Feat09))) + .Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Feat10Featurized", inputColumnName: nameof(UrlClick.Feat10))) + .Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Feat11Featurized", inputColumnName: nameof(UrlClick.Feat11))) + .Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Feat12Featurized", inputColumnName: nameof(UrlClick.Feat12))) + .Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Feat13Featurized", inputColumnName: nameof(UrlClick.Feat13))); + + var finalTransformerPipeLine = featuresTransformer.Append(mlContext.Transforms.Concatenate("Features", + "Feat01Featurized", "Feat02Featurized", "Feat03Featurized", "Feat04Featurized", "Feat05Featurized", + "Feat06Featurized", "Feat07Featurized", "Feat08Featurized", "Feat09Featurized", "Feat10Featurized", + "Feat11Featurized", "Feat12Featurized", "Feat12Featurized", + "Cat14Encoded", "Cat15Encoded", "Cat16Encoded", "Cat17Encoded", "Cat18Encoded", "Cat19Encoded", + "Cat20Encoded", "Cat21Encoded", "Cat22Encoded", "Cat23Encoded", "Cat24Encoded", "Cat25Encoded", + "Cat26Encoded", "Cat27Encoded", "Cat28Encoded", "Cat29Encoded", "Cat30Encoded", "Cat31Encoded", + "Cat32Encoded", "Cat33Encoded", "Cat34Encoded", "Cat35Encoded", "Cat36Encoded", "Cat37Encoded", + "Cat38Encoded", "Cat39Encoded")); + + // Apply the ML algorithm + var trainingPipeLine = finalTransformerPipeLine.Append(mlContext.BinaryClassification.Trainers.FieldAwareFactorizationMachine(labelColumnName: "Label", featureColumnName: "Features")); + + Console.WriteLine("Training the ML model while streaming data from a SQL database..."); + Stopwatch watch = new Stopwatch(); + watch.Start(); + + var model = trainingPipeLine.Fit(trainTestData.TrainSet); + + watch.Stop(); + Console.WriteLine("Elapsed time for training the model = {0} seconds", watch.ElapsedMilliseconds/1000); + + Console.WriteLine("Evaluating the model..."); + Stopwatch watch2 = new Stopwatch(); + watch2.Start(); + + var predictions = model.Transform(trainTestData.TestSet); + // Now that we have the test predictions, calculate the metrics of those predictions and output the results. + var metrics = mlContext.BinaryClassification.Evaluate(predictions); + + watch2.Stop(); + Console.WriteLine("Elapsed time for evaluating the model = {0} seconds", watch2.ElapsedMilliseconds / 1000); + + ConsoleHelper.PrintBinaryClassificationMetrics("==== Evaluation Metrics training from a Database ====", metrics); + + // + Console.WriteLine("Trying a single prediction:"); + + var predictionEngine = mlContext.Model.CreatePredictionEngine(model); + + UrlClick sampleData = new UrlClick() { + Label = String.Empty, + Feat01 = "32", Feat02 = "3", Feat03 = "5", Feat04 = "NULL", Feat05 = "1", + Feat06 = "0", Feat07 = "0", Feat08 = "61", Feat09 = "5", Feat10 = "0", + Feat11 = "1", Feat12 = "3157", Feat13 = "5", + Cat14 = "e5f3fd8d", Cat15 = "a0aaffa6", Cat16 = "aa15d56f", Cat17 = "da8a3421", + Cat18 = "cd69f233", Cat19 = "6fcd6dcb", Cat20 = "ab16ed81", Cat21 = "43426c29", + Cat22 = "1df5e154", Cat23 = "00c5ffb7", Cat24 = "be4ee537", Cat25 = "f3bbfe99", + Cat26 = "7de9c0a9", Cat27 = "6652dc64", Cat28 = "99eb4e27", Cat29 = "4cdc3efa", + Cat30 = "d20856aa", Cat31 = "a1eb1511", Cat32 = "9512c20b", Cat33 = "febfd863", + Cat34 = "a3323ca1", Cat35 = "c8e1ee56", Cat36 = "1752e9e8", Cat37 = "75350c8a", + Cat38 = "991321ea", Cat39 = "b757e957" + }; + + var clickPrediction = predictionEngine.Predict(sampleData); + + Console.WriteLine($"Predicted Label: {clickPrediction.PredictedLabel} - Score:{Sigmoid(clickPrediction.Score)}", Color.YellowGreen); + Console.WriteLine(); + + //*** Detach database from localdb only if you used a conn-string with a filepath to attach the database file into localdb *** + Console.WriteLine("... Detaching database from SQL localdb ..."); + DetachDatabase(connectionString); + + Console.WriteLine("=============== Press any key ==============="); + Console.ReadKey(); + } + + public static float Sigmoid(float x) + { + return (float)(100 / (1 + Math.Exp(-x))); + } + + public static void DetachDatabase(string userConnectionString) //DELETE PARAM ************* + { + string dbName = string.Empty; + using (SqlConnection userSqlDatabaseConnection = new SqlConnection(userConnectionString)) + { + userSqlDatabaseConnection.Open(); + dbName = userSqlDatabaseConnection.Database; + } + + string masterConnString = $"Data Source = (LocalDB)\\MSSQLLocalDB;Integrated Security = True"; + using (SqlConnection sqlDatabaseConnection = new SqlConnection(masterConnString)) + { + sqlDatabaseConnection.Open(); + + string prepareDbcommandString = $"ALTER DATABASE [{dbName}] SET OFFLINE WITH ROLLBACK IMMEDIATE ALTER DATABASE [{dbName}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE"; + //(ALTERNATIVE) string prepareDbcommandString = $"ALTER DATABASE [{dbName}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE"; + SqlCommand sqlPrepareCommand = new SqlCommand(prepareDbcommandString, sqlDatabaseConnection); + sqlPrepareCommand.ExecuteNonQuery(); + + string detachCommandString = "sp_detach_db"; + SqlCommand sqlDetachCommand = new SqlCommand(detachCommandString, sqlDatabaseConnection); + sqlDetachCommand.CommandType = CommandType.StoredProcedure; + sqlDetachCommand.Parameters.AddWithValue("@dbname", dbName); + sqlDetachCommand.ExecuteNonQuery(); + } + } + } +} \ No newline at end of file diff --git a/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/SqlLocalDb/Criteo-100k-rows.mdf b/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/SqlLocalDb/Criteo-100k-rows.mdf new file mode 100644 index 000000000..9e7024e5d Binary files /dev/null and b/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/SqlLocalDb/Criteo-100k-rows.mdf differ diff --git a/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/SqlLocalDb/Criteo-100k-rows_log.ldf b/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/SqlLocalDb/Criteo-100k-rows_log.ldf new file mode 100644 index 000000000..2ead86504 Binary files /dev/null and b/samples/csharp/getting-started/DatabaseLoader/DatabaseLoaderConsoleApp/SqlLocalDb/Criteo-100k-rows_log.ldf differ diff --git a/samples/csharp/getting-started/DatabaseLoader/README.md b/samples/csharp/getting-started/DatabaseLoader/README.md new file mode 100644 index 000000000..7d7330e57 --- /dev/null +++ b/samples/csharp/getting-started/DatabaseLoader/README.md @@ -0,0 +1,2 @@ + +TBD \ No newline at end of file diff --git a/samples/nuget.config b/samples/nuget.config index 08f9e043b..f08d30390 100644 --- a/samples/nuget.config +++ b/samples/nuget.config @@ -3,7 +3,6 @@ -