From db144840e0273d5213e9c67608126cd34ceeb082 Mon Sep 17 00:00:00 2001 From: Rogan Carr Date: Thu, 14 Mar 2019 16:37:35 -0700 Subject: [PATCH 1/6] In-progress ONNX scenario tests. --- test/Microsoft.ML.Functional.Tests/ONNX.cs | 73 ++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 test/Microsoft.ML.Functional.Tests/ONNX.cs diff --git a/test/Microsoft.ML.Functional.Tests/ONNX.cs b/test/Microsoft.ML.Functional.Tests/ONNX.cs new file mode 100644 index 0000000000..6beda07ad0 --- /dev/null +++ b/test/Microsoft.ML.Functional.Tests/ONNX.cs @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.IO; +using Microsoft.ML.Functional.Tests.Datasets; +using Microsoft.ML.RunTests; +using Microsoft.ML.TestFramework; +using Microsoft.ML.TestFramework.Attributes; +using Microsoft.ML.Trainers; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.ML.Functional.Tests +{ + public class ONNX : BaseTestClass + { + public ONNX(ITestOutputHelper output) : base(output) + { + } + + /// + /// ONNX: I can save a model to ONNX and reload it and use it in a pipeline. + /// + [OnnxFactAttribute] + public void SaveOnnxModelLoadAndScoreSDCA() + { + var mlContext = new MLContext(seed: 1); + + // Get the dataset. + var data = mlContext.Data.LoadFromTextFile(GetDataPath(TestDatasets.housing.trainFilename), hasHeader: true); + + // Create a pipeline to train on the housing data. + var pipeline = mlContext.Transforms.Concatenate("Features", HousingRegression.Features) + .Append(mlContext.Transforms.Normalize("Features")) + .AppendCacheCheckpoint(mlContext) + .Append(mlContext.Regression.Trainers.Sdca( + new SdcaRegressionTrainer.Options { NumberOfThreads = 1, MaximumNumberOfIterations = 10 })); + + // Fit the pipeline. + var model = pipeline.Fit(data); + + // Serialize the pipeline to a file. + var modelFileName = "model.onnx"; + var modelPath = DeleteOutputPath(modelFileName); + using (var file = File.Create(modelPath)) + mlContext.Model.ConvertToOnnx(model, data, file); + + // Load the model as a transform. + var onnxEstimator = mlContext.Transforms.ApplyOnnxModel(modelPath); + var onnxModel = onnxEstimator.Fit(data); + + // Create prediction engine and test predictions. + var originalPredictionEngine = model.CreatePredictionEngine(mlContext); + var onnxPredictionEngine = onnxModel.CreatePredictionEngine(mlContext); + + // Take a handful of examples out of the dataset and compute predictions. + var dataEnumerator = mlContext.Data.CreateEnumerable(mlContext.Data.TakeRows(data, 5), false); + foreach (var row in dataEnumerator) + { + var originalPrediction = originalPredictionEngine.Predict(row); + var onnxPrediction = onnxPredictionEngine.Predict(row); + // Check that the predictions are identical. + Assert.Equal(originalPrediction.Score, onnxPrediction.Score); + } + } + + private class ScoreColumn + { + public float Score { get; set; } + } + } +} From 8a122b4bc503cad12588034bb311e02f470c7188 Mon Sep 17 00:00:00 2001 From: Rogan Carr Date: Fri, 15 Mar 2019 15:20:19 -0700 Subject: [PATCH 2/6] Adding functional tests for ONNX scenarios --- test/Microsoft.ML.Functional.Tests/Common.cs | 4 +- test/Microsoft.ML.Functional.Tests/ONNX.cs | 128 ++++++++++++++++++- 2 files changed, 127 insertions(+), 5 deletions(-) diff --git a/test/Microsoft.ML.Functional.Tests/Common.cs b/test/Microsoft.ML.Functional.Tests/Common.cs index 35e28ffa27..d6cb0c10dd 100644 --- a/test/Microsoft.ML.Functional.Tests/Common.cs +++ b/test/Microsoft.ML.Functional.Tests/Common.cs @@ -84,14 +84,14 @@ public static void AssertTestTypeDatasetsAreEqual(MLContext mlContext, IDataView /// /// An array of floats. /// An array of floats. - public static void AssertEqual(float[] array1, float[] array2) + public static void AssertEqual(float[] array1, float[] array2, int precision = 6) { Assert.NotNull(array1); Assert.NotNull(array2); Assert.Equal(array1.Length, array2.Length); for (int i = 0; i < array1.Length; i++) - Assert.Equal(array1[i], array2[i]); + Assert.Equal(array1[i], array2[i], precision: precision); } /// diff --git a/test/Microsoft.ML.Functional.Tests/ONNX.cs b/test/Microsoft.ML.Functional.Tests/ONNX.cs index 6beda07ad0..00cf56340f 100644 --- a/test/Microsoft.ML.Functional.Tests/ONNX.cs +++ b/test/Microsoft.ML.Functional.Tests/ONNX.cs @@ -8,6 +8,8 @@ using Microsoft.ML.TestFramework; using Microsoft.ML.TestFramework.Attributes; using Microsoft.ML.Trainers; +using Microsoft.ML.Trainers.FastTree; +using Microsoft.ML.Transforms; using Xunit; using Xunit.Abstractions; @@ -19,6 +21,110 @@ public ONNX(ITestOutputHelper output) : base(output) { } + /// + /// ONNX: I can save a model to ONNX and reload it and use it in a pipeline. + /// + [OnnxFactAttribute] + public void SaveOnnxModelLoadAndScoreFastTree() + { + var mlContext = new MLContext(seed: 1); + + // Get the dataset. + var data = mlContext.Data.LoadFromTextFile(GetDataPath(TestDatasets.housing.trainFilename), hasHeader: true); + + // Create a pipeline to train on the housing data. + var pipeline = mlContext.Transforms.Concatenate("Features", HousingRegression.Features) + .Append(mlContext.Transforms.Normalize("Features")) + .AppendCacheCheckpoint(mlContext) + .Append(mlContext.Regression.Trainers.FastTree( + new FastTreeRegressionTrainer.Options { NumberOfThreads = 1, NumberOfTrees = 10 })); + + // Fit the pipeline. + var model = pipeline.Fit(data); + + // Serialize the pipeline to a file. + var modelFileName = "SaveOnnxLoadAndScoreFastTreeModel.onnx"; + var modelPath = DeleteOutputPath(modelFileName); + using (var file = File.Create(modelPath)) + mlContext.Model.ConvertToOnnx(model, data, file); + + // Load the model as a transform. + var onnxEstimator = mlContext.Transforms.ApplyOnnxModel(modelPath); + var onnxModel = onnxEstimator.Fit(data); + + // TODO #2980: ONNX outputs don't match the outputs of the model, so we must hand-correct this for now. + // TODO #2981: ONNX models cannot be fit as part of a pipeline, so we must use a workaround like this. + var onnxWorkaroundPipeline = onnxModel.Append( + mlContext.Transforms.CopyColumns("Score", "Score0").Fit(onnxModel.Transform(data))); + + // Create prediction engine and test predictions. + var originalPredictionEngine = model.CreatePredictionEngine(mlContext); + // TODO #2982: ONNX produces vector types and not the original output type. + var onnxPredictionEngine = onnxWorkaroundPipeline.CreatePredictionEngine(mlContext); + + // Take a handful of examples out of the dataset and compute predictions. + var dataEnumerator = mlContext.Data.CreateEnumerable(mlContext.Data.TakeRows(data, 5), false); + foreach (var row in dataEnumerator) + { + var originalPrediction = originalPredictionEngine.Predict(row); + var onnxPrediction = onnxPredictionEngine.Predict(row); + // Check that the predictions are identical. + Assert.Equal(originalPrediction.Score, onnxPrediction.Score[0], precision: 4); // Note the low-precision equality! + } + } + + /// + /// ONNX: I can save a model to ONNX and reload it and use it in a pipeline. + /// + [OnnxFactAttribute] + public void SaveOnnxModelLoadAndScoreKMeans() + { + var mlContext = new MLContext(seed: 1); + + // Get the dataset. + var data = mlContext.Data.LoadFromTextFile(GetDataPath(TestDatasets.housing.trainFilename), hasHeader: true); + + // Create a pipeline to train on the housing data. + var pipeline = mlContext.Transforms.Concatenate("Features", HousingRegression.Features) + .Append(mlContext.Transforms.Normalize("Features")) + .AppendCacheCheckpoint(mlContext) + .Append(mlContext.Clustering.Trainers.KMeans( + new KMeansTrainer.Options { NumberOfThreads = 1, MaximumNumberOfIterations = 10 })); + + // Fit the pipeline. + var model = pipeline.Fit(data); + + // Serialize the pipeline to a file. + var modelFileName = "SaveOnnxLoadAndScoreKMeansModel.onnx"; + var modelPath = DeleteOutputPath(modelFileName); + using (var file = File.Create(modelPath)) + mlContext.Model.ConvertToOnnx(model, data, file); + + // Load the model as a transform. + var onnxEstimator = mlContext.Transforms.ApplyOnnxModel(modelPath); + var onnxModel = onnxEstimator.Fit(data); + + // TODO #2980: ONNX outputs don't match the outputs of the model, so we must hand-correct this for now. + // TODO #2981: ONNX models cannot be fit as part of a pipeline, so we must use a workaround like this. + var onnxWorkaroundPipeline = onnxModel.Append( + mlContext.Transforms.CopyColumns("Score", "Score0").Fit(onnxModel.Transform(data))); + + // Create prediction engine and test predictions. + var originalPredictionEngine = model.CreatePredictionEngine(mlContext); + // TODO #2982: ONNX produces vector types and not the original output type. + var onnxPredictionEngine = onnxWorkaroundPipeline.CreatePredictionEngine(mlContext); + + // Take a handful of examples out of the dataset and compute predictions. + var dataEnumerator = mlContext.Data.CreateEnumerable(mlContext.Data.TakeRows(data, 5), false); + foreach (var row in dataEnumerator) + { + var originalPrediction = originalPredictionEngine.Predict(row); + var onnxPrediction = onnxPredictionEngine.Predict(row); + // Check that the predictions are identical. + Common.AssertEqual(originalPrediction.Score, onnxPrediction.Score, precision: 4); // Note the low precision! + } + } + /// /// ONNX: I can save a model to ONNX and reload it and use it in a pipeline. /// @@ -41,7 +147,7 @@ public void SaveOnnxModelLoadAndScoreSDCA() var model = pipeline.Fit(data); // Serialize the pipeline to a file. - var modelFileName = "model.onnx"; + var modelFileName = "SaveOnnxLoadAndScoreSdcaModel.onnx"; var modelPath = DeleteOutputPath(modelFileName); using (var file = File.Create(modelPath)) mlContext.Model.ConvertToOnnx(model, data, file); @@ -50,9 +156,15 @@ public void SaveOnnxModelLoadAndScoreSDCA() var onnxEstimator = mlContext.Transforms.ApplyOnnxModel(modelPath); var onnxModel = onnxEstimator.Fit(data); + // TODO #2980: ONNX outputs don't match the outputs of the model, so we must hand-correct this for now. + // TODO #2981: ONNX models cannot be fit as part of a pipeline, so we must use a workaround like this. + var onnxWorkaroundPipeline = onnxModel.Append( + mlContext.Transforms.CopyColumns("Score", "Score0").Fit(onnxModel.Transform(data))); + // Create prediction engine and test predictions. var originalPredictionEngine = model.CreatePredictionEngine(mlContext); - var onnxPredictionEngine = onnxModel.CreatePredictionEngine(mlContext); + // TODO #2982: ONNX produces vector types and not the original output type. + var onnxPredictionEngine = onnxWorkaroundPipeline.CreatePredictionEngine(mlContext); // Take a handful of examples out of the dataset and compute predictions. var dataEnumerator = mlContext.Data.CreateEnumerable(mlContext.Data.TakeRows(data, 5), false); @@ -61,7 +173,7 @@ public void SaveOnnxModelLoadAndScoreSDCA() var originalPrediction = originalPredictionEngine.Predict(row); var onnxPrediction = onnxPredictionEngine.Predict(row); // Check that the predictions are identical. - Assert.Equal(originalPrediction.Score, onnxPrediction.Score); + Assert.Equal(originalPrediction.Score, onnxPrediction.Score[0], precision: 4); // Note the low-precision equality! } } @@ -69,5 +181,15 @@ private class ScoreColumn { public float Score { get; set; } } + + private class OnnxScoreColumn + { + public float[] Score { get; set; } + } + + private class ClusteringScoreColumn + { + public float[] Score { get; set; } + } } } From eb44b64714ea9d653278f36e5cac620a71cb3c7e Mon Sep 17 00:00:00 2001 From: Rogan Carr Date: Tue, 19 Mar 2019 13:29:14 -0700 Subject: [PATCH 3/6] Adding common column classes to CommonColumns.cs --- ...ContributionOutput.cs => CommonColumns.cs} | 19 ++++++++++++++- .../Datasets/FeatureColumn.cs | 14 ----------- test/Microsoft.ML.Functional.Tests/ONNX.cs | 24 ++++--------------- 3 files changed, 22 insertions(+), 35 deletions(-) rename test/Microsoft.ML.Functional.Tests/Datasets/{FeatureContributionOutput.cs => CommonColumns.cs} (56%) delete mode 100644 test/Microsoft.ML.Functional.Tests/Datasets/FeatureColumn.cs diff --git a/test/Microsoft.ML.Functional.Tests/Datasets/FeatureContributionOutput.cs b/test/Microsoft.ML.Functional.Tests/Datasets/CommonColumns.cs similarity index 56% rename from test/Microsoft.ML.Functional.Tests/Datasets/FeatureContributionOutput.cs rename to test/Microsoft.ML.Functional.Tests/Datasets/CommonColumns.cs index 6aa8dcbb11..7cf469ef57 100644 --- a/test/Microsoft.ML.Functional.Tests/Datasets/FeatureContributionOutput.cs +++ b/test/Microsoft.ML.Functional.Tests/Datasets/CommonColumns.cs @@ -2,9 +2,16 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - namespace Microsoft.ML.Functional.Tests.Datasets { + /// + /// A class to hold a feature column. + /// + internal sealed class FeatureColumn + { + public float[] Features { get; set; } + } + /// /// A class to hold the output of FeatureContributionCalculator /// @@ -12,4 +19,14 @@ internal sealed class FeatureContributionOutput { public float[] FeatureContributions { get; set; } } + + internal sealed class ScoreColumn + { + public float Score { get; set; } + } + + internal sealed class VectorScoreColumn + { + public float[] Score { get; set; } + } } diff --git a/test/Microsoft.ML.Functional.Tests/Datasets/FeatureColumn.cs b/test/Microsoft.ML.Functional.Tests/Datasets/FeatureColumn.cs deleted file mode 100644 index 090ad23646..0000000000 --- a/test/Microsoft.ML.Functional.Tests/Datasets/FeatureColumn.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace Microsoft.ML.Functional.Tests.Datasets -{ - /// - /// A class to hold a feature column. - /// - internal sealed class FeatureColumn - { - public float[] Features { get; set; } - } -} diff --git a/test/Microsoft.ML.Functional.Tests/ONNX.cs b/test/Microsoft.ML.Functional.Tests/ONNX.cs index 00cf56340f..ddb64a81f3 100644 --- a/test/Microsoft.ML.Functional.Tests/ONNX.cs +++ b/test/Microsoft.ML.Functional.Tests/ONNX.cs @@ -9,7 +9,6 @@ using Microsoft.ML.TestFramework.Attributes; using Microsoft.ML.Trainers; using Microsoft.ML.Trainers.FastTree; -using Microsoft.ML.Transforms; using Xunit; using Xunit.Abstractions; @@ -60,7 +59,7 @@ public void SaveOnnxModelLoadAndScoreFastTree() // Create prediction engine and test predictions. var originalPredictionEngine = model.CreatePredictionEngine(mlContext); // TODO #2982: ONNX produces vector types and not the original output type. - var onnxPredictionEngine = onnxWorkaroundPipeline.CreatePredictionEngine(mlContext); + var onnxPredictionEngine = onnxWorkaroundPipeline.CreatePredictionEngine(mlContext); // Take a handful of examples out of the dataset and compute predictions. var dataEnumerator = mlContext.Data.CreateEnumerable(mlContext.Data.TakeRows(data, 5), false); @@ -110,9 +109,9 @@ public void SaveOnnxModelLoadAndScoreKMeans() mlContext.Transforms.CopyColumns("Score", "Score0").Fit(onnxModel.Transform(data))); // Create prediction engine and test predictions. - var originalPredictionEngine = model.CreatePredictionEngine(mlContext); + var originalPredictionEngine = model.CreatePredictionEngine(mlContext); // TODO #2982: ONNX produces vector types and not the original output type. - var onnxPredictionEngine = onnxWorkaroundPipeline.CreatePredictionEngine(mlContext); + var onnxPredictionEngine = onnxWorkaroundPipeline.CreatePredictionEngine(mlContext); // Take a handful of examples out of the dataset and compute predictions. var dataEnumerator = mlContext.Data.CreateEnumerable(mlContext.Data.TakeRows(data, 5), false); @@ -164,7 +163,7 @@ public void SaveOnnxModelLoadAndScoreSDCA() // Create prediction engine and test predictions. var originalPredictionEngine = model.CreatePredictionEngine(mlContext); // TODO #2982: ONNX produces vector types and not the original output type. - var onnxPredictionEngine = onnxWorkaroundPipeline.CreatePredictionEngine(mlContext); + var onnxPredictionEngine = onnxWorkaroundPipeline.CreatePredictionEngine(mlContext); // Take a handful of examples out of the dataset and compute predictions. var dataEnumerator = mlContext.Data.CreateEnumerable(mlContext.Data.TakeRows(data, 5), false); @@ -176,20 +175,5 @@ public void SaveOnnxModelLoadAndScoreSDCA() Assert.Equal(originalPrediction.Score, onnxPrediction.Score[0], precision: 4); // Note the low-precision equality! } } - - private class ScoreColumn - { - public float Score { get; set; } - } - - private class OnnxScoreColumn - { - public float[] Score { get; set; } - } - - private class ClusteringScoreColumn - { - public float[] Score { get; set; } - } } } From c76c6f034e56f2344d424c2ab1967aa9608bb68e Mon Sep 17 00:00:00 2001 From: Rogan Carr Date: Tue, 19 Mar 2019 13:31:29 -0700 Subject: [PATCH 4/6] Adding xmldocs to column classes. --- .../Datasets/CommonColumns.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/Microsoft.ML.Functional.Tests/Datasets/CommonColumns.cs b/test/Microsoft.ML.Functional.Tests/Datasets/CommonColumns.cs index 7cf469ef57..348d2563f9 100644 --- a/test/Microsoft.ML.Functional.Tests/Datasets/CommonColumns.cs +++ b/test/Microsoft.ML.Functional.Tests/Datasets/CommonColumns.cs @@ -13,18 +13,24 @@ internal sealed class FeatureColumn } /// - /// A class to hold the output of FeatureContributionCalculator + /// A class to hold the output of FeatureContributionCalculator. /// internal sealed class FeatureContributionOutput { public float[] FeatureContributions { get; set; } } + /// + /// A class to hold the Score column. + /// internal sealed class ScoreColumn { public float Score { get; set; } } + /// + /// A class to hold a vector Score column. + /// internal sealed class VectorScoreColumn { public float[] Score { get; set; } From abcf7858e9f037dda44499759d6d8f89fefa54ba Mon Sep 17 00:00:00 2001 From: Rogan Carr Date: Tue, 19 Mar 2019 14:12:10 -0700 Subject: [PATCH 5/6] Updating docstrings. --- test/Microsoft.ML.Functional.Tests/ONNX.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Microsoft.ML.Functional.Tests/ONNX.cs b/test/Microsoft.ML.Functional.Tests/ONNX.cs index ddb64a81f3..ac2002cd40 100644 --- a/test/Microsoft.ML.Functional.Tests/ONNX.cs +++ b/test/Microsoft.ML.Functional.Tests/ONNX.cs @@ -21,7 +21,7 @@ public ONNX(ITestOutputHelper output) : base(output) } /// - /// ONNX: I can save a model to ONNX and reload it and use it in a pipeline. + /// ONNX: Models can be serialized to ONNX, deserialized back to ML.NET, and used a pipeline. /// [OnnxFactAttribute] public void SaveOnnxModelLoadAndScoreFastTree() @@ -73,7 +73,7 @@ public void SaveOnnxModelLoadAndScoreFastTree() } /// - /// ONNX: I can save a model to ONNX and reload it and use it in a pipeline. + /// ONNX: Models can be serialized to ONNX, deserialized back to ML.NET, and used a pipeline. /// [OnnxFactAttribute] public void SaveOnnxModelLoadAndScoreKMeans() @@ -125,7 +125,7 @@ public void SaveOnnxModelLoadAndScoreKMeans() } /// - /// ONNX: I can save a model to ONNX and reload it and use it in a pipeline. + /// ONNX: Models can be serialized to ONNX, deserialized back to ML.NET, and used a pipeline. /// [OnnxFactAttribute] public void SaveOnnxModelLoadAndScoreSDCA() From 8f7da32e5b6a2b546426175fb02ffc645ae9480e Mon Sep 17 00:00:00 2001 From: Rogan Carr Date: Tue, 19 Mar 2019 14:43:40 -0700 Subject: [PATCH 6/6] Updating relative to master --- test/Microsoft.ML.Functional.Tests/ONNX.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/Microsoft.ML.Functional.Tests/ONNX.cs b/test/Microsoft.ML.Functional.Tests/ONNX.cs index ac2002cd40..3ece5658b8 100644 --- a/test/Microsoft.ML.Functional.Tests/ONNX.cs +++ b/test/Microsoft.ML.Functional.Tests/ONNX.cs @@ -57,9 +57,9 @@ public void SaveOnnxModelLoadAndScoreFastTree() mlContext.Transforms.CopyColumns("Score", "Score0").Fit(onnxModel.Transform(data))); // Create prediction engine and test predictions. - var originalPredictionEngine = model.CreatePredictionEngine(mlContext); + var originalPredictionEngine = mlContext.Model.CreatePredictionEngine(model); // TODO #2982: ONNX produces vector types and not the original output type. - var onnxPredictionEngine = onnxWorkaroundPipeline.CreatePredictionEngine(mlContext); + var onnxPredictionEngine = mlContext.Model.CreatePredictionEngine(onnxWorkaroundPipeline); // Take a handful of examples out of the dataset and compute predictions. var dataEnumerator = mlContext.Data.CreateEnumerable(mlContext.Data.TakeRows(data, 5), false); @@ -109,9 +109,9 @@ public void SaveOnnxModelLoadAndScoreKMeans() mlContext.Transforms.CopyColumns("Score", "Score0").Fit(onnxModel.Transform(data))); // Create prediction engine and test predictions. - var originalPredictionEngine = model.CreatePredictionEngine(mlContext); + var originalPredictionEngine = mlContext.Model.CreatePredictionEngine(model); // TODO #2982: ONNX produces vector types and not the original output type. - var onnxPredictionEngine = onnxWorkaroundPipeline.CreatePredictionEngine(mlContext); + var onnxPredictionEngine = mlContext.Model.CreatePredictionEngine(onnxWorkaroundPipeline); // Take a handful of examples out of the dataset and compute predictions. var dataEnumerator = mlContext.Data.CreateEnumerable(mlContext.Data.TakeRows(data, 5), false); @@ -123,7 +123,7 @@ public void SaveOnnxModelLoadAndScoreKMeans() Common.AssertEqual(originalPrediction.Score, onnxPrediction.Score, precision: 4); // Note the low precision! } } - + /// /// ONNX: Models can be serialized to ONNX, deserialized back to ML.NET, and used a pipeline. /// @@ -161,9 +161,9 @@ public void SaveOnnxModelLoadAndScoreSDCA() mlContext.Transforms.CopyColumns("Score", "Score0").Fit(onnxModel.Transform(data))); // Create prediction engine and test predictions. - var originalPredictionEngine = model.CreatePredictionEngine(mlContext); + var originalPredictionEngine = mlContext.Model.CreatePredictionEngine(model); // TODO #2982: ONNX produces vector types and not the original output type. - var onnxPredictionEngine = onnxWorkaroundPipeline.CreatePredictionEngine(mlContext); + var onnxPredictionEngine = mlContext.Model.CreatePredictionEngine(onnxWorkaroundPipeline); // Take a handful of examples out of the dataset and compute predictions. var dataEnumerator = mlContext.Data.CreateEnumerable(mlContext.Data.TakeRows(data, 5), false);