Skip to content

Use inline training data in generated Console Project file. #4907

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public ITrainerEsitmator CreateInstance(MLContext mlContext, IEnumerable<Sweepab
options.LabelColumnName = columnInfo.LabelColumnName;
options.MatrixColumnIndexColumnName = columnInfo.UserIdColumnName;
options.MatrixRowIndexColumnName = columnInfo.ItemIdColumnName;
options.Quiet = true;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for quite the verbose output from MatrixFactorization trainer

return mlContext.Recommendation().Trainers.MatrixFactorization(options);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
using Microsoft.ML.CodeGenerator.CSharp;
using Microsoft.ML.CodeGenerator.Templates.Azure.Console;
using Microsoft.ML.CodeGenerator.Templates.Console;
using Microsoft.ML.CodeGenerator.Utilities;
using Microsoft.ML.Transforms;
using Tensorflow.Operations.Losses;

namespace Microsoft.ML.CodeGenerator.CodeGenerator.CSharp
{
Expand Down Expand Up @@ -79,21 +81,21 @@ public AzureAttachConsoleAppCodeGenerator(Pipeline pipeline, ColumnInferenceResu

var columns = _columnInferenceResult.TextLoaderOptions.Columns;
var featuresList = columns.Where((str) => str.Name != _settings.LabelName).Select((str) => str.Name).ToList();
var sampleResult = Utils.GenerateSampleData(_settings.TrainDataset, _columnInferenceResult);
PredictProgram = new CSharpCodeFile()
{
File = new PredictProgram()
{
TaskType = _settings.MlTask.ToString(),
LabelName = _settings.LabelName,
Namespace = _nameSpaceValue,
TestDataPath = _settings.TestDataset,
TrainDataPath = _settings.TrainDataset,
AllowQuoting = _columnInferenceResult.TextLoaderOptions.AllowQuoting,
AllowSparse = _columnInferenceResult.TextLoaderOptions.AllowSparse,
HasHeader = _columnInferenceResult.TextLoaderOptions.HasHeader,
Separator = _columnInferenceResult.TextLoaderOptions.Separators.FirstOrDefault(),
Target = _settings.Target,
Features = featuresList,
SampleData = sampleResult,
}.TransformText(),
Name = "Program.cs",
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -434,19 +434,19 @@ private string GeneratePredictProgramCSFileContent(string namespaceValue)
{
var columns = _columnInferenceResult.TextLoaderOptions.Columns;
var featuresList = columns.Where((str) => str.Name != _settings.LabelName).Select((str) => str.Name).ToList();
var sampleData = Utils.GenerateSampleData(_settings.TrainDataset, _columnInferenceResult);
PredictProgram predictProgram = new PredictProgram()
{
TaskType = _settings.MlTask.ToString(),
LabelName = _settings.LabelName,
Namespace = namespaceValue,
TestDataPath = _settings.TestDataset,
TrainDataPath = _settings.TrainDataset,
HasHeader = _columnInferenceResult.TextLoaderOptions.HasHeader,
Separator = _columnInferenceResult.TextLoaderOptions.Separators.FirstOrDefault(),
AllowQuoting = _columnInferenceResult.TextLoaderOptions.AllowQuoting,
AllowSparse = _columnInferenceResult.TextLoaderOptions.AllowSparse,
Features = featuresList,
Target = _settings.Target,
SampleData = sampleData,
};
return predictProgram.TransformText();
}
Expand Down
101 changes: 26 additions & 75 deletions src/Microsoft.ML.CodeGenerator/Templates/Console/PredictProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,32 +32,29 @@ public virtual string TransformText()
} else if(Target == CSharp.GenerateTarget.ModelBuilder){
MB_Annotation();
}
this.Write("\r\nusing System;\r\nusing System.IO;\r\nusing System.Linq;\r\nusing Microsoft.ML;\r\nusing" +
" ");
this.Write("\r\nusing System;\r\nusing ");
this.Write(this.ToStringHelper.ToStringWithCulture(Namespace));
this.Write(".Model;\r\n\r\nnamespace ");
this.Write(this.ToStringHelper.ToStringWithCulture(Namespace));
this.Write(".ConsoleApp\r\n{\r\n class Program\r\n {\r\n //Dataset to use for prediction" +
"s \r\n");
if(string.IsNullOrEmpty(TestDataPath)){
this.Write(" private const string DATA_FILEPATH = @\"");
this.Write(this.ToStringHelper.ToStringWithCulture(TrainDataPath));
this.Write("\";\r\n");
} else{
this.Write(" private const string DATA_FILEPATH = @\"");
this.Write(this.ToStringHelper.ToStringWithCulture(TestDataPath));
this.Write("\";\r\n");
}
this.Write(@"
static void Main(string[] args)
{
// Create single instance of sample data from first line of dataset for model input
ModelInput sampleData = CreateSingleDataSample(DATA_FILEPATH);

// Make a single prediction on the sample data and print results
var predictionResult = ConsumeModel.Predict(sampleData);

Console.WriteLine(""Using model to make single prediction -- Comparing actual ");
this.Write(".ConsoleApp\r\n{\r\n class Program\r\n {\r\n static void Main(string[] args)" +
"\r\n {\r\n // Create single instance of sample data from first lin" +
"e of dataset for model input\r\n");
if(SampleData != null) {
this.Write(" ModelInput sampleData = new ModelInput()\r\n {\r\n");
foreach(var kv in SampleData){
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(kv.Key));
this.Write("=");
this.Write(this.ToStringHelper.ToStringWithCulture(kv.Value));
this.Write(",\r\n");
}
this.Write(" };\r\n");
}else{
this.Write(" ModelInput sampleData = new ModelInput();\r\n");
}
this.Write("\r\n\t\t\t// Make a single prediction on the sample data and print results\r\n\t\t\tvar pre" +
"dictionResult = ConsumeModel.Predict(sampleData);\r\n\r\n\t\t\tConsole.WriteLine(\"Using" +
" model to make single prediction -- Comparing actual ");
this.Write(this.ToStringHelper.ToStringWithCulture(Utils.Normalize(LabelName)));
this.Write(" with predicted ");
this.Write(this.ToStringHelper.ToStringWithCulture(Utils.Normalize(LabelName)));
Expand All @@ -70,81 +67,35 @@ static void Main(string[] args)
this.Write("}\");\r\n");
}
if("BinaryClassification".Equals(TaskType) ){
this.Write("\t\t\tConsole.WriteLine($\"\\n\\nActual ");
this.Write(this.ToStringHelper.ToStringWithCulture(Utils.Normalize(LabelName)));
this.Write(": {sampleData.");
this.Write(this.ToStringHelper.ToStringWithCulture(Utils.Normalize(LabelName)));
this.Write("} \\nPredicted ");
this.Write("\t\t\tConsole.WriteLine($\"\\n\\nPredicted ");
this.Write(this.ToStringHelper.ToStringWithCulture(Utils.Normalize(LabelName)));
this.Write(": {predictionResult.Prediction}\\n\\n\");\r\n");
} else if("Regression".Equals(TaskType) || "Recommendation".Equals(TaskType)){
this.Write("\t\t\tConsole.WriteLine($\"\\n\\nActual ");
this.Write(this.ToStringHelper.ToStringWithCulture(Utils.Normalize(LabelName)));
this.Write(": {sampleData.");
this.Write(this.ToStringHelper.ToStringWithCulture(Utils.Normalize(LabelName)));
this.Write("} \\nPredicted ");
this.Write("\t\t\tConsole.WriteLine($\"\\n\\nPredicted ");
this.Write(this.ToStringHelper.ToStringWithCulture(Utils.Normalize(LabelName)));
this.Write(": {predictionResult.Score}\\n\\n\");\r\n");
} else if("MulticlassClassification".Equals(TaskType)){
this.Write("\t\t\tConsole.WriteLine($\"\\n\\nActual ");
this.Write(this.ToStringHelper.ToStringWithCulture(Utils.Normalize(LabelName)));
this.Write(": {sampleData.");
this.Write(this.ToStringHelper.ToStringWithCulture(Utils.Normalize(LabelName)));
this.Write("} \\nPredicted ");
this.Write("\t\t\tConsole.WriteLine($\"\\n\\nPredicted ");
this.Write(this.ToStringHelper.ToStringWithCulture(Utils.Normalize(LabelName)));
this.Write(" value {predictionResult.Prediction} \\nPredicted ");
this.Write(this.ToStringHelper.ToStringWithCulture(Utils.Normalize(LabelName)));
this.Write(" scores: [{String.Join(\",\", predictionResult.Score)}]\\n\\n\");\r\n");
}
this.Write(@" Console.WriteLine(""=============== End of process, hit any key to finish ==============="");
Console.ReadKey();
}

// Change this code to create your own sample data
#region CreateSingleDataSample
// Method to load single row of dataset to try a single prediction
private static ModelInput CreateSingleDataSample(string dataFilePath)
{
// Create MLContext
MLContext mlContext = new MLContext();

// Load dataset
IDataView dataView = mlContext.Data.LoadFromTextFile<ModelInput>(
path: dataFilePath,
hasHeader : ");
this.Write(this.ToStringHelper.ToStringWithCulture(HasHeader.ToString().ToLowerInvariant()));
this.Write(",\r\n separatorChar : \'");
this.Write(this.ToStringHelper.ToStringWithCulture(Regex.Escape(Separator.ToString())));
this.Write("\',\r\n allowQuoting : ");
this.Write(this.ToStringHelper.ToStringWithCulture(AllowQuoting.ToString().ToLowerInvariant()));
this.Write(",\r\n allowSparse: ");
this.Write(this.ToStringHelper.ToStringWithCulture(AllowSparse.ToString().ToLowerInvariant()));
this.Write(@");

// Use first line of dataset as model input
// You can replace this with new test data (hardcoded or from end-user application)
ModelInput sampleForPrediction = mlContext.Data.CreateEnumerable<ModelInput>(dataView, false)
.First();
return sampleForPrediction;
}
#endregion
}
}
");
this.Write(" Console.WriteLine(\"=============== End of process, hit any key to fin" +
"ish ===============\");\r\n Console.ReadKey();\r\n }\r\n }\r\n}\r\n");
return this.GenerationEnvironment.ToString();
}

public string TaskType {get;set;}
public string Namespace {get;set;}
public string LabelName {get;set;}
public string TestDataPath {get;set;}
public string TrainDataPath {get;set;}
public char Separator {get;set;}
public bool AllowQuoting {get;set;}
public bool AllowSparse {get;set;}
public bool HasHeader {get;set;}
public IList<string> Features {get;set;}
internal CSharp.GenerateTarget Target {get;set;}
public IDictionary<string, string> SampleData {get;set;}


void CLI_Annotation()
Expand Down
56 changes: 15 additions & 41 deletions src/Microsoft.ML.CodeGenerator/Templates/Console/PredictProgram.tt
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,25 @@
<# } #>

using System;
using System.IO;
using System.Linq;
using Microsoft.ML;
using <#= Namespace #>.Model;

namespace <#= Namespace #>.ConsoleApp
{
class Program
{
//Dataset to use for predictions
<#if(string.IsNullOrEmpty(TestDataPath)){ #>
private const string DATA_FILEPATH = @"<#= TrainDataPath #>";
<# } else{ #>
private const string DATA_FILEPATH = @"<#= TestDataPath #>";
<# } #>

static void Main(string[] args)
{
// Create single instance of sample data from first line of dataset for model input
ModelInput sampleData = CreateSingleDataSample(DATA_FILEPATH);
// Create single instance of sample data from first line of dataset for model input
<# if(SampleData != null) {#>
ModelInput sampleData = new ModelInput()
{
<# foreach(var kv in SampleData){ #>
<#= kv.Key #>=<#= kv.Value #>,
<#}#>
};
<#}else{#>
ModelInput sampleData = new ModelInput();
<#}#>

// Make a single prediction on the sample data and print results
var predictionResult = ConsumeModel.Predict(sampleData);
Expand All @@ -41,51 +40,26 @@ namespace <#= Namespace #>.ConsoleApp
Console.WriteLine($"<#= label #>: {sampleData.<#= Utils.Normalize(label) #>}");
<#}#>
<#if("BinaryClassification".Equals(TaskType) ){ #>
Console.WriteLine($"\n\nActual <#= Utils.Normalize(LabelName) #>: {sampleData.<#= Utils.Normalize(LabelName) #>} \nPredicted <#= Utils.Normalize(LabelName) #>: {predictionResult.Prediction}\n\n");
Console.WriteLine($"\n\nPredicted <#= Utils.Normalize(LabelName) #>: {predictionResult.Prediction}\n\n");
<#} else if("Regression".Equals(TaskType) || "Recommendation".Equals(TaskType)){#>
Console.WriteLine($"\n\nActual <#= Utils.Normalize(LabelName) #>: {sampleData.<#= Utils.Normalize(LabelName) #>} \nPredicted <#= Utils.Normalize(LabelName) #>: {predictionResult.Score}\n\n");
Console.WriteLine($"\n\nPredicted <#= Utils.Normalize(LabelName) #>: {predictionResult.Score}\n\n");
<#} else if("MulticlassClassification".Equals(TaskType)){#>
Console.WriteLine($"\n\nActual <#= Utils.Normalize(LabelName) #>: {sampleData.<#= Utils.Normalize(LabelName) #>} \nPredicted <#= Utils.Normalize(LabelName) #> value {predictionResult.Prediction} \nPredicted <#= Utils.Normalize(LabelName) #> scores: [{String.Join(",", predictionResult.Score)}]\n\n");
Console.WriteLine($"\n\nPredicted <#= Utils.Normalize(LabelName) #> value {predictionResult.Prediction} \nPredicted <#= Utils.Normalize(LabelName) #> scores: [{String.Join(",", predictionResult.Score)}]\n\n");
<#} #>
Console.WriteLine("=============== End of process, hit any key to finish ===============");
Console.ReadKey();
}

// Change this code to create your own sample data
#region CreateSingleDataSample
// Method to load single row of dataset to try a single prediction
private static ModelInput CreateSingleDataSample(string dataFilePath)
{
// Create MLContext
MLContext mlContext = new MLContext();

// Load dataset
IDataView dataView = mlContext.Data.LoadFromTextFile<ModelInput>(
path: dataFilePath,
hasHeader : <#= HasHeader.ToString().ToLowerInvariant() #>,
separatorChar : '<#= Regex.Escape(Separator.ToString()) #>',
allowQuoting : <#= AllowQuoting.ToString().ToLowerInvariant() #>,
allowSparse: <#= AllowSparse.ToString().ToLowerInvariant() #>);

// Use first line of dataset as model input
// You can replace this with new test data (hardcoded or from end-user application)
ModelInput sampleForPrediction = mlContext.Data.CreateEnumerable<ModelInput>(dataView, false)
.First();
return sampleForPrediction;
}
#endregion
}
}
<#+
public string TaskType {get;set;}
public string Namespace {get;set;}
public string LabelName {get;set;}
public string TestDataPath {get;set;}
public string TrainDataPath {get;set;}
public char Separator {get;set;}
public bool AllowQuoting {get;set;}
public bool AllowSparse {get;set;}
public bool HasHeader {get;set;}
public IList<string> Features {get;set;}
internal CSharp.GenerateTarget Target {get;set;}
public IDictionary<string, string> SampleData {get;set;}
#>
Loading