Skip to content

Commit 982df42

Browse files
[AutoML] CodeGen For AzureAttach (#4498)
* build to modelbuilder * update Model project * update ConsoleApp * small update: * fix test and update * add IsAzureAttach to setting * remove a task * add some comments * refactor AzureImage CodeGenerator * still some refactor * some clean up * update * add LabelMapping.tt, rename some CodeGenerators * add ImageLabelMapping.cs * update ConsumeModel.cs * target AzureAttachModelCodeGenerator at ModelOutputClass instead of OnnxModelOutputClass * add test case for AzureImageCodeGenerator * rename AzureImageCodeGeneratorTest * add some test * rename AzureImageClassification to Azure * add AzureModelBuilder * add AzureCodeGeneratorTest * update ImageLabelMapping to accept label * remove AzureImageCodeGenerator * fix test * fix test * fix bugs * update base on Eric's review * Update TaskKind.cs * Update src/Microsoft.ML.CodeGenerator/CodeGenerator/CSharp/TransformGeneratorFactory.cs Co-Authored-By: Justin Ormont <[email protected]> * update based on Bri's change * rename ProjectFile to CSharpProjectFile, add CSharpCodeFile and stop using ProjectFileGenerator in codegen * rm partial class * rename Interface (add CSharp prefix) * implement IProjectGenerator in ICSharpSolutionGenerator to have same API with old CodeGen * add header * add LoadImage transformer Co-authored-by: Justin Ormont <[email protected]>
1 parent 3d8ed0b commit 982df42

File tree

84 files changed

+5622
-84
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+5622
-84
lines changed

src/Microsoft.ML.AutoML/EstimatorExtensions/EstimatorExtensionCatalog.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ internal enum EstimatorName
2020
TextFeaturizing,
2121
TypeConverting,
2222
ValueToKeyMapping,
23+
RawByteImageLoading,
2324
ImageLoading
2425
}
2526

@@ -39,7 +40,8 @@ internal class EstimatorExtensionCatalog
3940
{ EstimatorName.TextFeaturizing, typeof(TextFeaturizingExtension) },
4041
{ EstimatorName.TypeConverting, typeof(TypeConvertingExtension) },
4142
{ EstimatorName.ValueToKeyMapping, typeof(ValueToKeyMappingExtension) },
42-
{ EstimatorName.ImageLoading, typeof(ImageLoadingExtension) }
43+
{ EstimatorName.RawByteImageLoading, typeof(RawByteImageLoading) },
44+
{ EstimatorName.ImageLoading, typeof(ImageLoading) }
4345
};
4446

4547
public static IEstimatorExtension GetExtension(EstimatorName estimatorName)

src/Microsoft.ML.AutoML/EstimatorExtensions/EstimatorExtensions.cs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ private static IEstimator<ITransformer> CreateInstance(MLContext context, string
272272
}
273273
}
274274

275-
internal class ImageLoadingExtension : IEstimatorExtension
275+
internal class RawByteImageLoading : IEstimatorExtension
276276
{
277277
public static string ImageFolder { private get; set; }
278278
public IEstimator<ITransformer> CreateInstance(MLContext context, PipelineNode pipelineNode)
@@ -286,7 +286,7 @@ public static SuggestedTransform CreateSuggestedTransform(MLContext context, str
286286
{
287287
{ "imageFolder", ImageFolder },
288288
};
289-
var pipelineNode = new PipelineNode(EstimatorName.ImageLoading.ToString(), PipelineNodeType.Transform, inColumn, outColumn, pipelineNodeProperty);
289+
var pipelineNode = new PipelineNode(EstimatorName.RawByteImageLoading.ToString(), PipelineNodeType.Transform, inColumn, outColumn, pipelineNodeProperty);
290290
var estimator = CreateInstance(context, inColumn, outColumn);
291291
return new SuggestedTransform(pipelineNode, estimator);
292292
}
@@ -296,4 +296,29 @@ private static IEstimator<ITransformer> CreateInstance(MLContext context, string
296296
return context.Transforms.LoadRawImageBytes(outColumn, ImageFolder, inColumn);
297297
}
298298
}
299+
300+
internal class ImageLoading : IEstimatorExtension
301+
{
302+
public static string ImageFolder { private get; set; }
303+
public IEstimator<ITransformer> CreateInstance(MLContext context, PipelineNode pipelineNode)
304+
{
305+
return CreateInstance(context, pipelineNode.InColumns[0], pipelineNode.OutColumns[0]);
306+
}
307+
308+
public static SuggestedTransform CreateSuggestedTransform(MLContext context, string inColumn, string outColumn)
309+
{
310+
var pipelineNodeProperty = new Dictionary<string, object>()
311+
{
312+
{ "imageFolder", ImageFolder },
313+
};
314+
var pipelineNode = new PipelineNode(EstimatorName.ImageLoading.ToString(), PipelineNodeType.Transform, inColumn, outColumn, pipelineNodeProperty);
315+
var estimator = CreateInstance(context, inColumn, outColumn);
316+
return new SuggestedTransform(pipelineNode, estimator);
317+
}
318+
319+
private static IEstimator<ITransformer> CreateInstance(MLContext context, string inColumn, string outColumn)
320+
{
321+
return context.Transforms.LoadImages(outColumn, ImageFolder, inColumn);
322+
}
323+
}
299324
}

