Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
adam444555 authored Nov 12, 2021
2 parents ea35bf7 + 813c861 commit 4977b9e
Show file tree
Hide file tree
Showing 26 changed files with 584 additions and 178 deletions.
34 changes: 18 additions & 16 deletions .azure-pipelines/linux-conda-CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
Py39-Onnx1101-Rt190-Skl0242:
do.bench: '0'
python.version: '3.9'
numpy.version: '>=1.18.1'
numpy.version: '<1.21.0'
onnx.version: '==1.10.1' # 'test'
onnx.target_opset: ''
onnxrt.version: 'onnxruntime==1.9.0' # '-i https://test.pypi.org/simple/ ort-nightly'
Expand All @@ -36,17 +36,17 @@ jobs:
Py39-Onnx1101-Rt181-Skl0242:
do.bench: '0'
python.version: '3.9'
numpy.version: '>=1.18.1'
numpy.version: '<1.21.0'
onnx.version: '==1.10.1' # 'test'
onnx.target_opset: ''
onnxrt.version: 'onnxruntime==1.8.1' # '-i https://test.pypi.org/simple/ ort-nightly'
sklearn.version: '>=0.24.2'
sklearn.version: '>=0.24.2 lightgbm==3.2.0'
onnxcc.version: '>=1.8.1' # git
run.example: '0'
Py39-Onnx190-Rt180-Skl0242:
do.bench: '0'
python.version: '3.9'
numpy.version: '>=1.18.1'
numpy.version: '<1.21.0'
onnx.version: '==1.9.0'
onnx.target_opset: ''
onnxrt.version: 'onnxruntime>=1.8.1' # '-i https://test.pypi.org/simple/ ort-nightly'
Expand All @@ -56,7 +56,7 @@ jobs:
Py39-Onnx190-Rt170-Skl0242:
do.bench: '0'
python.version: '3.9'
numpy.version: '>=1.18.1'
numpy.version: '<1.21.0'
onnx.version: '==1.9.0'
onnx.target_opset: ''
onnxrt.version: 'onnxruntime==1.7.0' # '-i https://test.pypi.org/simple/ ort-nightly'
Expand All @@ -66,7 +66,7 @@ jobs:
Py38-Onnx181-Rt170-Skl0242:
do.bench: '0'
python.version: '3.8'
numpy.version: '>=1.18.1'
numpy.version: '<1.21.0'
onnx.version: '==1.8.1'
onnx.target_opset: ''
onnxrt.version: 'onnxruntime==1.7.0' # '-i https://test.pypi.org/simple/ ort-nightly'
Expand All @@ -76,7 +76,7 @@ jobs:
Py38-Onnx181-Rt170-Skl0241:
do.bench: '0'
python.version: '3.8'
numpy.version: '>=1.18.1'
numpy.version: '<1.21.0'
onnx.version: '==1.8.1'
onnx.target_opset: ''
onnxrt.version: 'onnxruntime==1.7.0' # '-i https://test.pypi.org/simple/ ort-nightly'
Expand All @@ -86,7 +86,7 @@ jobs:
Py38-Onnx181-Rt160-Skl0240:
do.bench: '0'
python.version: '3.8'
numpy.version: '>=1.18.1'
numpy.version: '<1.21.0'
onnx.version: '==1.8.1'
onnx.target_opset: ''
onnxrt.version: 'onnxruntime==1.6.0'
Expand All @@ -96,7 +96,7 @@ jobs:
Py38-Onnx170-Rt160-Skl0240:
do.bench: '0'
python.version: '3.8'
numpy.version: '>=1.18.1'
numpy.version: '<1.21.0'
onnx.version: '==1.7.0'
onnx.target_opset: ''
onnxrt.version: 'onnxruntime==1.6.0'
Expand All @@ -106,7 +106,7 @@ jobs:
Py37-Onnx170-Rt151-Skl0232:
do.bench: '0'
python.version: '3.7'
numpy.version: '>=1.18.1'
numpy.version: '<1.21.0'
onnx.version: '==1.7.0'
onnx.target_opset: ''
onnxrt.version: 'onnxruntime==1.5.1'
Expand All @@ -116,7 +116,7 @@ jobs:
Py37-Onnx170-Rt140-Skl0232:
do.bench: '0'
python.version: '3.7'
numpy.version: '>=1.18.1'
numpy.version: '<1.21.0'
onnx.version: '==1.7.0'
onnx.target_opset: ''
onnxrt.version: 'onnxruntime==1.4.0' # '-i https://test.pypi.org/simple/ ort-nightly'
Expand All @@ -126,7 +126,7 @@ jobs:
Py37-Onnx170-Rt130-Skl0231:
do.bench: '0'
python.version: '3.7'
numpy.version: '>=1.18.1'
numpy.version: '<1.21.0'
onnx.version: '==1.7.0'
onnx.target_opset: ''
onnxrt.version: 'onnxruntime==1.3.0'
Expand All @@ -136,7 +136,7 @@ jobs:
Py37-Onnx170-Rt120-Skl0230-Op11:
do.bench: '0'
python.version: '3.7'
numpy.version: '>=1.18.1'
numpy.version: '<1.21.0'
onnx.version: '==1.7.0'
onnx.target_opset: '11'
onnxrt.version: 'onnxruntime==1.2.0'
Expand All @@ -146,7 +146,7 @@ jobs:
Py37-Onnx160-Rt120-Skl0230:
do.bench: '0'
python.version: '3.7'
numpy.version: '>=1.18.1'
numpy.version: '<1.21.0'
onnx.version: '==1.6.0'
onnx.target_opset: ''
onnxcc.version: '==1.7.0'
Expand All @@ -156,7 +156,7 @@ jobs:
Py37-Onnx160-Rt111-Skl0222:
do.bench: '0'
python.version: '3.7'
numpy.version: '>=1.18.1'
numpy.version: '<1.21.0'
onnx.version: '==1.6.0'
onnx.target_opset: ''
onnxcc.version: '==1.7.0'
Expand All @@ -166,7 +166,7 @@ jobs:
Py37-Onnx160-Rt100-Skl0213:
do.bench: '0'
python.version: '3.7'
numpy.version: '==1.18.1'
numpy.version: '<1.21.0'
onnx.version: '==1.6.0'
onnx.target_opset: ''
onnxcc.version: '==1.7.0'
Expand Down Expand Up @@ -257,6 +257,8 @@ jobs:
echo "---------------"
pip show numpy
echo "---------------"
pip show scipy
echo "---------------"
pip show pandas
echo "---------------"
pip show onnx
Expand Down
2 changes: 1 addition & 1 deletion skl2onnx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
Main entry point to the converter from the *scikit-learn* to *onnx*.
"""
__version__ = "1.10.0"
__version__ = "1.10.1"
__author__ = "Microsoft"
__producer__ = "skl2onnx"
__producer_version__ = __version__
Expand Down
91 changes: 72 additions & 19 deletions skl2onnx/_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,17 +413,9 @@ def _parse_sklearn_random_trees_embedding(scope, model, inputs,
return res


def _parse_sklearn_classifier(scope, model, inputs, custom_parsers=None):
options = scope.get_options(model, dict(zipmap=True))
no_zipmap = (
(isinstance(options['zipmap'], bool) and not options['zipmap']) or
(model.__class__ in [NuSVC, SVC] and not model.probability))
probability_tensor = _parse_sklearn_simple_model(
scope, model, inputs, custom_parsers=custom_parsers)
if no_zipmap:
return probability_tensor

if options['zipmap'] == 'columns':
def _apply_zipmap(zipmap_options, scope, model, input_type,
probability_tensor):
if zipmap_options == 'columns':
zipmap_operator = scope.declare_local_operator('SklearnZipMapColumns')
classes = get_label_classes(scope, model)
classes_names = get_label_classes(scope, model, node_names=True)
Expand Down Expand Up @@ -456,10 +448,11 @@ def _parse_sklearn_classifier(scope, model, inputs, custom_parsers=None):
label_type = StringTensorType([None])

zip_label = scope.declare_local_variable('output_label', label_type)
zipmap_operator.outputs.append(zip_label)
if len(probability_tensor) == 2:
zipmap_operator.outputs.append(zip_label)

if options['zipmap'] == 'columns':
prob_type = probability_tensor[1].type
if zipmap_options == 'columns':
prob_type = probability_tensor[-1].type
for cl in classes_names:
output_cl = scope.declare_local_variable(cl, prob_type.__class__())
zipmap_operator.outputs.append(output_cl)
Expand All @@ -468,24 +461,84 @@ def _parse_sklearn_classifier(scope, model, inputs, custom_parsers=None):
'output_probability',
SequenceType(
DictionaryType(
label_type, guess_tensor_type(inputs[0].type))))
label_type, guess_tensor_type(input_type))))
zipmap_operator.outputs.append(zip_probability)

zipmap_operator.init_status(is_evaluated=True)
return zipmap_operator.outputs


def _parse_sklearn_classifier(scope, model, inputs, custom_parsers=None):
options = scope.get_options(model, dict(zipmap=True))
no_zipmap = (
(isinstance(options['zipmap'], bool) and not options['zipmap']) or
(model.__class__ in [NuSVC, SVC] and not model.probability))
probability_tensor = _parse_sklearn_simple_model(
scope, model, inputs, custom_parsers=custom_parsers)
if no_zipmap:
return probability_tensor
return _apply_zipmap(
options['zipmap'], scope, model, inputs[0].type, probability_tensor)


def _parse_sklearn_multi_output_classifier(scope, model, inputs,
custom_parsers=None):
alias = _get_sklearn_operator_name(type(model))
this_operator = scope.declare_local_operator(alias, model)
this_operator.inputs = inputs
label = scope.declare_local_variable("label", Int64TensorType())
proba = scope.declare_local_variable(
"probabilities", SequenceType(guess_tensor_type(inputs[0].type)))
guessed_output_type = guess_tensor_type(inputs[0].type)
label_type = Int64TensorType()
label = scope.declare_local_variable("label", label_type)

options = scope.get_options(model, dict(zipmap=True))
no_zipmap = isinstance(options['zipmap'], bool) and not options['zipmap']

if no_zipmap:
proba = scope.declare_local_variable(
"probabilities", SequenceType(guessed_output_type))
this_operator.outputs.append(label)
this_operator.outputs.append(proba)
return this_operator.outputs

warnings.warn(
"The current converter for class %r "
"creates a sequence of maps as an output."
"This is not allowed in standards ONNX specifications."
"" % model.__class__.__name__,
RuntimeWarning)

this_operator.outputs.append(label)
proba = scope.declare_local_variable(
"output_probabilities", SequenceType(guessed_output_type))
this_operator.outputs.append(proba)
return this_operator.outputs

zipmap = options.get('zipmap', False)
if zipmap == 'columns':
raise RuntimeError(
"Unable to convert model %r with option zipmap=%r." % (
model.__class__.__name__, zipmap))

# zipmap is True
zipped = []
for i in range(len(model.estimators_)):
output_name = scope.declare_local_variable(
"multi_output_%d" % i, guessed_output_type)
sequence_at = scope.declare_local_operator('SklearnSequenceAt')
sequence_at.inputs.append(proba)
sequence_at.outputs.append(output_name)
sequence_at.index = i
zipped.extend(
_apply_zipmap(
zipmap, scope, model.estimators_[i],
guessed_output_type, sequence_at.outputs))

sequence_build = scope.declare_local_operator('SklearnSequenceConstruct')
sequence_build.inputs.extend(zipped)
proba_zipped = scope.declare_local_variable(
"probabilities",
SequenceType(DictionaryType(label_type, guessed_output_type)))
sequence_build.outputs.append(proba_zipped)
return sequence_build.outputs


def _parse_sklearn_gaussian_process(scope, model, inputs, custom_parsers=None):
Expand Down
2 changes: 2 additions & 0 deletions skl2onnx/operator_converters/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
from . import ransac_regressor
from . import replace_op
from . import scaler_op
from . import sequence
from . import sgd_classifier
from . import stacking
from . import support_vector_machines
Expand Down Expand Up @@ -108,6 +109,7 @@
ransac_regressor,
replace_op,
scaler_op,
sequence,
sgd_classifier,
stacking,
support_vector_machines,
Expand Down
6 changes: 5 additions & 1 deletion skl2onnx/operator_converters/calibrated_classifier_cv.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
guess_numpy_type, Int64TensorType, guess_proto_type)
from ..common._registration import register_converter
from .._supported_operators import sklearn_operator_name_map
from sklearn.ensemble import RandomForestClassifier


def _handle_zeros(scope, container, concatenated_prob_name,
Expand Down Expand Up @@ -256,6 +257,8 @@ def convert_calibrated_classifier_base_estimator(scope, operator, container,
# | |
# V |
# class_prob_tensor [M, C] <--'
model_proba = {RandomForestClassifier}

if scope.get_options(operator.raw_operator, dict(nocl=False))['nocl']:
raise RuntimeError(
"Option 'nocl' is not implemented for operator '{}'.".format(
Expand All @@ -275,7 +278,8 @@ def convert_calibrated_classifier_base_estimator(scope, operator, container,
prob_name = [None] * n_classes

this_operator = scope.declare_local_operator(op_type, base_model)
if container.has_options(base_model, 'raw_scores'):
if (container.has_options(base_model, 'raw_scores') and
not type(base_model) in model_proba):
container.add_options(id(base_model), {'raw_scores': True})
scope.add_options(id(base_model), {'raw_scores': True})
this_operator.inputs = operator.inputs
Expand Down
10 changes: 5 additions & 5 deletions skl2onnx/operator_converters/multioutput.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,12 @@ def convert_multi_output_classifier_converter(
op_version=op_version)
for y in y_list]

label = OnnxConcat(*label_list, axis=1, op_version=op_version,
output_names=[operator.outputs[0]])
label.add_to(scope=scope, container=container)

# probabilities
proba_list = [OnnxIdentity(y[1], op_version=op_version)
for y in y_list]
label = OnnxConcat(*label_list, axis=1, op_version=op_version,
output_names=[operator.outputs[0]])
label.add_to(scope=scope, container=container)

proba = OnnxSequenceConstruct(
*proba_list, op_version=op_version,
Expand All @@ -79,4 +78,5 @@ def convert_multi_output_classifier_converter(
convert_multi_output_regressor_converter)
register_converter('SklearnMultiOutputClassifier',
convert_multi_output_classifier_converter,
options={'nocl': [False, True]})
options={'nocl': [False, True],
'zipmap': [False, True]})
2 changes: 1 addition & 1 deletion skl2onnx/operator_converters/random_forest.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def convert_sklearn_random_forest_classifier(
elif use_raw_scores:
raise RuntimeError(
"The converter cannot implement decision_function for "
"'{}'.".format(type(op)))
"'{}' and loss '{}'.".format(type(op), loss))

input_name = operator.input_full_names
if type(operator.inputs[0].type) == BooleanTensorType:
Expand Down
31 changes: 31 additions & 0 deletions skl2onnx/operator_converters/sequence.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# SPDX-License-Identifier: Apache-2.0

from ..proto import onnx_proto
from ..common._registration import register_converter
from ..common._topology import Scope, Operator
from ..common._container import ModelComponentContainer


def convert_sklearn_sequence_at(scope: Scope, operator: Operator,
container: ModelComponentContainer):
i_index = operator.index
index_name = scope.get_unique_variable_name("seq_at%d" % i_index)
container.add_initializer(
index_name, onnx_proto.TensorProto.INT64, [], [i_index])
container.add_node(
'SequenceAt', [operator.inputs[0].full_name, index_name],
operator.outputs[0].full_name,
name=scope.get_unique_operator_name('SequenceAt%d' % i_index))


def convert_sklearn_sequence_construct(scope: Scope, operator: Operator,
container: ModelComponentContainer):
container.add_node(
'SequenceConstruct', [i.full_name for i in operator.inputs],
operator.outputs[0].full_name,
name=scope.get_unique_operator_name('SequenceConstruct'))


register_converter('SklearnSequenceAt', convert_sklearn_sequence_at)
register_converter(
'SklearnSequenceConstruct', convert_sklearn_sequence_construct)
Loading

0 comments on commit 4977b9e

Please sign in to comment.