Skip to content

Updated codegen to support object detection scenario. #5216

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
merged 40 commits into from
Aug 28, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
34d970f
Buffer re-use using ArrayPool and a few more checks (#4293)
harshithapv Oct 4, 2019
9bc3d7b
Image Classification API: Fix processing incomplete batch(<batchSize)…
ashbhandare Oct 4, 2019
c073e6b
upgrade to 3.1
LittleLittleCloud Apr 28, 2020
8f0fc1a
write inline data using invariantCulture
LittleLittleCloud Apr 28, 2020
e96d716
Merge branch 'master' of https://github.com/dotnet/machinelearning
LittleLittleCloud Apr 29, 2020
8c17bbe
Merge branch 'master' of https://github.com/dotnet/machinelearning
LittleLittleCloud May 14, 2020
b2947f5
Merge branch 'master' of https://github.com/dotnet/machinelearning
LittleLittleCloud May 18, 2020
ff1c909
Merge branch 'master' of https://github.com/dotnet/machinelearning
LittleLittleCloud May 20, 2020
c8f154b
Update: ModelBuilder codegen for Object Detection
ttstanley Jun 2, 2020
7da13e8
Merge branch 'u/tevin/ObjectDetectionCodeGen'
ttstanley Jun 2, 2020
8cedee5
updated testing files to give better test results
ttstanley Jun 2, 2020
44f18ef
Refactored test code
ttstanley Jun 3, 2020
eed5d85
trying to test performance
ttstanley Jun 3, 2020
045f93a
fix commit
Jun 8, 2020
c164c97
Adding changes from prior commit
ttstanley Jun 9, 2020
8d47c48
small changes to finilize codegen
ttstanley Jun 9, 2020
9226395
Made changes based on csproj
ttstanley Jun 10, 2020
b399a27
minor changes to make final build
ttstanley Jun 10, 2020
ce35740
updated onnxruntime to 1.3
ttstanley Jun 10, 2020
7ec0c2b
targetting older automl
ttstanley Jun 10, 2020
0fe683e
taking out dependency on automl taskkind for OD
ttstanley Jun 11, 2020
b7556da
final build got predictions working for OD
ttstanley Jun 11, 2020
737d5a7
Merge upstream into remote origin
ttstanley Jun 12, 2020
aa89ddf
Merge branch 'real/origin/master' into u/tevin/CodeGen
ttstanley Jun 12, 2020
f1aa8ac
took out old test paths to generalize tests
ttstanley Jun 12, 2020
93eaf54
cleaning up outdated comments
ttstanley Jun 15, 2020
2c03cf8
for the build packaging
ttstanley Jun 15, 2020
9f784f4
rebuild
ttstanley Jun 16, 2020
dad9055
Merge branch 'master' of https://github.com/dotnet/machinelearning
LittleLittleCloud Jul 20, 2020
741d77a
Merge branch 'master' of https://github.com/dotnet/machinelearning
LittleLittleCloud Jul 21, 2020
7f42788
Merge branch 'master' into u/tevin/CodeGen
LittleLittleCloud Jul 21, 2020
dad6672
fix tests
LittleLittleCloud Jul 21, 2020
45c462a
fix build error
LittleLittleCloud Jul 21, 2020
445f982
fix e2e bug
LittleLittleCloud Jul 22, 2020
594c828
Merge branch 'master' of https://github.com/dotnet/machinelearning
LittleLittleCloud Aug 26, 2020
a7d20ac
Merge branch 'master' into u/tevin/CodeGen
LittleLittleCloud Aug 26, 2020
82c672f
fix e2e bug
LittleLittleCloud Aug 26, 2020
9116501
Update Microsoft.ML.CodeGenerator.nupkgproj
LittleLittleCloud Aug 27, 2020
9473c48
Update Microsoft.ML.CodeGenerator.csproj
LittleLittleCloud Aug 27, 2020
ccc5d6c
remove .approved.txt that not used
LittleLittleCloud Aug 27, 2020
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
Prev Previous commit
Next Next commit
fix commit
  • Loading branch information
Tevin committed Jun 8, 2020
commit 045f93a4525d10f2a3661988cd3397fd98197731
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public AzureAttachModelCodeGenerator(Pipeline pipeline, ColumnInferenceResults c
Namespace = _nameSpaceValue,
ImportLabels = _settings.ClassificationLabel,
}.TransformText(),
Name = "LabelMapping.cs",
Name = "ObjectDetectionLabelMapping.cs",
};