src/Microsoft.ML.AutoML/TransformInference/TransformInference.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ public override IEnumerable<SuggestedTransform> Apply(IntermediateColumn[] colum
358358
var columnDestSuffix = "_featurized";
359359
string columnDestRenamed = $"{column.ColumnName}{columnDestSuffix}";
360360

361-
yield return ImageLoadingExtension.CreateSuggestedTransform(Context, column.ColumnName, columnDestRenamed);
361+
yield return RawByteImageLoading.CreateSuggestedTransform(Context, column.ColumnName, columnDestRenamed);
362362
}
363363
}
364364
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.IO;
8+
using System.Text;
9+
using Microsoft.ML.AutoML;
10+
using Microsoft.ML.CodeGenerator.CodeGenerator.CSharp.Interface;
11+
using Microsoft.ML.CodeGenerator.CSharp;
12+
13+
namespace Microsoft.ML.CodeGenerator.CodeGenerator.CSharp.AzureCodeGenerator
14+
{
15+
internal class AzureAttachCodeGenenrator : ICSharpSolutionGenerator
16+
{
17+
public ICSharpProjectGenerator AzureAttachConsoleApp { get; private set; }
18+
public ICSharpProjectGenerator AzureAttachModel { get; private set; }
19+
public string Name { get; set; }
20+
21+
private readonly Pipeline _pipeline;
22+
private readonly CodeGeneratorSettings _settings;
23+
private readonly ColumnInferenceResults _columnInferenceResult;
24+
25+
public AzureAttachCodeGenenrator(Pipeline pipeline, ColumnInferenceResults columnInferenceResults, CodeGeneratorSettings options)
26+
{
27+
_pipeline = pipeline;
28+
_settings = options;
29+
_columnInferenceResult = columnInferenceResults;
30+
Name = _settings.OutputName;
31+
var namespaceValue = Utilities.Utils.Normalize(_settings.OutputName);
32+
AzureAttachConsoleApp = new AzureAttachConsoleAppCodeGenerator(_pipeline, _columnInferenceResult, _settings, namespaceValue);
33+
AzureAttachModel = new AzureAttachModelCodeGenerator(_pipeline, _columnInferenceResult, _settings, namespaceValue);
34+
}
35+
36+
public ICSharpSolution ToSolution()
37+
{
38+
var solution = new CSharpSolution()
39+
{
40+
AzureAttachConsoleApp.ToProject(),
41+
AzureAttachModel.ToProject()
42+
};
43+
44+
solution.Name = _settings.OutputName;
45+
return solution;
46+
}
47+
48+
public void GenerateOutput()
49+
{
50+
var folder = Path.Combine(_settings.OutputBaseDir, _settings.OutputName);
51+
ToSolution().WriteToDisk(folder);
52+
}
53+
}
54+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Collections;
7+
using System.Collections.Generic;
8+
using System.IO;
9+
using System.Linq;
10+
using System.Text;
11+
using Microsoft.CodeAnalysis;
12+
using Microsoft.ML.AutoML;
13+
using Microsoft.ML.CodeGenerator.CodeGenerator.CSharp.Interface;
14+
using Microsoft.ML.CodeGenerator.CSharp;
15+
using Microsoft.ML.CodeGenerator.Templates.Azure.Console;
16+
using Microsoft.ML.CodeGenerator.Templates.Console;
17+
using Microsoft.ML.Transforms;
18+
19+
namespace Microsoft.ML.CodeGenerator.CodeGenerator.CSharp
20+
{
21+
internal class AzureAttachConsoleAppCodeGenerator : ICSharpProjectGenerator
22+
{
23+
private readonly Pipeline _pipeline;
24+
private readonly CodeGeneratorSettings _settings;
25+
private readonly ColumnInferenceResults _columnInferenceResult;
26+
private readonly string _nameSpaceValue;
27+
28+
public ICSharpFile ModelBuilder { get; private set; }
29+
public ICSharpFile PredictProject { get; private set; }
30+
public ICSharpFile PredictProgram { get; private set; }
31+
public string Name { get; set; }
32+
33+
public AzureAttachConsoleAppCodeGenerator(Pipeline pipeline, ColumnInferenceResults columnInferenceResults, CodeGeneratorSettings options, string namespaceValue)
34+
{
35+
_pipeline = pipeline;
36+
_settings = options;
37+
_columnInferenceResult = columnInferenceResults;
38+
_nameSpaceValue = namespaceValue;
39+
Name = $"{_settings.OutputName}.ConsoleApp";
40+
41+
var (_, _, PreTrainerTransforms, _) = _pipeline.GenerateTransformsAndTrainers();
42+
43+
ModelBuilder = new CSharpCodeFile()
44+
{
45+
File = new AzureModelBuilder()
46+
{
47+
Path = _settings.TrainDataset,
48+
HasHeader = _columnInferenceResult.TextLoaderOptions.HasHeader,
49+
Separator = _columnInferenceResult.TextLoaderOptions.Separators.FirstOrDefault(),
50+
PreTrainerTransforms = PreTrainerTransforms,
51+
AllowQuoting = _columnInferenceResult.TextLoaderOptions.AllowQuoting,
52+
AllowSparse = _columnInferenceResult.TextLoaderOptions.AllowSparse,
53+
Namespace = _nameSpaceValue,
54+
Target = _settings.Target,
55+
OnnxModelPath = _settings.OnnxModelPath,
56+
MLNetModelpath = _settings.ModelPath,
57+
}.TransformText(),
58+
Name = "ModelBuilder.cs",
59+
};
60+
61+
PredictProject = new CSharpProjectFile()
62+
{
63+
File = new PredictProject()
64+
{
65+
Namespace = _nameSpaceValue,
66+
IncludeMklComponentsPackage = false,
67+
IncludeLightGBMPackage = false,
68+
IncludeFastTreePackage = false,
69+
IncludeImageTransformerPackage = _settings.IsImage,
70+
IncludeImageClassificationPackage = false,
71+
IncludeOnnxPackage = true,
72+
IncludeResNet18Package = false,
73+
IncludeRecommenderPackage = false,
74+
StablePackageVersion = _settings.StablePackageVersion,
75+
UnstablePackageVersion = _settings.UnstablePackageVersion,
76+
}.TransformText(),
77+
Name = $"{_settings.OutputName}.ConsoleApp.csproj",
78+
};
79+
80+
var columns = _columnInferenceResult.TextLoaderOptions.Columns;
81+
var featuresList = columns.Where((str) => str.Name != _settings.LabelName).Select((str) => str.Name).ToList();
82+
PredictProgram = new CSharpCodeFile()
83+
{
84+
File = new PredictProgram()
85+
{
86+
TaskType = _settings.MlTask.ToString(),
87+
LabelName = _settings.LabelName,
88+
Namespace = _nameSpaceValue,
89+
TestDataPath = _settings.TestDataset,
90+
TrainDataPath = _settings.TrainDataset,
91+
AllowQuoting = _columnInferenceResult.TextLoaderOptions.AllowQuoting,
92+
AllowSparse = _columnInferenceResult.TextLoaderOptions.AllowSparse,
93+
HasHeader = _columnInferenceResult.TextLoaderOptions.HasHeader,
94+
Separator = _columnInferenceResult.TextLoaderOptions.Separators.FirstOrDefault(),
95+
Target = _settings.Target,
96+
Features = featuresList,
97+
}.TransformText(),
98+
Name = "Program.cs",
99+
};
100+
}
101+
102+
public ICSharpProject ToProject()
103+
{
104+
var project = new CSharpProject()
105+
{
106+
ModelBuilder,
107+
PredictProject,
108+
PredictProgram,
109+
};
110+
111+
project.Name = Name;
112+
return project;
113+
}
114+
}
115+
}

0 commit comments

Comments
 (0)