Skip to content
This repository was archived by the owner on Nov 16, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f2444ff
Add initial implementation of the export to ONNX functionality.
Jun 19, 2019
52c923b
Update the Microsoft.ML.OnnxConverter version in Platforms/build.csproj
Jul 12, 2019
23e933a
Add test for verifying onnx export support.
Jul 12, 2019
02645e5
Update the onnx conversion to be compatible with the latest changes
Jul 17, 2019
016c34a
Merge branch 'master' into onnx_export
Oct 16, 2019
a445f0d
Fix a few of the issues with test_export_to_onnx.
Oct 16, 2019
c22d5d0
Merge branch 'master' into onnx_export
Oct 16, 2019
f95884b
Merge branch 'master' into onnx_export
Oct 21, 2019
d11fffd
Add onnxruntime.dll to the NimbusML python package. It is already inc…
Oct 30, 2019
b3c6d62
Initial implementation of the OnnxRunner transform.
Oct 30, 2019
3aa1871
Fix missing reference to models_onnxconverter in nimbusml.pyproj.
Oct 30, 2019
65a3fa0
Merge branch 'onnx-export-and-execute' into onnx_export
Oct 30, 2019
781c05f
Merge branch 'master' into onnx_export
Oct 30, 2019
cc87fbb
Exclude OnnxRunner from the test_export_to_onnx tests.
Oct 31, 2019
2a80494
Remove OnnxRunner from test_estimator_checks.
Oct 31, 2019
1be3789
Merge branch 'master' into onnx_export
Dec 6, 2019
6331e93
Add back in OnnxConverter reference which was accidentally removed in…
Dec 6, 2019
f1b2c9c
Update onnx export test. TypeConverter, MeanVarianceScaler, MinMaxSca…
Dec 6, 2019
a988faf
Pretty print the output of test_export_to_onnx.
Dec 6, 2019
f5f7eb0
Merge branch 'master' into onnx_export
Dec 13, 2019
25caeb2
Merge branch 'master' into onnx_export
Dec 27, 2019
5dc5a91
Update to the latest version of ML.Net.
Dec 27, 2019
aabd76c
Merge branch 'master' into onnx_export
Dec 30, 2019
301894e
Update supported estimators in test_export_to_onnx.
Dec 31, 2019
1bde044
Merge branch 'master' into onnx_export
Jan 28, 2020
79cb2b5
Use the latest nightly builds for the ML.Net packages.
Jan 28, 2020
7421d0a
Merge branch 'aml' into onnx_export
ganik Jan 28, 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
1 change: 1 addition & 0 deletions build/libs_win.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ TensorFlow.NET.dll
NumSharp.Core.dll
System.Drawing.Common.dll
Microsoft.ML.*
onnxruntime.dll
2 changes: 1 addition & 1 deletion src/DotNetBridge/Bridge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ private static unsafe int GenericExec(EnvironmentBlock* penv, sbyte* psz, int cd
//env.ComponentCatalog.RegisterAssembly(typeof(AutoInference).Assembly); // ML.PipelineInference
env.ComponentCatalog.RegisterAssembly(typeof(DataViewReference).Assembly);
env.ComponentCatalog.RegisterAssembly(typeof(ImageLoadingTransformer).Assembly);
//env.ComponentCatalog.RegisterAssembly(typeof(SaveOnnxCommand).Assembly);
env.ComponentCatalog.RegisterAssembly(typeof(OnnxExportExtensions).Assembly);
//env.ComponentCatalog.RegisterAssembly(typeof(TimeSeriesProcessingEntryPoints).Assembly);
//env.ComponentCatalog.RegisterAssembly(typeof(ParquetLoader).Assembly);
env.ComponentCatalog.RegisterAssembly(typeof(SsaChangePointDetector).Assembly);
Expand Down
1 change: 1 addition & 0 deletions src/DotNetBridge/DotNetBridge.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<PackageReference Include="Microsoft.ML.Mkl.Components" Version="1.5.0-preview*" />
<PackageReference Include="Microsoft.ML.ImageAnalytics" Version="1.5.0-preview*" />
<PackageReference Include="Microsoft.ML.LightGBM" Version="1.5.0-preview*" />
<PackageReference Include="Microsoft.ML.OnnxConverter" Version="0.17.0-preview*" />
<PackageReference Include="Microsoft.ML.OnnxTransformer" Version="1.5.0-preview*" />
<PackageReference Include="Microsoft.ML.TensorFlow" Version="1.5.0-preview*" />
<PackageReference Include="Microsoft.ML.Vision" Version="1.5.0-preview*" />
Expand Down
54 changes: 54 additions & 0 deletions src/DotNetBridge/Entrypoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,5 +178,59 @@ public static ScoringTransformOutput Score(IHostEnvironment env, ScoringTransfor
};

}