ReshapeTransformerMap = new CSharpCodeFile()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ internal enum SpecialTransformer
LabelMapping = 4,
ObjectDetectionLabelMapping = 5, // Tevin: added for OD mappings
ReshapeTransformer = 6,
ObjectDetectionResizeImage = 7,
ObjectDetectionExtractPixel = 8,
ApplyObjectDetectionModel = 9,

}
internal static class TransformGeneratorFactory
Expand Down Expand Up @@ -103,6 +106,15 @@ internal static ITransformGenerator GetInstance(PipelineNode node)
case SpecialTransformer.ObjectDetectionLabelMapping:
result = new CustomObjectDetectionLabelMapping(node);
break;
case SpecialTransformer.ObjectDetectionExtractPixel:
result = new ObjectDetectionPixelExtract(node);
break;
case SpecialTransformer.ObjectDetectionResizeImage:
result = new ObjectDetectionImageResizing(node);
break;
case SpecialTransformer.ApplyObjectDetectionModel:
result = new ApplyObjectDetectionOnnxModel(node);
break;
case SpecialTransformer.ReshapeTransformer:
result = new CustomReshapeTransformer(node);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,17 @@ public override string GenerateTransformer()
}
}

internal class ObjectDetectionImageResizing : TransformGeneratorBase
{
public ObjectDetectionImageResizing(PipelineNode node) : base(node) { }
internal override string MethodName => "ResizeImages";

public override string GenerateTransformer()
{
return @"ResizeImages(outputColumnName: ""input"", imageWidth: 800, imageHeight: 600, inputColumnName: ""input"")";
}
}

internal class PixelExtract : TransformGeneratorBase
{
public PixelExtract(PipelineNode node) : base(node) { }
Expand All @@ -388,7 +399,18 @@ public override string GenerateTransformer()
}
}

internal class CustomNormalizeMapping : TransformGeneratorBase
internal class ObjectDetectionPixelExtract : TransformGeneratorBase
{
public ObjectDetectionPixelExtract(PipelineNode node) : base(node) { }
internal override string MethodName => "ExtractPixels";

public override string GenerateTransformer()
{
return @"ExtractPixels(outputColumnName: ""input"", inputColumnName: ""input"")";
}
}

internal class CustomNormalizeMapping : TransformGeneratorBase
{
public CustomNormalizeMapping(PipelineNode node) : base(node) { }
internal override string MethodName => "NormalizeMapping";
Expand Down Expand Up @@ -422,7 +444,7 @@ public CustomObjectDetectionLabelMapping(PipelineNode node) : base(node) { }

public override string GenerateTransformer()
{
return @"CustomMapping<ObjectDetectionLabelMappingInput, ModelOutput>( // added this line not sure what to do.
return @"CustomMapping<ObjectDetectionLabelMappingInput, ObjectDetectionLabelMappingOutput>( // added this line not sure what to do.
(input, output) => ObjectDetectionLabelMapping.Mapping(input, output),
contractName: nameof(ObjectDetectionLabelMapping))";
}
Expand All @@ -432,7 +454,7 @@ public override string GenerateTransformer()
internal class CustomReshapeTransformer : TransformGeneratorBase
{
public CustomReshapeTransformer(PipelineNode node) : base(node) { }
internal override string MethodName => "ObjectDetectionLabelMapping";
internal override string MethodName => "ReshapeTransformer";

public override string GenerateTransformer()
{
Expand All @@ -442,6 +464,18 @@ public override string GenerateTransformer()
}
}

// Tevin: added to have correct ApplyOnnxModel
internal class ApplyObjectDetectionOnnxModel : TransformGeneratorBase
{
public ApplyObjectDetectionOnnxModel(PipelineNode node) : base(node) { }
internal override string MethodName => "ApplyOnnxModel";

public override string GenerateTransformer()
{
return @"ApplyOnnxModel(modelFile: modelFile, outputColumnNames: new[] { ""boxes"",""labels"", ""scores"" }, inputColumnNames: new[] { ""input"" })";
}
}

