diff --git a/src/mlnet.Test/CommandLineTests.cs b/src/mlnet.Test/CommandLineTests.cs index 714b2ea318..b0d805f731 100644 --- a/src/mlnet.Test/CommandLineTests.cs +++ b/src/mlnet.Test/CommandLineTests.cs @@ -31,7 +31,7 @@ public void TestMinimumCommandLineArgs() var parser = new CommandLineBuilder() // Parser - .AddCommand(CommandDefinitions.New(handler)) + .AddCommand(CommandDefinitions.AutoTrain(handler)) .UseDefaults() .UseExceptionHandler((e, ctx) => { @@ -41,7 +41,7 @@ public void TestMinimumCommandLineArgs() var trainDataset = Path.GetTempFileName(); var testDataset = Path.GetTempFileName(); - string[] args = new[] { "new", "--ml-task", "binary-classification", "--dataset", trainDataset, "--label-column-name", "Label" }; + string[] args = new[] { "auto-train", "--ml-task", "binary-classification", "--dataset", trainDataset, "--label-column-name", "Label" }; parser.InvokeAsync(args).Wait(); File.Delete(trainDataset); File.Delete(testDataset); @@ -63,7 +63,7 @@ public void TestCommandLineArgsFailTest() var parser = new CommandLineBuilder() // parser - .AddCommand(CommandDefinitions.New(handler)) + .AddCommand(CommandDefinitions.AutoTrain(handler)) .UseDefaults() .UseExceptionHandler((e, ctx) => { @@ -76,22 +76,22 @@ public void TestCommandLineArgsFailTest() var testDataset = Path.GetTempFileName(); //wrong value to ml-task - string[] args = new[] { "new", "--ml-task", "bad-value", "--train-dataset", trainDataset, "--label-column-name", "Label" }; + string[] args = new[] { "auto-train", "--ml-task", "bad-value", "--train-dataset", trainDataset, "--label-column-name", "Label" }; parser.InvokeAsync(args).Wait(); Assert.IsFalse(parsingSuccessful); // Incorrect invocation - args = new[] { "new", "binary-classification", "--train-dataset", trainDataset, "--label-column-name", "Label" }; + args = new[] { "auto-train", "binary-classification", "--train-dataset", trainDataset, "--label-column-name", "Label" }; parser.InvokeAsync(args).Wait(); Assert.IsFalse(parsingSuccessful); // Non-existent file test - args = new[] { "new", "--ml-task", "binary-classification", "--train-dataset", "nonexistentfile.csv", "--label-column-name", "Label" }; + args = new[] { "auto-train", "--ml-task", "binary-classification", "--train-dataset", "nonexistentfile.csv", "--label-column-name", "Label" }; parser.InvokeAsync(args).Wait(); Assert.IsFalse(parsingSuccessful); // No label column or index test - args = new[] { "new", "--ml-task", "binary-classification", "--train-dataset", trainDataset, "--test-dataset", testDataset }; + args = new[] { "auto-train", "--ml-task", "binary-classification", "--train-dataset", trainDataset, "--test-dataset", testDataset }; parser.InvokeAsync(args).Wait(); File.Delete(trainDataset); File.Delete(testDataset); @@ -128,7 +128,7 @@ public void TestCommandLineArgsValuesTest() var parser = new CommandLineBuilder() // Parser - .AddCommand(CommandDefinitions.New(handler)) + .AddCommand(CommandDefinitions.AutoTrain(handler)) .UseDefaults() .UseExceptionHandler((e, ctx) => { @@ -137,7 +137,7 @@ public void TestCommandLineArgsValuesTest() .Build(); // Incorrect mltask test - string[] args = new[] { "new", "--ml-task", "binary-classification", "--dataset", trainDataset, "--label-column-name", labelName, "--validation-dataset", validDataset, "--test-dataset", testDataset, "--max-exploration-time", "5", "--name", name, "--output-path", outputPath, "--has-header", falseString }; + string[] args = new[] { "auto-train", "--ml-task", "binary-classification", "--dataset", trainDataset, "--label-column-name", labelName, "--validation-dataset", validDataset, "--test-dataset", testDataset, "--max-exploration-time", "5", "--name", name, "--output-path", outputPath, "--has-header", falseString }; parser.InvokeAsync(args).Wait(); File.Delete(trainDataset); File.Delete(testDataset); @@ -164,7 +164,7 @@ public void TestCommandLineArgsMutuallyExclusiveArgsTest() var parser = new CommandLineBuilder() // Parser - .AddCommand(CommandDefinitions.New(handler)) + .AddCommand(CommandDefinitions.AutoTrain(handler)) .UseDefaults() .UseExceptionHandler((e, ctx) => { @@ -173,17 +173,17 @@ public void TestCommandLineArgsMutuallyExclusiveArgsTest() .Build(); // Incorrect arguments : specifying dataset and train-dataset - string[] args = new[] { "new", "--ml-task", "BinaryClassification", "--dataset", dataset, "--train-dataset", trainDataset, "--label-column-name", labelName, "--test-dataset", testDataset, "--max-exploration-time", "5" }; + string[] args = new[] { "auto-train", "--ml-task", "BinaryClassification", "--dataset", dataset, "--train-dataset", trainDataset, "--label-column-name", labelName, "--test-dataset", testDataset, "--max-exploration-time", "5" }; parser.InvokeAsync(args).Wait(); Assert.IsFalse(parsingSuccessful); // Incorrect arguments : specifying train-dataset and not specifying test-dataset - args = new[] { "new", "--ml-task", "BinaryClassification", "--train-dataset", trainDataset, "--label-column-name", labelName, "--max-exploration-time", "5" }; + args = new[] { "auto-train", "--ml-task", "BinaryClassification", "--train-dataset", trainDataset, "--label-column-name", labelName, "--max-exploration-time", "5" }; parser.InvokeAsync(args).Wait(); Assert.IsFalse(parsingSuccessful); // Incorrect arguments : specifying label column name and index - args = new[] { "new", "--ml-task", "BinaryClassification", "--train-dataset", trainDataset, "--label-column-name", labelName, "--label-column-index", "0", "--test-dataset", testDataset, "--max-exploration-time", "5" }; + args = new[] { "auto-train", "--ml-task", "BinaryClassification", "--train-dataset", trainDataset, "--label-column-name", labelName, "--label-column-index", "0", "--test-dataset", testDataset, "--max-exploration-time", "5" }; parser.InvokeAsync(args).Wait(); File.Delete(trainDataset); File.Delete(testDataset); @@ -214,7 +214,7 @@ public void CacheArgumentTest() var parser = new CommandLineBuilder() // Parser - .AddCommand(CommandDefinitions.New(handler)) + .AddCommand(CommandDefinitions.AutoTrain(handler)) .UseDefaults() .UseExceptionHandler((e, ctx) => { @@ -223,7 +223,7 @@ public void CacheArgumentTest() .Build(); // valid cache test - string[] args = new[] { "new", "--ml-task", "binary-classification", "--dataset", trainDataset, "--label-column-name", labelName, "--cache", cache }; + string[] args = new[] { "auto-train", "--ml-task", "binary-classification", "--dataset", trainDataset, "--label-column-name", labelName, "--cache", cache }; parser.InvokeAsync(args).Wait(); Assert.IsTrue(parsingSuccessful); @@ -231,7 +231,7 @@ public void CacheArgumentTest() cache = "off"; // valid cache test - args = new[] { "new", "--ml-task", "binary-classification", "--dataset", trainDataset, "--label-column-name", labelName, "--cache", cache }; + args = new[] { "auto-train", "--ml-task", "binary-classification", "--dataset", trainDataset, "--label-column-name", labelName, "--cache", cache }; parser.InvokeAsync(args).Wait(); Assert.IsTrue(parsingSuccessful); @@ -239,14 +239,14 @@ public void CacheArgumentTest() cache = "auto"; // valid cache test - args = new[] { "new", "--ml-task", "binary-classification", "--dataset", trainDataset, "--label-column-name", labelName, "--cache", cache }; + args = new[] { "auto-train", "--ml-task", "binary-classification", "--dataset", trainDataset, "--label-column-name", labelName, "--cache", cache }; parser.InvokeAsync(args).Wait(); Assert.IsTrue(parsingSuccessful); parsingSuccessful = false; // invalid cache test - args = new[] { "new", "--ml-task", "binary-classification", "--dataset", trainDataset, "--label-column-name", labelName, "--cache", "blah" }; + args = new[] { "auto-train", "--ml-task", "binary-classification", "--dataset", trainDataset, "--label-column-name", labelName, "--cache", "blah" }; parser.InvokeAsync(args).Wait(); Assert.IsFalse(parsingSuccessful); @@ -276,7 +276,7 @@ public void IgnoreColumnsArgumentTest() var parser = new CommandLineBuilder() // Parser - .AddCommand(CommandDefinitions.New(handler)) + .AddCommand(CommandDefinitions.AutoTrain(handler)) .UseDefaults() .UseExceptionHandler((e, ctx) => { @@ -285,13 +285,13 @@ public void IgnoreColumnsArgumentTest() .Build(); // valid cache test - string[] args = new[] { "new", "--ml-task", "binary-classification", "--dataset", trainDataset, "--label-column-name", labelName, "--ignore-columns", ignoreColumns }; + string[] args = new[] { "auto-train", "--ml-task", "binary-classification", "--dataset", trainDataset, "--label-column-name", labelName, "--ignore-columns", ignoreColumns }; parser.InvokeAsync(args).Wait(); Assert.IsTrue(parsingSuccessful); parsingSuccessful = false; - args = new[] { "new", "--ml-task", "binary-classification", "--dataset", trainDataset, "--label-column-name", labelName, "--ignore-columns", "a b c" }; + args = new[] { "auto-train", "--ml-task", "binary-classification", "--dataset", trainDataset, "--label-column-name", labelName, "--ignore-columns", "a b c" }; parser.InvokeAsync(args).Wait(); Assert.IsFalse(parsingSuccessful); diff --git a/src/mlnet/CodeGenerator/CodeGenerationHelper.cs b/src/mlnet/CodeGenerator/CodeGenerationHelper.cs index 1245c5bbab..c3df5173da 100644 --- a/src/mlnet/CodeGenerator/CodeGenerationHelper.cs +++ b/src/mlnet/CodeGenerator/CodeGenerationHelper.cs @@ -99,32 +99,31 @@ public void GenerateCode() { using (var pbar = new FixedDurationBar(wait, "", options)) { + pbar.Message = Strings.WaitingForFirstIteration; Thread t = default; switch (taskKind) { case TaskKind.BinaryClassification: t = new Thread(() => binaryRunDetails = automlEngine.ExploreBinaryClassificationModels(context, trainData, validationData, columnInformation, new BinaryExperimentSettings().OptimizingMetric, pbar)); - t.Start(); break; case TaskKind.Regression: t = new Thread(() => regressionRunDetails = automlEngine.ExploreRegressionModels(context, trainData, validationData, columnInformation, new RegressionExperimentSettings().OptimizingMetric, pbar)); - t.Start(); break; case TaskKind.MulticlassClassification: t = new Thread(() => multiRunDetails = automlEngine.ExploreMultiClassificationModels(context, trainData, validationData, columnInformation, new MulticlassExperimentSettings().OptimizingMetric, pbar)); - t.Start(); break; default: logger.Log(LogLevel.Error, Strings.UnsupportedMlTask); break; } + t.Start(); if (!pbar.CompletedHandle.WaitOne(wait)) pbar.Message = $"{nameof(FixedDurationBar)} did not signal {nameof(FixedDurationBar.CompletedHandle)} after {wait}"; if (t.IsAlive == true) { - string waitingMessage = "Waiting for the last iteration to complete ..."; + string waitingMessage = Strings.WaitingForLastIteration; string originalMessage = pbar.Message; pbar.Message = waitingMessage; t.Join(); diff --git a/src/mlnet/Commands/CommandDefinitions.cs b/src/mlnet/Commands/CommandDefinitions.cs index c1b304e72f..8d20db8e9a 100644 --- a/src/mlnet/Commands/CommandDefinitions.cs +++ b/src/mlnet/Commands/CommandDefinitions.cs @@ -14,9 +14,9 @@ namespace Microsoft.ML.CLI.Commands { internal static class CommandDefinitions { - internal static System.CommandLine.Command New(ICommandHandler handler) + internal static System.CommandLine.Command AutoTrain(ICommandHandler handler) { - var newCommand = new System.CommandLine.Command("new", "Create a new .NET project using ML.NET to train and run a model", handler: handler) + var newCommand = new System.CommandLine.Command("auto-train", "Create a new .NET project using ML.NET to train and run a model", handler: handler) { Dataset(), ValidationDataset(), @@ -62,56 +62,56 @@ internal static System.CommandLine.Command New(ICommandHandler handler) return newCommand; Option Dataset() => - new Option("--dataset", "File path to either a single dataset or a training dataset for train/test split approaches.", + new Option(new List() { "--dataset", "-d" }, "File path to either a single dataset or a training dataset for train/test split approaches.", new Argument().ExistingOnly()); Option ValidationDataset() => - new Option("--validation-dataset", "File path for the validation dataset in train/validation/test split approaches.", + new Option(new List() { "--validation-dataset", "-v" }, "File path for the validation dataset in train/validation/test split approaches.", new Argument(defaultValue: default(FileInfo)).ExistingOnly()); Option TestDataset() => - new Option("--test-dataset", "File path for the test dataset in train/test approaches.", + new Option(new List() { "--test-dataset", "-t" }, "File path for the test dataset in train/test approaches.", new Argument(defaultValue: default(FileInfo)).ExistingOnly()); Option MlTask() => - new Option("--ml-task", "Type of ML task to perform. Current supported tasks: regression, binary-classification, multiclass-classification.", + new Option(new List() { "--ml-task", "--mltask", "--task", "-T" }, "Type of ML task to perform. Current supported tasks: regression, binary-classification, multiclass-classification.", new Argument().FromAmong(GetMlTaskSuggestions())); Option LabelName() => - new Option("--label-column-name", "Name of the label (target) column to predict.", + new Option(new List() { "--label-column-name", "-n" }, "Name of the label (target) column to predict.", new Argument()); Option LabelColumnIndex() => - new Option("--label-column-index", "Index of the label (target) column to predict.", + new Option(new List() { "--label-column-index", "-i" }, "Index of the label (target) column to predict.", new Argument()); Option MaxExplorationTime() => - new Option("--max-exploration-time", "Maximum time in seconds for exploring models with best configuration.", + new Option(new List() { "--max-exploration-time", "-x" }, "Maximum time in seconds for exploring models with best configuration.", new Argument(defaultValue: 10)); Option Verbosity() => - new Option(new List() { "--verbosity" }, "Output verbosity choices: q[uiet], m[inimal] (by default) and diag[nostic].", + new Option(new List() { "--verbosity", "-V" }, "Output verbosity choices: q[uiet], m[inimal] (by default) and diag[nostic].", new Argument(defaultValue: "m").FromAmong(GetVerbositySuggestions())); Option Name() => - new Option(new List() { "--name" }, "Name for the output project or solution to create. ", + new Option(new List() { "--name", "-N" }, "Name for the output project or solution to create. ", new Argument()); Option OutputPath() => - new Option(new List() { "--output-path" }, "Location folder to place the generated output. The default is the current directory.", + new Option(new List() { "--output-path", "-o" }, "Location folder to place the generated output. The default is the current directory.", new Argument(defaultValue: new DirectoryInfo("."))); Option HasHeader() => - new Option(new List() { "--has-header" }, "Specify true/false depending if the dataset file(s) have a header row.", + new Option(new List() { "--has-header", "-h" }, "Specify true/false depending if the dataset file(s) have a header row.", new Argument(defaultValue: true)); Option Cache() => - new Option(new List() { "--cache" }, "Specify on/off/auto if you want cache to be turned on, off or auto determined.", + new Option(new List() { "--cache", "-c" }, "Specify on/off/auto if you want cache to be turned on, off or auto determined.", new Argument(defaultValue: "auto").FromAmong(GetCacheSuggestions())); // This is a temporary hack to work around having comma separated values for argument. This feature needs to be enabled in the parser itself. Option IgnoreColumns() => - new Option(new List() { "--ignore-columns" }, "Specify the columns that needs to be ignored in the given dataset.", + new Option(new List() { "--ignore-columns", "-I" }, "Specify the columns that needs to be ignored in the given dataset.", new Argument>(symbolResult => { try diff --git a/src/mlnet/Program.cs b/src/mlnet/Program.cs index c150f7758c..404e971655 100644 --- a/src/mlnet/Program.cs +++ b/src/mlnet/Program.cs @@ -61,7 +61,7 @@ public static void Main(string[] args) var parser = new CommandLineBuilder() // parser - .AddCommand(CommandDefinitions.New(handler)) + .AddCommand(CommandDefinitions.AutoTrain(handler)) .UseDefaults() .Build(); diff --git a/src/mlnet/Strings.resx b/src/mlnet/Strings.resx index 4a138d0a69..382a026dfd 100644 --- a/src/mlnet/Strings.resx +++ b/src/mlnet/Strings.resx @@ -177,4 +177,10 @@ https://aka.ms/mlnet-cli + + Waiting for the first iteration to complete ... + + + Waiting for the last iteration to complete ... + \ No newline at end of file diff --git a/src/mlnet/strings.Designer.cs b/src/mlnet/strings.Designer.cs index 7f4dc90b7e..214db2da81 100644 --- a/src/mlnet/strings.Designer.cs +++ b/src/mlnet/strings.Designer.cs @@ -239,5 +239,23 @@ internal static string UnsupportedMlTask { return ResourceManager.GetString("UnsupportedMlTask", resourceCulture); } } + + /// + /// Looks up a localized string similar to Waiting for the first iteration to complete .... + /// + internal static string WaitingForFirstIteration { + get { + return ResourceManager.GetString("WaitingForFirstIteration", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Waiting for the last iteration to complete .... + /// + internal static string WaitingForLastIteration { + get { + return ResourceManager.GetString("WaitingForLastIteration", resourceCulture); + } + } } }