public sealed class OnnxTransformInput : TransformInputBase
{
[Argument(ArgumentType.Required, HelpText = "Path to the onnx model file.", ShortName = "model", SortOrder = 0)]
public string ModelFile;

[Argument(ArgumentType.Multiple, HelpText = "Name of the input column.", SortOrder = 1)]
public string[] InputColumns;

[Argument(ArgumentType.Multiple, HelpText = "Name of the output column.", SortOrder = 2)]
public string[] OutputColumns;

[Argument(ArgumentType.AtMostOnce, HelpText = "GPU device id to run on (e.g. 0,1,..). Null for CPU. Requires CUDA 9.1.", SortOrder = 3)]
public int? GpuDeviceId = null;

[Argument(ArgumentType.AtMostOnce, HelpText = "If true, resumes execution on CPU upon GPU error. If false, will raise the GPU execption.", SortOrder = 4)]
public bool FallbackToCpu = false;
}

public sealed class OnnxTransformOutput
{
[TlcModule.Output(Desc = "ONNX transformed dataset", SortOrder = 1)]
public IDataView OutputData;

[TlcModule.Output(Desc = "Transform model", SortOrder = 2)]
public TransformModel Model;
}

[TlcModule.EntryPoint(Name = "Models.OnnxTransformer",
Desc = "Applies an ONNX model to a dataset.",
UserName = "Onnx Transformer",
ShortName = "onnx-xf")]
public static OnnxTransformOutput ApplyOnnxModel(IHostEnvironment env, OnnxTransformInput input)
{
var host = EntryPointUtils.CheckArgsAndCreateHost(env, "OnnxTransform", input);

var inputColumns = input.InputColumns ?? (Array.Empty<string>());
var outputColumns = input.OutputColumns ?? (Array.Empty<string>());

var transformsCatalog = new TransformsCatalog(host);
var onnxScoringEstimator = OnnxCatalog.ApplyOnnxModel(transformsCatalog,
outputColumns,
inputColumns,
input.ModelFile,
input.GpuDeviceId,
input.FallbackToCpu);

var view = onnxScoringEstimator.Fit(input.Data).Transform(input.Data);
return new OnnxTransformOutput()
{
Model = new TransformModelImpl(host, view, input.Data),
OutputData = view
};
}
}
}
1 change: 1 addition & 0 deletions src/DotNetBridge/ManifestUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public static class ManifestUtils
typeof(ImageLoadingTransformer),
typeof(SymbolicSgdLogisticRegressionBinaryTrainer),
typeof(OnnxContext),
typeof(OnnxExportExtensions),
typeof(SsaForecastingTransformer),
typeof(VariableColumnTransform),
typeof(DateTimeTransformer)
Expand Down
1 change: 1 addition & 0 deletions src/Platforms/build.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<PackageReference Include="Microsoft.ML.Mkl.Components" Version="1.5.0-preview*" />
<PackageReference Include="Microsoft.ML.ImageAnalytics" Version="1.5.0-preview*" />
<PackageReference Include="Microsoft.ML.LightGBM" Version="1.5.0-preview*" />
<PackageReference Include="Microsoft.ML.OnnxConverter" Version="0.17.0-preview*" />
<PackageReference Include="Microsoft.ML.OnnxTransformer" Version="1.5.0-preview*" />
<PackageReference Include="Microsoft.ML.TensorFlow" Version="1.5.0-preview*" />
<PackageReference Include="Microsoft.ML.Vision" Version="1.5.0-preview*" />
Expand Down
5 changes: 5 additions & 0 deletions src/python/nimbusml.pyproj
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@
<Compile Include="nimbusml\internal\core\preprocessing\filter\skipfilter.py" />
<Compile Include="nimbusml\internal\core\preprocessing\filter\takefilter.py" />
<Compile Include="nimbusml\internal\core\preprocessing\normalization\lpscaler.py" />
<Compile Include="nimbusml\internal\core\preprocessing\onnxrunner.py" />
<Compile Include="nimbusml\internal\core\preprocessing\normalization\robustscaler.py" />
<Compile Include="nimbusml\internal\core\preprocessing\schema\prefixcolumnconcatenator.py" />
<Compile Include="nimbusml\internal\core\preprocessing\schema\columnduplicator.py" />
Expand Down Expand Up @@ -359,6 +360,8 @@
<Compile Include="nimbusml\internal\entrypoints\models_multioutputregressionevaluator.py" />
<Compile Include="nimbusml\internal\entrypoints\models_naivecalibrator.py" />
<Compile Include="nimbusml\internal\entrypoints\models_oneversusall.py" />
<Compile Include="nimbusml\internal\entrypoints\models_onnxconverter.py" />
<Compile Include="nimbusml\internal\entrypoints\models_onnxtransformer.py" />
<Compile Include="nimbusml\internal\entrypoints\models_ovamodelcombiner.py" />
<Compile Include="nimbusml\internal\entrypoints\models_pavcalibrator.py" />
<Compile Include="nimbusml\internal\entrypoints\models_plattcalibrator.py" />
Expand Down Expand Up @@ -672,6 +675,7 @@
<Compile Include="nimbusml\preprocessing\normalization\minmaxscaler.py" />
<Compile Include="nimbusml\preprocessing\normalization\robustscaler.py" />
<Compile Include="nimbusml\preprocessing\normalization\__init__.py" />
<Compile Include="nimbusml\preprocessing\onnxrunner.py" />
<Compile Include="nimbusml\preprocessing\schema\prefixcolumnconcatenator.py" />
<Compile Include="nimbusml\preprocessing\schema\columnconcatenator.py" />
<Compile Include="nimbusml\preprocessing\schema\columndropper.py" />
Expand Down Expand Up @@ -747,6 +751,7 @@
<Compile Include="nimbusml\timeseries\ssaspikedetector.py" />
<Compile Include="nimbusml\timeseries\timeseriesimputer.py" />
<Compile Include="nimbusml\timeseries\__init__.py" />
<Compile Include="tests_extended\test_export_to_onnx.py" />
<Compile Include="tests\test_estimator_checks.py" />
<Compile Include="nimbusml\tests\feature_extraction\text\test_lightlda.py" />
<Compile Include="nimbusml\tests\idv\test_idv.py" />
Expand Down
18 changes: 17 additions & 1 deletion src/python/nimbusml/base_predictor.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,6 @@ def summary(self):
self.model_summary_ = pipeline.summary()
return self.model_summary_