internal class ApplyOnnxModel : TransformGeneratorBase
{
public ApplyOnnxModel(PipelineNode node) : base(node) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,18 @@ public class ObjectDetectionLabelMapping : CustomMappingFactory<ObjectDetectionL
"oat Bottom;\r\n\r\n public string Label;\r\n\r\n public float Score;\r\n\r\n " +
" public override string ToString()\r\n {\r\n return $\"Top: {t" +
"his.Top}, Left: {this.Left}, Right: {this.Right}, Bottom: {this.Bottom}, Label: " +
"{this.Label}, Score: {this.Score}\";\r\n }\r\n }\r\n\r\n\r\n public class Mode" +
"lOutput\r\n {\r\n [ColumnName(\"boxes\")]\r\n public float[] Boxes;\r\n\r\n" +
" [ColumnName(\"PredictedLabels\")]\r\n public string[] Labels;\r\n\r\n " +
" [ColumnName(\"scores\")]\r\n public float[] Scores;\r\n\r\n private Bo" +
"undingBox[] BoundingBoxes\r\n {\r\n get\r\n {\r\n " +
" var boundingBoxes = new List<BoundingBox>();\r\n return bound" +
"ingBoxes.ToArray();\r\n }\r\n }\r\n\r\n public BoundingBox[] Ge" +
"tBoundingBoxes()\r\n {\r\n return this.BoundingBoxes;\r\n }\r\n" +
"\r\n public override string ToString()\r\n {\r\n var sb = new" +
" StringBuilder();\r\n\r\n foreach (var box in this.BoundingBoxes)\r\n " +
" {\r\n sb.AppendLine(box.ToString());\r\n }\r\n\r\n " +
" return sb.ToString();\r\n }\r\n }\r\n}\r\n");
"{this.Label}, Score: {this.Score}\";\r\n }\r\n }\r\n\r\n\r\n public class Obje" +
"ctDetectionLabelMappingOutput\r\n {\r\n [ColumnName(\"boxes\")]\r\n pub" +
"lic float[] Boxes;\r\n\r\n [ColumnName(\"PredictedLabels\")]\r\n public st" +
"ring[] Labels;\r\n\r\n [ColumnName(\"scores\")]\r\n public float[] Scores;" +
"\r\n\r\n private BoundingBox[] BoundingBoxes\r\n {\r\n get\r\n " +
" {\r\n var boundingBoxes = new List<BoundingBox>();\r\n " +
" return boundingBoxes.ToArray();\r\n }\r\n }\r\n\r\n p" +
"ublic BoundingBox[] GetBoundingBoxes()\r\n {\r\n return this.Bound" +
"ingBoxes;\r\n }\r\n\r\n public override string ToString()\r\n {\r\n " +
" var sb = new StringBuilder();\r\n\r\n foreach (var box in this." +
"BoundingBoxes)\r\n {\r\n sb.AppendLine(box.ToString());\r\n " +
" }\r\n\r\n return sb.ToString();\r\n }\r\n }\r\n}\r\n");
return this.GenerationEnvironment.ToString();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ namespace <#= Namespace #>.Model
}


