Skip to content

Commit 4dad29e

Browse files
authored
Upgrade max supported opset version (#1098)
* upgrade version Signed-off-by: Xavier Dupre <[email protected]> * requirements Signed-off-by: Xavier Dupre <[email protected]> * fix ohe Signed-off-by: Xavier Dupre <[email protected]> * better message Signed-off-by: Xavier Dupre <[email protected]> * documentation Signed-off-by: Xavier Dupre <[email protected]> * fix missing dependency Signed-off-by: Xavier Dupre <[email protected]> --------- Signed-off-by: Xavier Dupre <[email protected]>
1 parent c4a9de3 commit 4dad29e

15 files changed

+42
-204
lines changed

CHANGELOGS.md

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
## 1.17.0 (development)
44

5+
* Upgrade the maximum supported opset to 21,
6+
update requirements to scikit-learn>=1.1,
7+
older versions are not tested anymore,
8+
[#1098](https://github.com/onnx/sklearn-onnx/pull/1098)
9+
* Support infrequent categories for OneHotEncoder
10+
[#1029](https://github.com/onnx/sklearn-onnx/pull/1029)
511
* Support kernel Matern in Gaussian Process
612
[#978](https://github.com/onnx/sklearn-onnx/pull/978)
713
* Fix for multidimensional gaussian process

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ including models or transformers coming from external libraries.
1818
## Documentation
1919
Full documentation including tutorials is available at [https://onnx.ai/sklearn-onnx/](https://onnx.ai/sklearn-onnx/).
2020
[Supported scikit-learn Models](https://onnx.ai/sklearn-onnx/supported.html)
21-
Last supported opset is 19.
21+
Last supported opset is 21.
2222

2323
You may also find answers in [existing issues](https://github.com/onnx/sklearn-onnx/issues?utf8=%E2%9C%93&q=is%3Aissue)
2424
or submit a new one.

docs/api_summary.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,6 @@ Topology
124124
--------
125125

126126
.. autoclass:: skl2onnx.common._topology.Topology
127-
:members: compile, topological_operator_iterator
127+
:members:
128128

129129
.. autofunction:: skl2onnx.common._topology.convert_topology

docs/exts/sphinx_skl2onnx_extension.py

+13
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,19 @@ def make_ref(name):
174174

175175
rows.append("")
176176
for name in sorted_keys:
177+
if name in {
178+
"OnnxDecorrelateTransformer",
179+
"OnnxGrowthCalculator",
180+
"OnnxPredictableTSNE",
181+
"OnnxSklearnLGBMClassifier",
182+
"OnnxSklearnLGBMRegressor",
183+
"OnnxSklearnXGBClassifier",
184+
"OnnxSklearnXGBRegressor",
185+
"OnnxSklearnPipeline",
186+
"OnnxSklearnColumnTransformer",
187+
"OnnxSklearnFeatureUnion",
188+
}:
189+
continue
177190
rows = []
178191
cl = cls[name]
179192
rows.append(".. _l-sklops-{}:".format(cl.__name__))

requirements-dev.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# tests
22
black
3+
jinja2
34
onnxruntime-extensions
45
onnxscript
56
pandas

requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
onnx>=1.2.1
2-
scikit-learn>=0.19
2+
scikit-learn>=1.1
33
onnxconverter-common>=1.7.0

skl2onnx/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
__producer_version__ = __version__
1010
__domain__ = "ai.onnx"
1111
__model_version__ = 0
12-
__max_supported_opset__ = 19 # Converters are tested up to this version.
12+
__max_supported_opset__ = 21 # Converters are tested up to this version.
1313

1414

1515
from .convert import convert_sklearn, to_onnx, wrap_as_onnx_mixin # noqa

skl2onnx/algebra/_cache/__init__.py

-6
This file was deleted.

skl2onnx/algebra/automation.py

-149
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import textwrap
44
import onnx
55
import onnx.defs # noqa
6-
from onnx.defs import OpSchema
76

87

98
def _get_doc_template():
@@ -115,154 +114,6 @@ def get_domain_list():
115114
)
116115

117116

118-
def get_rst_doc(op_name=None):
119-
"""
120-
Returns a documentation in RST format
121-
for all :class:`OnnxOperator`.
122-
123-
:param op_name: operator name of None for all
124-
:return: string
125-
126-
The function relies on module *jinja2* or replaces it
127-
with a simple rendering if not present.
128-
"""
129-
if op_name is None:
130-
schemas = onnx.defs.get_all_schemas_with_history()
131-
elif isinstance(op_name, str):
132-
schemas = [
133-
schema
134-
for schema in onnx.defs.get_all_schemas_with_history()
135-
if schema.name == op_name
136-
]
137-
if len(schemas) > 1:
138-
raise RuntimeError(
139-
"Multiple operators have the same name '{}'.".format(op_name)
140-
)
141-
elif not isinstance(op_name, list):
142-
schemas = [op_name]
143-
if len(schemas) == 0:
144-
raise ValueError("Unable to find any operator with name '{}'.".format(op_name))
145-
146-
# from onnx.backend.sample.ops import collect_sample_implementations
147-
# from onnx.backend.test.case import collect_snippets
148-
# SNIPPETS = collect_snippets()
149-
# SAMPLE_IMPLEMENTATIONS = collect_sample_implementations()
150-
def format_name_with_domain(sch):
151-
if sch.domain:
152-
return "{} ({})".format(sch.name, sch.domain)
153-
return sch.name
154-
155-
def get_is_homogeneous(obj):
156-
try:
157-
return obj.is_homogeneous
158-
except AttributeError:
159-
try:
160-
return obj.isHomogeneous
161-
except AttributeError:
162-
return False
163-
164-
def format_option(obj):
165-
opts = []
166-
if OpSchema.FormalParameterOption.Optional == obj.option:
167-
opts.append("optional")
168-
elif OpSchema.FormalParameterOption.Variadic == obj.option:
169-
opts.append("variadic")
170-
if get_is_homogeneous(obj):
171-
opts.append("heterogeneous")
172-
if opts:
173-
return " (%s)" % ", ".join(opts)
174-
return ""
175-
176-
def getconstraint(const, ii):
177-
if const.type_param_str:
178-
name = const.type_param_str
179-
else:
180-
name = str(ii)
181-
if const.allowed_type_strs:
182-
name += " " + ", ".join(const.allowed_type_strs)
183-
return name
184-
185-
def getname(obj, i):
186-
name = obj.name
187-
if len(name) == 0:
188-
return str(i)
189-
return name
190-
191-
def process_documentation(doc):
192-
if doc is None:
193-
doc = ""
194-
doc = textwrap.dedent(doc)
195-
main_docs_url = "https://github.com/onnx/onnx/blob/main/"
196-
rep = {
197-
"[the doc](IR.md)": "`ONNX <{0}docs/IR.md>`_",
198-
"[the doc](Broadcasting.md)": (
199-
"`Broadcasting in ONNX <{0}docs/Broadcasting.md>`_"
200-
),
201-
"<dl>": "",
202-
"</dl>": "",
203-
"<dt>": "* ",
204-
"<dd>": " ",
205-
"</dt>": "",
206-
"</dd>": "",
207-
"<tt>": "``",
208-
"</tt>": "``",
209-
"<br>": "\n",
210-
}
211-
for k, v in rep.items():
212-
doc = doc.replace(k, v.format(main_docs_url))
213-
move = 0
214-
lines = []
215-
for line in doc.split("\n"):
216-
if line.startswith("```"):
217-
if move > 0:
218-
move -= 4
219-
lines.append("\n")
220-
else:
221-
lines.append("::\n")
222-
move += 4
223-
elif move > 0:
224-
lines.append(" " * move + line)
225-
else:
226-
lines.append(line)
227-
return "\n".join(lines)
228-
229-
def build_doc_url(sch):
230-
doc_url = "https://github.com/onnx/onnx/blob/main/docs/Operators"
231-
if "ml" in sch.domain:
232-
doc_url += "-ml"
233-
doc_url += ".md"
234-
doc_url += "#"
235-
if sch.domain not in (None, "", "ai.onnx"):
236-
doc_url += sch.domain + "."
237-
return doc_url
238-
239-
def get_type_str(inou):
240-
try:
241-
return inou.type_str
242-
except AttributeError:
243-
return inou.typeStr
244-
245-
fnwd = format_name_with_domain
246-
tmpl = _template_operator
247-
docs = tmpl.render(
248-
schemas=schemas,
249-
OpSchema=OpSchema,
250-
len=len,
251-
getattr=getattr,
252-
sorted=sorted,
253-
format_option=format_option,
254-
getconstraint=getconstraint,
255-
getname=getname,
256-
enumerate=enumerate,
257-
format_name_with_domain=fnwd,
258-
process_documentation=process_documentation,
259-
build_doc_url=build_doc_url,
260-
str=str,
261-
get_type_str=get_type_str,
262-
)
263-
return docs
264-
265-
266117
def _get_doc_template_sklearn():
267118
try:
268119
from jinja2 import Template

skl2onnx/algebra/onnx_ops.py

+2-20
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
Place holder for all ONNX operators.
55
"""
66
import sys
7-
import os
87
import numpy as np
98

109
try:
@@ -14,8 +13,6 @@
1413
import onnx
1514
from ..common.data_types import DataType
1615
from ..common._topology import Variable
17-
from .automation import get_rst_doc
18-
from ._cache import cache_folder
1916

2017

2118
def ClassFactory(
@@ -169,7 +166,6 @@ def dynamic_class_creation(cache=False):
169166
<https://github.com/onnx/onnx/blob/main/docs/
170167
Operators-ml.md>`_.
171168
"""
172-
cache_dir = cache_folder()
173169
res = {}
174170
for schema in onnx.defs.get_all_schemas_with_history():
175171
if schema.support_level == schema.SupportType.EXPERIMENTAL:
@@ -199,22 +195,8 @@ def _c(obj, label, i):
199195
outputs = [_c(o, "O", i) for i, o in enumerate(schema.outputs)]
200196
args = [p for p in schema.attributes]
201197

202-
if "_" in name:
203-
class_name = "Onnx" + name
204-
else:
205-
class_name = "Onnx" + schema.name
206-
207-
filename = os.path.join(
208-
cache_dir, schema.name + "_" + str(schema.since_version) + ".rst"
209-
)
210-
if not cache and os.path.exists(filename):
211-
with open(filename, "r", encoding="utf-8") as f:
212-
doc = f.read()
213-
else:
214-
doc = get_rst_doc(schema)
215-
if cache:
216-
with open(filename, "w", encoding="utf-8") as f:
217-
f.write(doc)
198+
class_name = "Onnx" + (name if "_" in name else schema.name)
199+
doc = f"See `{name} <https://onnx.ai/onnx/operators/onnx__{name}.html>`_."
218200

219201
cl = ClassFactory(
220202
class_name,

skl2onnx/common/_topology.py

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ def _default_OPSET_TO_IR_VERSION():
6363
18: 8,
6464
19: 9,
6565
20: 9,
66+
21: 10,
6667
}
6768

6869

skl2onnx/operator_converters/one_hot_encoder.py

-7
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,6 @@ def convert_sklearn_one_hot_encoder(
4545

4646
enum_cats = []
4747
index_inputs = 0
48-
to_drop = ohe_op._drop_idx_after_grouping
49-
if to_drop is not None:
50-
# raise NotImplementedError(
51-
# f"The converter is not implemented when "
52-
# f"_drop_idx_after_grouping is not None: {to_drop}."
53-
# )
54-
pass
5548

5649
for index, cats in enumerate(ohe_op.categories_):
5750
filtered_cats = ohe_op._compute_transformed_categories(index)

tests/test_algebra_onnx_doc.py

+6-17
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from numpy.testing import assert_almost_equal
77
import onnx
88
from skl2onnx.algebra.onnx_ops import dynamic_class_creation
9-
from skl2onnx.algebra.automation import get_rst_doc_sklearn, get_rst_doc
9+
from skl2onnx.algebra.automation import get_rst_doc_sklearn
1010
from test_utils import TARGET_OPSET
1111

1212

@@ -43,27 +43,16 @@ def test_transpose2(self):
4343
res = self.predict_with_onnxruntime(model_def, X)
4444
assert_almost_equal(res["Y"], X)
4545

46-
@unittest.skipIf(
47-
sys.platform.startswith("win"), reason="onnx schema are incorrect on Windows"
48-
)
49-
@unittest.skipIf(TARGET_OPSET <= 20, reason="not available")
50-
def test_doc_onnx(self):
51-
rst = get_rst_doc()
52-
assert "**Summary**" in rst
53-
5446
@unittest.skipIf(
5547
sys.platform.startswith("win"), reason="onnx schema are incorrect on Windows"
5648
)
5749
@unittest.skipIf(TARGET_OPSET <= 20, reason="not available")
5850
def test_doc_sklearn(self):
59-
try:
60-
rst = get_rst_doc_sklearn()
61-
assert ".. _l-sklops-OnnxSklearnBernoulliNB:" in rst
62-
except KeyError as e:
63-
assert "SklearnGaussianProcessRegressor" in str(
64-
e
65-
) or "SklearnGaussianProcessClassifier" in str(e)
51+
rst = get_rst_doc_sklearn()
52+
assert (
53+
".. _l-sklops-OnnxSklearnBernoulliNB:" in rst
54+
), f"Unable to find a substring in {rst}"
6655

6756

6857
if __name__ == "__main__":
69-
unittest.main()
58+
unittest.main(verbosity=2)

tests/test_sklearn_one_hot_encoder_converter.py

+1
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,7 @@ def test_shape_inference_onnx(self):
472472
def test_shape_inference_onnxruntime(self):
473473
self._shape_inference("onnxruntime")
474474

475+
@unittest.skipIf(not skl12(), reason="sparse output not available")
475476
def test_min_frequency(self):
476477
data = pandas.DataFrame(
477478
[

tests/test_utils/__init__.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ def create_tensor(N, C, H=None, W=None):
6060

6161

6262
def _get_ir_version(opv):
63+
if opv >= 21:
64+
return 10
6365
if opv >= 19:
6466
return 9
6567
if opv >= 15:
@@ -83,7 +85,11 @@ def max_onnxruntime_opset():
8385
<https://github.com/microsoft/onnxruntime/blob/main/docs/Versioning.md>`_.
8486
"""
8587
vi = pv.Version(ort_version.split("+")[0])
86-
if vi >= pv.Version("1.16.0"):
88+
if vi >= pv.Version("1.18.0"):
89+
return 21
90+
if vi >= pv.Version("1.17.0"):
91+
return 20
92+
if vi >= pv.Version("1.15.0"):
8793
return 19
8894
if vi >= pv.Version("1.14.0"):
8995
return 18
@@ -120,6 +126,7 @@ def max_onnxruntime_opset():
120126
)
121127
)
122128

129+
# opset-ml == 4 still not implemented in onnxruntime
123130
value_ml = 3
124131
if TARGET_OPSET <= 16:
125132
# TreeEnsemble* for opset-ml == 3 is implemented in onnxruntime==1.12.0

0 commit comments

Comments
 (0)