/// <summary> /// Initializes a new instance of the <see cref="OnnxModel"/> class. /// </summary> /// <param name="configuration">The configuration for the onnx model runner.</param> public OnnxModel(OnnxModelConfiguration configuration) { this.configuration = configuration; // The schemaDefinition is a ML.NET construct that allows us to specify the form // of the inputs. In this case we construct a schema definition programmatically // to reflect that the input is a vector of floats, of the sizes specified in the // configuration this.schemaDefinition = SchemaDefinition.Create(typeof(OnnxInputVector)); this.schemaDefinition[nameof(OnnxInputVector.Vector)].ColumnType = new VectorDataViewType(NumberDataViewType.Single, this.configuration.InputVectorSize); this.schemaDefinition[nameof(OnnxInputVector.Vector)].ColumnName = this.configuration.InputVectorName; // We create the onnxTransformer which will be used to score inputs var onnxEmptyInputDataView = this.context.Data.LoadFromEnumerable(new List <OnnxInputVector>(), this.schemaDefinition); var scoringEstimator = this.context.Transforms.ApplyOnnxModel( modelFile: configuration.ModelFileName, outputColumnNames: new[] { configuration.OutputVectorName }, inputColumnNames: new[] { configuration.InputVectorName }, shapeDictionary: configuration.ShapeDictionary, gpuDeviceId: configuration.GpuDeviceId, fallbackToCpu: false); this.onnxTransformer = scoringEstimator.Fit(onnxEmptyInputDataView); }
/// <summary> /// Initializes a new instance of the <see cref="MaskRCNNOnnxModel"/> class. /// </summary> /// <param name="imageWidth">Input image width.</param> /// <param name="imageHeight">Input image height.</param> /// <param name="modelFileName">Model file name.</param> /// <param name="gpuDeviceId">GPU device ID to run execution on, or null to run on CPU.</param> /// <remarks> /// To run on a GPU, use the Microsoft.Psi.Onnx.Gpu library instead of Microsoft.Psi.Onnx.Cpu, and pass /// a valid non-negative integer. Typical device ID values are 0 or 1. /// </remarks> public MaskRCNNOnnxModel(int imageWidth, int imageHeight, string modelFileName, int?gpuDeviceId = null) { //// REVIEW: note the ColumnType below is (float, 3, height, width), while the plain OnnxModel is simply (float, size) //// the rest is very similar to OnnxModel this.schemaDefinition = SchemaDefinition.Create(typeof(OnnxInputVector)); this.schemaDefinition[nameof(OnnxInputVector.Vector)].ColumnType = new VectorDataViewType(NumberDataViewType.Single, 3, imageHeight, imageWidth); this.schemaDefinition[nameof(OnnxInputVector.Vector)].ColumnName = "image"; var onnxEmptyInputDataView = this.context.Data.LoadFromEnumerable(new List <OnnxInputVector>(), this.schemaDefinition); var shapeDictionary = new Dictionary <string, int[]>() { { "image", new int[] { 3, imageHeight, imageWidth } } }; var scoringEstimator = this.context.Transforms.ApplyOnnxModel( modelFile: modelFileName, inputColumnNames: new[] { "image" }, outputColumnNames: new[] { BOXES, LABELS, SCORES, MASKS }, shapeDictionary: shapeDictionary, gpuDeviceId: gpuDeviceId, fallbackToCpu: false); this.onnxTransformer = scoringEstimator.Fit(onnxEmptyInputDataView); }
public void OnnxModelScenario() { var modelFile = "squeezenet/00000001/model.onnx"; using (var env = new ConsoleEnvironment(seed: 1, conc: 1)) { var samplevector = GetSampleArrayData(); var dataView = ML.Data.ReadFromEnumerable( new TestData[] { new TestData() { data_0 = samplevector } }); var onnx = new OnnxTransformer(env, "softmaxout_1", modelFile, "data_0").Transform(dataView); onnx.Schema.TryGetColumnIndex("softmaxout_1", out int score); using (var curs = onnx.GetRowCursor(onnx.Schema["softmaxout_1"])) { var getScores = curs.GetGetter <VBuffer <float> >(score); var buffer = default(VBuffer <float>); while (curs.MoveNext()) { getScores(ref buffer); Assert.Equal(1000, buffer.Length); } } } }
[ConditionalFact(typeof(Environment), nameof(Environment.Is64BitProcess))] // x86 output differs from Baseline public void OnnxModelMultiInput() { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return; } var modelFile = @"twoinput\twoinput.onnx"; using (var env = new ConsoleEnvironment(seed: 1, conc: 1)) { var samplevector = GetSampleArrayData(); var dataView = ComponentCreation.CreateDataView(Env, new TestDataMulti[] { new TestDataMulti() { ina = new float[] { 1, 2, 3, 4, 5 }, inb = new float[] { 1, 2, 3, 4, 5 } } }); var onnx = new OnnxTransformer(env, modelFile, new[] { "ina", "inb" }, new[] { "outa", "outb" }).Transform(dataView); onnx.Schema.TryGetColumnIndex("outa", out int scoresa); onnx.Schema.TryGetColumnIndex("outb", out int scoresb); using (var curs = onnx.GetRowCursor(col => col == scoresa || col == scoresb)) { var getScoresa = curs.GetGetter <VBuffer <float> >(scoresa); var getScoresb = curs.GetGetter <VBuffer <float> >(scoresb); var buffera = default(VBuffer <float>); var bufferb = default(VBuffer <float>); while (curs.MoveNext()) { getScoresa(ref buffera); getScoresb(ref bufferb); Assert.Equal(5, buffera.Length); Assert.Equal(5, bufferb.Length); Assert.Equal(0, buffera.GetValues().ToArray().Sum()); Assert.Equal(30, bufferb.GetValues().ToArray().Sum()); } } } }
public void OnnxModelMultiInput() { var modelFile = Path.Combine(Directory.GetCurrentDirectory(), "twoinput", "twoinput.onnx"); using (var env = new ConsoleEnvironment(seed: 1, conc: 1)) { var samplevector = GetSampleArrayData(); var dataView = ML.Data.ReadFromEnumerable( new TestDataMulti[] { new TestDataMulti() { ina = new float[] { 1, 2, 3, 4, 5 }, inb = new float[] { 1, 2, 3, 4, 5 } } }); var onnx = new OnnxTransformer(env, new[] { "outa", "outb" }, new[] { "ina", "inb" }, modelFile).Transform(dataView); onnx.Schema.TryGetColumnIndex("outa", out int scoresa); onnx.Schema.TryGetColumnIndex("outb", out int scoresb); using (var curs = onnx.GetRowCursor(onnx.Schema["outa"], onnx.Schema["outb"])) { var getScoresa = curs.GetGetter <VBuffer <float> >(scoresa); var getScoresb = curs.GetGetter <VBuffer <float> >(scoresb); var buffera = default(VBuffer <float>); var bufferb = default(VBuffer <float>); while (curs.MoveNext()) { getScoresa(ref buffera); getScoresb(ref bufferb); Assert.Equal(5, buffera.Length); Assert.Equal(5, bufferb.Length); Assert.Equal(0, buffera.GetValues().ToArray().Sum()); Assert.Equal(30, bufferb.GetValues().ToArray().Sum()); } } } }
[ConditionalFact(typeof(Environment), nameof(Environment.Is64BitProcess))] // x86 output differs from Baseline public void OnnxModelScenario() { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return; } var modelFile = "squeezenet/00000001/model.onnx"; using (var env = new ConsoleEnvironment(seed: 1, conc: 1)) { var samplevector = GetSampleArrayData(); var dataView = ComponentCreation.CreateDataView(Env, new TestData[] { new TestData() { data_0 = samplevector } }); var onnx = new OnnxTransformer(env, modelFile, "data_0", "softmaxout_1").Transform(dataView); onnx.Schema.TryGetColumnIndex("softmaxout_1", out int score); using (var curs = onnx.GetRowCursor(onnx.Schema["softmaxout_1"])) { var getScores = curs.GetGetter <VBuffer <float> >(score); var buffer = default(VBuffer <float>); while (curs.MoveNext()) { getScores(ref buffer); Assert.Equal(1000, buffer.Length); } } } }
public void TestOnnxTransformWithCustomShapes() { // The loaded model has input shape [-1, 3] and output shape [-1]. var modelFile = Path.Combine(Directory.GetCurrentDirectory(), "unknowndimensions", "test_unknowndimensions_float.onnx"); var dataPoints = new InputWithCustomShape[] { // It's a flattened 3-by-3 tensor. // [1.1, 1.3, 1.2] // |1.9, 1.3, 1.2| // [1.1, 1.3, 1.8] new InputWithCustomShape() { input = new float[] { 1.1f, 1.3f, 1.2f, 1.9f, 1.3f, 1.2f, 1.1f, 1.3f, 1.8f } }, // It's a flattened 3-by-3 tensor. // [0, 0, 1] // |1, 0, 0| // [1, 0, 0] new InputWithCustomShape() { input = new float[] { 0f, 0f, 1f, 1f, 0f, 0f, 1f, 0f, 0f } } }; var shapeDictionary = new Dictionary <string, int[]>() { { nameof(InputWithCustomShape.input), new int[] { 3, 3 } } }; var dataView = ML.Data.LoadFromEnumerable(dataPoints); var pipeline = new OnnxScoringEstimator[3]; var onnxTransformer = new OnnxTransformer[3]; var transformedDataViews = new IDataView[3]; // Test three public ONNX APIs with the custom shape. // Test 1. pipeline[0] = ML.Transforms.ApplyOnnxModel( new[] { nameof(PredictionWithCustomShape.argmax) }, new[] { nameof(InputWithCustomShape.input) }, modelFile, shapeDictionary); onnxTransformer[0] = pipeline[0].Fit(dataView); transformedDataViews[0] = onnxTransformer[0].Transform(dataView); // Test 2. pipeline[1] = ML.Transforms.ApplyOnnxModel( nameof(PredictionWithCustomShape.argmax), nameof(InputWithCustomShape.input), modelFile, shapeDictionary); onnxTransformer[1] = pipeline[1].Fit(dataView); transformedDataViews[1] = onnxTransformer[1].Transform(dataView); // Test 3. pipeline[2] = ML.Transforms.ApplyOnnxModel(modelFile, shapeDictionary); onnxTransformer[2] = pipeline[2].Fit(dataView); transformedDataViews[2] = onnxTransformer[2].Transform(dataView); // Conduct the same check for all the 3 called public APIs. foreach (var transformedDataView in transformedDataViews) { var transformedDataPoints = ML.Data.CreateEnumerable <PredictionWithCustomShape>(transformedDataView, false).ToList(); // One data point generates one transformed data point. Assert.Equal(dataPoints.Count(), transformedDataPoints.Count); // Check result numbers. They are results of applying ONNX argmax along the second axis; for example // [1.1, 1.3, 1.2] ---> [1] because 1.3 (indexed by 1) is the largest element. // |1.9, 1.3, 1.2| ---> |0| 1.9 0 // [1.1, 1.3, 1.8] ---> [2] 1.8 2 var expectedResults = new long[][] { new long[] { 1, 0, 2 }, new long[] { 2, 0, 0 } }; for (int i = 0; i < transformedDataPoints.Count; ++i) { Assert.Equal(transformedDataPoints[i].argmax, expectedResults[i]); } } for (int i = 0; i < 3; i++) { (onnxTransformer[i] as IDisposable)?.Dispose(); } }
/// <summary> /// Initializes a new instance of <see cref="OnnxScoringEstimator"/>. /// </summary> /// <param name="catalog">The transform's catalog.</param> /// <param name="transformer">The ONNX transformer.</param> public static OnnxScoringEstimator ApplyOnnxModel(this TransformsCatalog catalog, OnnxTransformer transformer) => new OnnxScoringEstimator(CatalogUtils.GetEnvironment(catalog), transformer);