public class ModelOutput
public class ObjectDetectionLabelMappingOutput
{
[ColumnName("boxes")]
public float[] Boxes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public virtual string TransformText()
namespace Microsoft.ML.ModelBuilder.AutoMLService.RemoteAutoML.ObjectDetectionTransformerHelpers
{
[CustomMappingFactoryAttribute(nameof(ReshapeTransformer))]
class ReshapeTransformer : CustomMappingFactory<Input, Output>
public class ReshapeTransformer : CustomMappingFactory<Input, Output>
{
// This is the custom mapping. We now separate it into a method, so that we can use it both in training and in loading.
public static void Mapping(Input input, Output output)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ using Microsoft.ML.Transforms;
namespace Microsoft.ML.ModelBuilder.AutoMLService.RemoteAutoML.ObjectDetectionTransformerHelpers
{
[CustomMappingFactoryAttribute(nameof(ReshapeTransformer))]
class ReshapeTransformer : CustomMappingFactory<Input, Output>
public class ReshapeTransformer : CustomMappingFactory<Input, Output>
{
// This is the custom mapping. We now separate it into a method, so that we can use it both in training and in loading.
public static void Mapping(Input input, Output output)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,28 @@ public virtual string TransformText()
}
if("ObjectDetection".Equals(TaskType)){
this.Write(" [ColumnName(\"boxes\")]\r\n public float[] Boxes { get; set; }\r\n\r\n " +
" [ColumnName(\"PredictedLabels)]\r\n public string[] Labels { get; set; }" +
"\r\n\r\n [ColumnName(\"scores\")]\r\n public float[] Scores { get; set; }\r" +
"\n");
" [ColumnName(\"PredictedLabels\")]\r\n public string[] Labels { get; set; " +
"}\r\n\r\n [ColumnName(\"scores\")]\r\n public float[] Scores { get; set; }" +
"\r\n\r\n private BoundingBox[] BoundingBoxes\r\n {\r\n get\r\n " +
" {\r\n var boundingBoxes = new List<BoundingBox>();\r\n\r\n " +
" boundingBoxes = Enumerable.Range(0, this.Labels.Length)\r\n " +
" .Select((index) =>\r\n {\r\n " +
" var boxes = this.Boxes;\r\n var scores " +
"= this.Scores;\r\n var labels = this.Labels;\r\n\r\n " +
" return new BoundingBox()\r\n " +
" {\r\n Left = boxes[index * 4],\r\n " +
" Top = boxes[(index * 4) + 1],\r\n " +
" Right = boxes[(index * 4) + 2],\r\n Bottom = b" +
"oxes[(index * 4) + 3],\r\n Score = scores[index]," +
"\r\n Label = labels[index].ToString(),\r\n " +
" };\r\n }).ToList();\r\n " +
" return boundingBoxes.ToArray();\r\n }\r\n }\r\n }\r\n\r\n public " +
"class BoundingBox\r\n {\r\n public float Top;\r\n\r\n public float Left" +
";\r\n\r\n public float Right;\r\n\r\n public float Bottom;\r\n\r\n publ" +
"ic string Label;\r\n\r\n public float Score;\r\n\r\n public override strin" +
"g ToString()\r\n {\r\n return $\"Top: {this.Top}, Left: {this.Left}" +
", Right: {this.Right}, Bottom: {this.Bottom}, Label: {this.Label}, Score: {this." +
"Score}\";\r\n }\r\n");
} else if("MulticlassClassification".Equals(TaskType)){
this.Write(" public float[] Score { get; set; }\r\n");
}else{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,58 @@ namespace <#= Namespace #>.Model
[ColumnName("boxes")]
public float[] Boxes { get; set; }

[ColumnName("PredictedLabels)]
[ColumnName("PredictedLabels")]
public string[] Labels { get; set; }

[ColumnName("scores")]
public float[] Scores { get; set; }

private BoundingBox[] BoundingBoxes
{
get
{
var boundingBoxes = new List<BoundingBox>();

boundingBoxes = Enumerable.Range(0, this.Labels.Length)
.Select((index) =>
{
var boxes = this.Boxes;
var scores = this.Scores;
var labels = this.Labels;

return new BoundingBox()
{
Left = boxes[index * 4],
Top = boxes[(index * 4) + 1],
Right = boxes[(index * 4) + 2],
Bottom = boxes[(index * 4) + 3],
Score = scores[index],
Label = labels[index].ToString(),
};
}).ToList();
return boundingBoxes.ToArray();
}
}
}

public class BoundingBox
{
public float Top;

public float Left;

public float Right;

public float Bottom;

public string Label;

public float Score;

public override string ToString()
{
return $"Top: {this.Top}, Left: {this.Left}, Right: {this.Right}, Bottom: {this.Bottom}, Label: {this.Label}, Score: {this.Score}";
}
<#} else if("MulticlassClassification".Equals(TaskType)){ #>
public float[] Score { get; set; }
<#}else{ #>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ public virtual string TransformText()
if (IncludeOnnxModel){
this.Write(" <PackageReference Include=\"Microsoft.ML.OnnxTransformer\" Version=\"");
this.Write(this.ToStringHelper.ToStringWithCulture(StablePackageVersion));
this.Write("\" />\r\n");
this.Write("\" />\r\n <PackageReference Include=\"Microsoft.ML.OnnxRuntime\" Version=\"1.2.0\" />" +
"\r\n");
}
if (IncludeImageClassificationPackage){
this.Write(" <PackageReference Include=\"Microsoft.ML.Vision\" Version=\"");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<#}#>
<# if (IncludeOnnxModel){ #>
<PackageReference Include="Microsoft.ML.OnnxTransformer" Version="<#= StablePackageVersion #>" />
<PackageReference Include="Microsoft.ML.OnnxRuntime" Version="1.2.0" />
<#}#>
<# if (IncludeImageClassificationPackage){ #>
<PackageReference Include="Microsoft.ML.Vision" Version="<#= StablePackageVersion #>" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ public virtual string TransformText()
if (IncludeOnnxPackage){
this.Write(" <PackageReference Include=\"Microsoft.ML.OnnxTransformer\" Version=\"");
this.Write(this.ToStringHelper.ToStringWithCulture(StablePackageVersion));
this.Write("\" />\r\n");
this.Write("\" />\r\n <PackageReference Include=\"Microsoft.ML.OnnxRuntime\" Version=\"1.2.0\" />" +
"\r\n");
}
if (IncludeResNet18Package){
this.Write(" <PackageReference Include=\"Microsoft.ML.DnnImageFeaturizer.ResNet18\" Version=" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<#}#>
<# if (IncludeOnnxPackage){ #>
<PackageReference Include="Microsoft.ML.OnnxTransformer" Version="<#= StablePackageVersion #>" />
<PackageReference Include="Microsoft.ML.OnnxRuntime" Version="1.2.0" />
<#}#>
<# if (IncludeResNet18Package){ #>
<PackageReference Include="Microsoft.ML.DnnImageFeaturizer.ResNet18" Version="0.15.1" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.ML" Version="stableversion" />
<PackageReference Include="Microsoft.ML.OnnxTransformer" Version="stableversion" />
<PackageReference Include="Microsoft.ML.OnnxRuntime" Version="1.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CodeGenTest.Model\CodeGenTest.Model.csproj" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.ML" Version="stableversion" />
<PackageReference Include="Microsoft.ML.OnnxTransformer" Version="stableversion" />
<PackageReference Include="Microsoft.ML.OnnxRuntime" Version="1.2.0" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,14 @@ namespace CodeGenTest.ConsoleApp
// Data process configuration with pipeline data transformations to:
// 1. Score using provided onnx model
// 2. Map scores to labels to make model output easier to understand and use
var pipeline = mlContext.Transforms.LoadImages("/path/to/onnxModel", null, "ImagePath")
.Append(mlContext.Transforms.ResizeImages("ImageSource_featurized", 224, 224, "ImageSource_featurized"))
.Append(mlContext.Transforms.ExtractPixels("ImageSource_featurized", "ImageSource_featurized"))
var pipeline = mlContext.Transforms.LoadImages("input", null, "ImagePath")
.Append(mlContext.Transforms.ResizeImages(outputColumnName: "input", imageWidth: 800, imageHeight: 600, inputColumnName: "input"))
.Append(mlContext.Transforms.ExtractPixels(outputColumnName: "input", inputColumnName: "input"))
.Append(mlContext.Transforms.CustomMapping<Input, Output>(
(input, output) => ReshapeTransformer.Mapping(input, output),
contractName: nameof(ReshapeTransformer)))
.Append(mlContext.Transforms.ApplyOnnxModel(modelFile: ONNX_MODEL))
.Append(mlContext.Transforms.CustomMapping<ObjectDetectionLabelMappingInput, ModelOutput>( // added this line not sure what to do.
.Append(mlContext.Transforms.ApplyOnnxModel(modelFile: modelFile, outputColumnNames: new[] { "boxes", "labels", "scores" }, inputColumnNames: new[] { "input" }))
.Append(mlContext.Transforms.CustomMapping<ObjectDetectionLabelMappingInput, ObjectDetectionLabelMappingOutput>( // added this line not sure what to do.
(input, output) => ObjectDetectionLabelMapping.Mapping(input, output),
contractName: nameof(ObjectDetectionLabelMapping)));
return pipeline;
Expand Down
Loading