@trace
def _get_implicit_transforms(
self,
features,
Expand Down Expand Up @@ -354,3 +353,20 @@ def _get_graph_nodes(
row_group_column_name=group_id_column)
graph_nodes['learner_node'] = [learner_node]
return graph_nodes, learner_features

@trace
def export_to_onnx(self, *args, **kwargs):
"""
Export the model to the ONNX format.

See :py:meth:`nimbusml.Pipeline.export_to_onnx` for accepted arguments.
"""
if not hasattr(self, 'model_') \
or self.model_ is None \
or not os.path.isfile(self.model_):

raise ValueError("Model is not fitted. Train or load a model before "
"export_to_onnx().")

pipeline = Pipeline([self], model=self.model_)
pipeline.export_to_onnx(*args, **kwargs)
17 changes: 17 additions & 0 deletions src/python/nimbusml/base_transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,20 @@ def transform(self, X, as_binary_data_stream=False, **params):
data = pipeline.transform(
X, as_binary_data_stream=as_binary_data_stream, **params)
return data

@trace
def export_to_onnx(self, *args, **kwargs):
"""
Export the model to the ONNX format.

See :py:meth:`nimbusml.Pipeline.export_to_onnx` for accepted arguments.
"""
if not hasattr(self, 'model_') \
or self.model_ is None \
or not os.path.isfile(self.model_):

raise ValueError("Model is not fitted. Train or load a model before "
"export_to_onnx().")

pipeline = Pipeline([self], model=self.model_)
pipeline.export_to_onnx(*args, **kwargs)
71 changes: 71 additions & 0 deletions src/python/nimbusml/internal/core/preprocessing/onnxrunner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
# --------------------------------------------------------------------------------------------
# - Generated by tools/entrypoint_compiler.py: do not edit by hand
"""
OnnxRunner
"""

__all__ = ["OnnxRunner"]


from ...entrypoints.models_onnxtransformer import models_onnxtransformer
from ...utils.utils import trace
from ..base_pipeline_item import BasePipelineItem, DefaultSignature


class OnnxRunner(BasePipelineItem, DefaultSignature):
"""
**Description**
Applies an ONNX model to a dataset.

:param model_file: Path to the onnx model file.

:param input_columns: Name of the input column.

:param output_columns: Name of the output column.

:param gpu_device_id: GPU device id to run on (e.g. 0,1,..). Null for CPU.
Requires CUDA 9.1.

:param fallback_to_cpu: If true, resumes execution on CPU upon GPU error.
If false, will raise the GPU execption.

:param params: Additional arguments sent to compute engine.

"""

@trace
def __init__(
self,
model_file,
input_columns=None,
output_columns=None,
gpu_device_id=None,
fallback_to_cpu=False,
**params):
BasePipelineItem.__init__(
self, type='transform', **params)

self.model_file = model_file
self.input_columns = input_columns
self.output_columns = output_columns
self.gpu_device_id = gpu_device_id
self.fallback_to_cpu = fallback_to_cpu

@property
def _entrypoint(self):
return models_onnxtransformer

@trace
def _get_node(self, **all_args):
algo_args = dict(
model_file=self.model_file,
input_columns=self.input_columns,
output_columns=self.output_columns,
gpu_device_id=self.gpu_device_id,
fallback_to_cpu=self.fallback_to_cpu)

all_args.update(algo_args)
return self._entrypoint(**all_args)
116 changes: 116 additions & 0 deletions src/python/nimbusml/internal/entrypoints/models_onnxconverter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# - Generated by tools/entrypoint_compiler.py: do not edit by hand
"""
Models.OnnxConverter
"""


from ..utils.entrypoints import EntryPoint
from ..utils.utils import try_set, unlist


def models_onnxconverter(
onnx,
data_file=None,
json=None,
name=None,
domain=None,
inputs_to_drop=None,
outputs_to_drop=None,
model=None,
onnx_version='Stable',
predictive_model=None,
**params):
"""
**Description**
Converts the model to ONNX format.

:param data_file: The data file (inputs).
:param onnx: The path to write the output ONNX to. (inputs).
:param json: The path to write the output JSON to. (inputs).
:param name: The 'name' property in the output ONNX. By default
this will be the ONNX extension-less name. (inputs).
:param domain: The 'domain' property in the output ONNX.
(inputs).
:param inputs_to_drop: Array of input column names to drop
(inputs).
:param outputs_to_drop: Array of output column names to drop
(inputs).
:param model: Model that needs to be converted to ONNX format.
(inputs).
:param onnx_version: The targeted ONNX version. It can be either
"Stable" or "Experimental". If "Experimental" is used,
produced model can contain components that is not officially
supported in ONNX standard. (inputs).
:param predictive_model: Predictor model that needs to be
converted to ONNX format. (inputs).
"""

entrypoint_name = 'Models.OnnxConverter'
inputs = {}
outputs = {}

if data_file is not None:
inputs['DataFile'] = try_set(
obj=data_file,
none_acceptable=True,
is_of_type=str)
if onnx is not None:
inputs['Onnx'] = try_set(
obj=onnx,
none_acceptable=False,
is_of_type=str)
if json is not None:
inputs['Json'] = try_set(
obj=json,
none_acceptable=True,
is_of_type=str)
if name is not None:
inputs['Name'] = try_set(
obj=name,
none_acceptable=True,
is_of_type=str,
is_column=True)
if domain is not None:
inputs['Domain'] = try_set(
obj=domain,
none_acceptable=True,
is_of_type=str)
if inputs_to_drop is not None:
inputs['InputsToDrop'] = try_set(
obj=inputs_to_drop,
none_acceptable=True,
is_of_type=list)
if outputs_to_drop is not None:
inputs['OutputsToDrop'] = try_set(
obj=outputs_to_drop,
none_acceptable=True,
is_of_type=list)
if model is not None:
inputs['Model'] = try_set(
obj=model,
none_acceptable=True,
is_of_type=str)
if onnx_version is not None:
inputs['OnnxVersion'] = try_set(
obj=onnx_version,
none_acceptable=True,
is_of_type=str,
values=[
'Stable',
'Experimental'])
if predictive_model is not None:
inputs['PredictiveModel'] = try_set(
obj=predictive_model, none_acceptable=True, is_of_type=str)

input_variables = {
x for x in unlist(inputs.values())
if isinstance(x, str) and x.startswith("$")}
output_variables = {
x for x in unlist(outputs.values())
if isinstance(x, str) and x.startswith("$")}

entrypoint = EntryPoint(
name=entrypoint_name, inputs=inputs, outputs=outputs,
input_variables=input_variables,
output_variables=output_variables)
return entrypoint
Loading