diff --git a/src/Microsoft.ML.CodeGenerator/Templates/Console/ConsumeModel.cs b/src/Microsoft.ML.CodeGenerator/Templates/Console/ConsumeModel.cs index 7c01186c3b..ba1983786b 100644 --- a/src/Microsoft.ML.CodeGenerator/Templates/Console/ConsumeModel.cs +++ b/src/Microsoft.ML.CodeGenerator/Templates/Console/ConsumeModel.cs @@ -39,21 +39,30 @@ public virtual string TransformText() { public class ConsumeModel { - // For more info on consuming ML.NET models, visit https://aka.ms/model-builder-consume + private static Lazy> PredictionEngine = new Lazy>(CreatePredictionEngine); + + // For more info on consuming ML.NET models, visit https://aka.ms/mlnet-consume // Method for consuming model in your app public static ModelOutput Predict(ModelInput input) { - + ModelOutput result = PredictionEngine.Value.Predict(input); + return result; + } + + public static PredictionEngine CreatePredictionEngine() + { // Create new MLContext MLContext mlContext = new MLContext(); "); if(HasNormalizeMapping){ - this.Write(" \r\n\t\t\t// Register NormalizeMapping\r\n mlContext.ComponentCatalog.Regist" + - "erAssembly(typeof(NormalizeMapping).Assembly);\r\n"); + this.Write(" \r\n\t\t\t// Register NormalizeMapping to calculate probabilities for each Label.\r\n " + + " mlContext.ComponentCatalog.RegisterAssembly(typeof(NormalizeMapping).A" + + "ssembly);\r\n"); } if(HasLabelMapping){ - this.Write(" \r\n\t\t\t// Register LabelMapping\r\n mlContext.ComponentCatalog.RegisterAs" + - "sembly(typeof(LabelMapping).Assembly);\r\n"); + this.Write(" \r\n\t\t\t// Register LabelMapping to map predicted Labels to their corresponding pro" + + "babilities (likelihood of specified Labels)\r\n mlContext.ComponentCata" + + "log.RegisterAssembly(typeof(LabelMapping).Assembly);\r\n"); } this.Write("\r\n // Load model & create prediction engine\r\n string modelP" + "ath = @\""); @@ -61,10 +70,8 @@ public static ModelOutput Predict(ModelInput input) this.Write(@"""; ITransformer mlModel = mlContext.Model.Load(modelPath, out var modelInputSchema); var predEngine = mlContext.Model.CreatePredictionEngine(mlModel); - - // Use model to make prediction on input data - ModelOutput result = predEngine.Predict(input); - return result; + + return predEngine; } } } diff --git a/src/Microsoft.ML.CodeGenerator/Templates/Console/ConsumeModel.tt b/src/Microsoft.ML.CodeGenerator/Templates/Console/ConsumeModel.tt index 626dde7a8b..30128af221 100644 --- a/src/Microsoft.ML.CodeGenerator/Templates/Console/ConsumeModel.tt +++ b/src/Microsoft.ML.CodeGenerator/Templates/Console/ConsumeModel.tt @@ -20,19 +20,26 @@ namespace <#= Namespace #>.Model { public class ConsumeModel { - // For more info on consuming ML.NET models, visit https://aka.ms/model-builder-consume + private static Lazy> PredictionEngine = new Lazy>(CreatePredictionEngine); + + // For more info on consuming ML.NET models, visit https://aka.ms/mlnet-consume // Method for consuming model in your app public static ModelOutput Predict(ModelInput input) { - + ModelOutput result = PredictionEngine.Value.Predict(input); + return result; + } + + public static PredictionEngine CreatePredictionEngine() + { // Create new MLContext MLContext mlContext = new MLContext(); <#if(HasNormalizeMapping){ #> - // Register NormalizeMapping + // Register NormalizeMapping to calculate probabilities for each Label. mlContext.ComponentCatalog.RegisterAssembly(typeof(NormalizeMapping).Assembly); <#} #> <#if(HasLabelMapping){ #> - // Register LabelMapping + // Register LabelMapping to map predicted Labels to their corresponding probabilities (likelihood of specified Labels) mlContext.ComponentCatalog.RegisterAssembly(typeof(LabelMapping).Assembly); <#} #> @@ -40,10 +47,8 @@ namespace <#= Namespace #>.Model string modelPath = @"<#= MLNetModelpath #>"; ITransformer mlModel = mlContext.Model.Load(modelPath, out var modelInputSchema); var predEngine = mlContext.Model.CreatePredictionEngine(mlModel); - - // Use model to make prediction on input data - ModelOutput result = predEngine.Predict(input); - return result; + + return predEngine; } } } diff --git a/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.AzureCodeGeneratorTest.ConsumeModel.cs.approved.txt b/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.AzureCodeGeneratorTest.ConsumeModel.cs.approved.txt index f39eca9bd9..1e9da143aa 100644 --- a/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.AzureCodeGeneratorTest.ConsumeModel.cs.approved.txt +++ b/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.AzureCodeGeneratorTest.ConsumeModel.cs.approved.txt @@ -11,15 +11,22 @@ namespace Test.Model { public class ConsumeModel { - // For more info on consuming ML.NET models, visit https://aka.ms/model-builder-consume + private static Lazy> PredictionEngine = new Lazy>(CreatePredictionEngine); + + // For more info on consuming ML.NET models, visit https://aka.ms/mlnet-consume // Method for consuming model in your app public static ModelOutput Predict(ModelInput input) { + ModelOutput result = PredictionEngine.Value.Predict(input); + return result; + } + public static PredictionEngine CreatePredictionEngine() + { // Create new MLContext MLContext mlContext = new MLContext(); - // Register LabelMapping + // Register LabelMapping to map predicted Labels to their corresponding probabilities (likelihood of specified Labels) mlContext.ComponentCatalog.RegisterAssembly(typeof(LabelMapping).Assembly); // Load model & create prediction engine @@ -27,9 +34,7 @@ namespace Test.Model ITransformer mlModel = mlContext.Model.Load(modelPath, out var modelInputSchema); var predEngine = mlContext.Model.CreatePredictionEngine(mlModel); - // Use model to make prediction on input data - ModelOutput result = predEngine.Predict(input); - return result; + return predEngine; } } } diff --git a/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.AzureImageCodeGeneratorTest.ConsumeModel.cs.approved.txt b/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.AzureImageCodeGeneratorTest.ConsumeModel.cs.approved.txt index ed853667b8..c7194979d9 100644 --- a/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.AzureImageCodeGeneratorTest.ConsumeModel.cs.approved.txt +++ b/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.AzureImageCodeGeneratorTest.ConsumeModel.cs.approved.txt @@ -11,18 +11,25 @@ namespace CodeGenTest.Model { public class ConsumeModel { - // For more info on consuming ML.NET models, visit https://aka.ms/model-builder-consume + private static Lazy> PredictionEngine = new Lazy>(CreatePredictionEngine); + + // For more info on consuming ML.NET models, visit https://aka.ms/mlnet-consume // Method for consuming model in your app public static ModelOutput Predict(ModelInput input) { + ModelOutput result = PredictionEngine.Value.Predict(input); + return result; + } + public static PredictionEngine CreatePredictionEngine() + { // Create new MLContext MLContext mlContext = new MLContext(); - // Register NormalizeMapping + // Register NormalizeMapping to calculate probabilities for each Label. mlContext.ComponentCatalog.RegisterAssembly(typeof(NormalizeMapping).Assembly); - // Register LabelMapping + // Register LabelMapping to map predicted Labels to their corresponding probabilities (likelihood of specified Labels) mlContext.ComponentCatalog.RegisterAssembly(typeof(LabelMapping).Assembly); // Load model & create prediction engine @@ -30,9 +37,7 @@ namespace CodeGenTest.Model ITransformer mlModel = mlContext.Model.Load(modelPath, out var modelInputSchema); var predEngine = mlContext.Model.CreatePredictionEngine(mlModel); - // Use model to make prediction on input data - ModelOutput result = predEngine.Predict(input); - return result; + return predEngine; } } } diff --git a/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.ConsumeModelContentTest.approved.txt b/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.ConsumeModelContentTest.approved.txt index 61b7b28beb..1e5a191392 100644 --- a/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.ConsumeModelContentTest.approved.txt +++ b/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.ConsumeModelContentTest.approved.txt @@ -15,11 +15,18 @@ namespace TestNamespace.Model { public class ConsumeModel { - // For more info on consuming ML.NET models, visit https://aka.ms/model-builder-consume + private static Lazy> PredictionEngine = new Lazy>(CreatePredictionEngine); + + // For more info on consuming ML.NET models, visit https://aka.ms/mlnet-consume // Method for consuming model in your app public static ModelOutput Predict(ModelInput input) { + ModelOutput result = PredictionEngine.Value.Predict(input); + return result; + } + public static PredictionEngine CreatePredictionEngine() + { // Create new MLContext MLContext mlContext = new MLContext(); @@ -28,9 +35,7 @@ namespace TestNamespace.Model ITransformer mlModel = mlContext.Model.Load(modelPath, out var modelInputSchema); var predEngine = mlContext.Model.CreatePredictionEngine(mlModel); - // Use model to make prediction on input data - ModelOutput result = predEngine.Predict(input); - return result; + return predEngine; } } } diff --git a/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.Recommendation_GenerateModelProjectContents_VerifyConsumeModel.approved.txt b/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.Recommendation_GenerateModelProjectContents_VerifyConsumeModel.approved.txt index 61b7b28beb..1e5a191392 100644 --- a/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.Recommendation_GenerateModelProjectContents_VerifyConsumeModel.approved.txt +++ b/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/ConsoleCodeGeneratorTests.Recommendation_GenerateModelProjectContents_VerifyConsumeModel.approved.txt @@ -15,11 +15,18 @@ namespace TestNamespace.Model { public class ConsumeModel { - // For more info on consuming ML.NET models, visit https://aka.ms/model-builder-consume + private static Lazy> PredictionEngine = new Lazy>(CreatePredictionEngine); + + // For more info on consuming ML.NET models, visit https://aka.ms/mlnet-consume // Method for consuming model in your app public static ModelOutput Predict(ModelInput input) { + ModelOutput result = PredictionEngine.Value.Predict(input); + return result; + } + public static PredictionEngine CreatePredictionEngine() + { // Create new MLContext MLContext mlContext = new MLContext(); @@ -28,9 +35,7 @@ namespace TestNamespace.Model ITransformer mlModel = mlContext.Model.Load(modelPath, out var modelInputSchema); var predEngine = mlContext.Model.CreatePredictionEngine(mlModel); - // Use model to make prediction on input data - ModelOutput result = predEngine.Predict(input); - return result; + return predEngine; } } } diff --git a/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/TemplateTest.TestConsumeModel.approved.txt b/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/TemplateTest.TestConsumeModel.approved.txt new file mode 100644 index 0000000000..25811efe96 --- /dev/null +++ b/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/TemplateTest.TestConsumeModel.approved.txt @@ -0,0 +1,43 @@ +// This file was auto-generated by ML.NET Model Builder. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.ML; +using Namespace.Model; + +namespace Namespace.Model +{ + public class ConsumeModel + { + private static Lazy> PredictionEngine = new Lazy>(CreatePredictionEngine); + + // For more info on consuming ML.NET models, visit https://aka.ms/mlnet-consume + // Method for consuming model in your app + public static ModelOutput Predict(ModelInput input) + { + ModelOutput result = PredictionEngine.Value.Predict(input); + return result; + } + + public static PredictionEngine CreatePredictionEngine() + { + // Create new MLContext + MLContext mlContext = new MLContext(); + + // Register NormalizeMapping to calculate probabilities for each Label. + mlContext.ComponentCatalog.RegisterAssembly(typeof(NormalizeMapping).Assembly); + + // Register LabelMapping to map predicted Labels to their corresponding probabilities (likelihood of specified Labels) + mlContext.ComponentCatalog.RegisterAssembly(typeof(LabelMapping).Assembly); + + // Load model & create prediction engine + string modelPath = @"/path/to/model"; + ITransformer mlModel = mlContext.Model.Load(modelPath, out var modelInputSchema); + var predEngine = mlContext.Model.CreatePredictionEngine(mlModel); + + return predEngine; + } + } +} diff --git a/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/TemplateTest.cs b/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/TemplateTest.cs index d4bb4ef9ca..5351a70401 100644 --- a/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/TemplateTest.cs +++ b/test/Microsoft.ML.CodeGenerator.Tests/ApprovalTests/TemplateTest.cs @@ -39,5 +39,21 @@ public void TestPredictProgram_WithSampleData() }; Approvals.Verify(predictProgram.TransformText()); } + + [Fact] + [UseReporter(typeof(DiffReporter))] + [MethodImpl(MethodImplOptions.NoInlining)] + public void TestConsumeModel() + { + var consumeModel = new ConsumeModel() + { + Namespace = "Namespace", + HasNormalizeMapping = true, + HasLabelMapping = true, + MLNetModelpath = @"/path/to/model", + }; + + Approvals.Verify(consumeModel.TransformText()); + } } }