sklearn-onnx icon indicating copy to clipboard operation
sklearn-onnx copied to clipboard

ValueError: Unable to create node 'LabelEncoder' with name='LabelEncoder3' and attributes={'keys_floats': array([False, True]), 'values_int64s': array([0, 1])}.

Open TopCoder2K opened this issue 1 year ago • 24 comments

Hi there!

I'm trying to convert the sklearn's Pipeline to the ONNX format, but I get a strange error. The Pipeline is the following:

        preprocessor = ColumnTransformer(
            transformers=[
                ("cat", OrdinalEncoder(dtype=np.int64), categorical_features),
                ("num", "passthrough", numerical_features),
            ],
            sparse_threshold=1,
            verbose_feature_names_out=False,
        ).set_output(transform="pandas")
        model = make_pipeline(
            self.preprocessor, RandomForestRegressor(**cfg.model.hyperparams)
        )

The dataset is obtained via fetch_openml("Bike_Sharing_Demand", version=2, as_frame=True, parser="pandas") and little preprocessing (e.g. the "heavy_rain" category is merged with the "rain" category). The result of print(X_train.iloc[:1]) is

   season  month  hour  holiday  weekday  workingday weather  temp  feel_temp  humidity  windspeed
0  spring      1     0    False        6       False   clear  9.84     14.395      0.81        0.0

When I run model_onnx = to_onnx(model, X=X_train.iloc[:1], verbose=1), I get an error in the title. The type guessing seems to work fine:

[to_onnx] initial_types=[('season', StringTensorType(shape=[None, 1])), ('month', Int64TensorType(shape=[None, 1])), ('hour', Int64TensorType(shape=[None, 1])), ('holiday', BooleanTensorType(shape=[None, 1])), ('weekday', Int64TensorType(shape=[None, 1])), ('workingday', BooleanTensorType(shape=[None, 1])), ('weather', StringTensorType(shape=[None, 1])), ('temp', DoubleTensorType(shape=[None, 1])), ('feel_temp', DoubleTensorType(shape=[None, 1])), ('humidity', DoubleTensorType(shape=[None, 1])), ('windspeed', DoubleTensorType(shape=[None, 1]))]

The remaining part of the output is:

[convert_sklearn] parse_sklearn_model
[convert_sklearn] convert_topology
[convert_operators] begin
[convert_operators] iteration 1 - n_vars=0 n_ops=5
[call_converter] call converter for 'SklearnConcat'.
[call_converter] call converter for 'SklearnOrdinalEncoder'.
Traceback (most recent call last):
  File "/home/topcoder2k/.cache/pypoetry/virtualenvs/mlopscourse-4vHWhyzM-py3.9/lib/python3.9/site-packages/skl2onnx/common/_container.py", line 707, in add_node
    node = make_node(op_type, inputs, outputs, name=name, **new_attrs)
  File "/home/topcoder2k/.cache/pypoetry/virtualenvs/mlopscourse-4vHWhyzM-py3.9/lib/python3.9/site-packages/onnx/helper.py", line 164, in make_node
    node.attribute.extend(
  File "/home/topcoder2k/.cache/pypoetry/virtualenvs/mlopscourse-4vHWhyzM-py3.9/lib/python3.9/site-packages/onnx/helper.py", line 165, in <genexpr>
    make_attribute(key, value)
  File "/home/topcoder2k/.cache/pypoetry/virtualenvs/mlopscourse-4vHWhyzM-py3.9/lib/python3.9/site-packages/onnx/helper.py", line 894, in make_attribute
    raise ValueError(
ValueError: Could not infer the attribute type from the elements of the passed Iterable value.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/topcoder2k/CodeProjects/MLOps/mlops-course/commands.py", line 59, in <module>
    fire.Fire()
  File "/home/topcoder2k/.cache/pypoetry/virtualenvs/mlopscourse-4vHWhyzM-py3.9/lib/python3.9/site-packages/fire/core.py", line 141, in Fire
    component_trace = _Fire(component, args, parsed_flag_args, context, name)
  File "/home/topcoder2k/.cache/pypoetry/virtualenvs/mlopscourse-4vHWhyzM-py3.9/lib/python3.9/site-packages/fire/core.py", line 475, in _Fire
    component, remaining_args = _CallAndUpdateTrace(
  File "/home/topcoder2k/.cache/pypoetry/virtualenvs/mlopscourse-4vHWhyzM-py3.9/lib/python3.9/site-packages/fire/core.py", line 691, in _CallAndUpdateTrace
    component = fn(*varargs, **kwargs)
  File "/home/topcoder2k/CodeProjects/MLOps/mlops-course/commands.py", line 30, in train
    Trainer(config_name, **kwargs).train()
  File "/home/topcoder2k/CodeProjects/MLOps/mlops-course/mlopscourse/train.py", line 69, in train
    model_onnx = to_onnx(model.model, X=X_train.iloc[:1], verbose=1)
  File "/home/topcoder2k/.cache/pypoetry/virtualenvs/mlopscourse-4vHWhyzM-py3.9/lib/python3.9/site-packages/skl2onnx/convert.py", line 306, in to_onnx
    return convert_sklearn(
  File "/home/topcoder2k/.cache/pypoetry/virtualenvs/mlopscourse-4vHWhyzM-py3.9/lib/python3.9/site-packages/skl2onnx/convert.py", line 208, in convert_sklearn
    onnx_model = convert_topology(
  File "/home/topcoder2k/.cache/pypoetry/virtualenvs/mlopscourse-4vHWhyzM-py3.9/lib/python3.9/site-packages/skl2onnx/common/_topology.py", line 1532, in convert_topology
    topology.convert_operators(container=container, verbose=verbose)
  File "/home/topcoder2k/.cache/pypoetry/virtualenvs/mlopscourse-4vHWhyzM-py3.9/lib/python3.9/site-packages/skl2onnx/common/_topology.py", line 1349, in convert_operators
    self.call_converter(operator, container, verbose=verbose)
  File "/home/topcoder2k/.cache/pypoetry/virtualenvs/mlopscourse-4vHWhyzM-py3.9/lib/python3.9/site-packages/skl2onnx/common/_topology.py", line 1132, in call_converter
    conv(self.scopes[0], operator, container)
  File "/home/topcoder2k/.cache/pypoetry/virtualenvs/mlopscourse-4vHWhyzM-py3.9/lib/python3.9/site-packages/skl2onnx/common/_registration.py", line 27, in __call__
    return self._fct(*args)
  File "/home/topcoder2k/.cache/pypoetry/virtualenvs/mlopscourse-4vHWhyzM-py3.9/lib/python3.9/site-packages/skl2onnx/operator_converters/ordinal_encoder.py", line 89, in convert_sklearn_ordinal_encoder
    container.add_node(
  File "/home/topcoder2k/.cache/pypoetry/virtualenvs/mlopscourse-4vHWhyzM-py3.9/lib/python3.9/site-packages/skl2onnx/common/_container.py", line 709, in add_node
    raise ValueError(
ValueError: Unable to create node 'LabelEncoder' with name='LabelEncoder3' and attributes={'keys_floats': array([False,  True]), 'values_int64s': array([0, 1])}.

The skl2onnx version from the poetry.lock is:

[[package]]
name = "skl2onnx"
version = "1.15.0"
description = "Convert scikit-learn models to ONNX"
optional = false
python-versions = "*"
files = [
    {file = "skl2onnx-1.15.0-py2.py3-none-any.whl", hash = "sha256:13a9ea5d50619ce42381c67001db8c87ce574a459a8f0738b45d2f4b93f465f6"},
    {file = "skl2onnx-1.15.0.tar.gz", hash = "sha256:05b2c2643ad0357ec1ea684d138438a2df657df828e57d07cb78c2e76be20e37"},
]

UPD:

I've also decided to leave here the python and scikit-learn versions:

python --- 3.9.13
scikit-learn --- 1.3.1

TopCoder2K avatar Dec 03 '23 08:12 TopCoder2K