TreeEnsembleClassifier (and other scikit pckages) not supported

Hi there, I’m building a model using scikit-learn, and converting it to ONXX with skl2onnx. I’m running into several “not supported” errors when importing into Unity, related to the following packages. Are there alternatives? Is scikit not well supported?

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression, RidgeClassifier
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier

Thanks!

Hi @talespinvr, are you able to list the “not supported” errors? Also, are you able to provide some example ONNX files (and also the python code if you don’t mind sharing?) We have done some work on random forest layers recently so we may be able to help.

Hi @PaulBUnity! See attached image. I’m happy to share the project but cannot upload its files here.
Where should I send them? The project is just an extension of this example, using skl2onnx to convert the trained model to onxx.

Errors are:

Scaler not supported
UnityEngine.Debug:LogError (object)
Unity.Sentis.D:LogError (object) (at ./Library/PackageCache/com.unity.sentis/Runtime/Core/Internals/Debug.cs:131)
Unity.Sentis.ONNX.ONNXModelConverter:ConvertOnnxModel (Onnx.ModelProto) (at ./Library/PackageCache/com.unity.sentis/Runtime/ONNX/ONNXModelConverter.cs:1282)
Unity.Sentis.ONNX.ONNXModelConverter:Convert () (at ./Library/PackageCache/com.unity.sentis/Runtime/ONNX/ONNXModelConverter.cs:156)
Unity.Sentis.ONNXModelImporter:OnImportAsset (UnityEditor.AssetImporters.AssetImportContext) (at ./Library/PackageCache/com.unity.sentis/Editor/ONNXModelImporter.cs:38)
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&) (at /Users/bokken/build/output/unity/unity/Modules/IMGUI/GUIUtility.cs:206)
TreeEnsembleClassifier not supported
UnityEngine.Debug:LogError (object)
Unity.Sentis.D:LogError (object) (at ./Library/PackageCache/com.unity.sentis/Runtime/Core/Internals/Debug.cs:131)
Unity.Sentis.ONNX.ONNXModelConverter:ConvertOnnxModel (Onnx.ModelProto) (at ./Library/PackageCache/com.unity.sentis/Runtime/ONNX/ONNXModelConverter.cs:1282)
Unity.Sentis.ONNX.ONNXModelConverter:Convert () (at ./Library/PackageCache/com.unity.sentis/Runtime/ONNX/ONNXModelConverter.cs:156)
Unity.Sentis.ONNXModelImporter:OnImportAsset (UnityEditor.AssetImporters.AssetImportContext) (at ./Library/PackageCache/com.unity.sentis/Editor/ONNXModelImporter.cs:38)
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&) (at /Users/bokken/build/output/unity/unity/Modules/IMGUI/GUIUtility.cs:206)
ZipMap not supported
UnityEngine.Debug:LogError (object)
Unity.Sentis.D:LogError (object) (at ./Library/PackageCache/com.unity.sentis/Runtime/Core/Internals/Debug.cs:131)
Unity.Sentis.ONNX.ONNXModelConverter:ConvertOnnxModel (Onnx.ModelProto) (at ./Library/PackageCache/com.unity.sentis/Runtime/ONNX/ONNXModelConverter.cs:1282)
Unity.Sentis.ONNX.ONNXModelConverter:Convert () (at ./Library/PackageCache/com.unity.sentis/Runtime/ONNX/ONNXModelConverter.cs:156)
Unity.Sentis.ONNXModelImporter:OnImportAsset (UnityEditor.AssetImporters.AssetImportContext) (at ./Library/PackageCache/com.unity.sentis/Editor/ONNXModelImporter.cs:38)
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&) (at /Users/bokken/build/output/unity/unity/Modules/IMGUI/GUIUtility.cs:206)

Hi, thanks yes we have recently done custom layer implementations of TreeEnsembleClassifier and Scaler. (ZipMap is not supported but there is a setting in the python export to get rid of that). Thanks for sending the files, I’ll check these out
to make sure they work and see if I can put those custom layers on github .

1 Like

OK, I can bet around ZipMap and even Scaler. Once available, I have no idea how I would integrate a custom TreeEnsembleClassifier , so would appreciate some advice once it is. Thanks!

We’ll either support that op or do a sample showing how to integrate it

Great! Meantime, are there any supported alternatives for Scaler and TreeEnsembleClassifier you’d recommend for scikit - so I can keep working on the model integration?

Also, I’m thinking of moving over to Tensor Flow, which I assume would be preferred/recommended?

checkout
~Samples\Add a custom layer
replace Scaler with our layer called ScaleBias it does the same thing.
I’m sure you can do the same with TreeEnsembleClassifier
it’s just doing a post_transform which you can do with our Softmax layer and then selecting a class based on the maxvalue which you can get via ArgMax :slight_smile:

Sorry I’m new here. Where is “~Samples\Add a custom layer” and how would I integrate it into my project?


Window > PackageManager

Got it thanks. The model I’ve trained literally only uses StandardScaler and RandomForestClassifier. Am I to remove both of these somehow and add custom layers, or is there a way to replace layers in an existing model?

Update: I assume something like this for Scaler:

[OpImport("Scaler")]
public class ScalerOp : IOpImporter
{
    public void Import(Model model, OperatorNode node)
    {
        // Setup default value of 0 if attribute not present.
        var threshold = "";
        var scale = "";

        // Check for attribute and retrieve it from OperatorNode.
        if (node.HasAttribute("threshold"))
            threshold = node.GetStringAttribute("threshold");

        if (node.HasAttribute("scale"))
            scale = node.GetStringAttribute("scale");

        // Add custom layer to model with node name (output), node inputs and attributes.
        //model.AddLayer(new Binarizer(node.Name, node.Inputs[0], threshold));
        model.AddLayer(new ScaleBias(node.Name, node.Inputs[0], scale: scale, bias: threshold));

        // Note: we could alternatively implement this operator entirely with existing Layers as follows
        // model.AddConstant(new Constant("threshold", new TensorFloat(new TensorShape(), new[] { threshold })));
        // model.AddLayer(new Greater(node.Name, node.Inputs[0], "threshold"));
    }
}

and for RandomForestClassifier, something like above with:

model.AddLayer(new Softmax(node.Name, node.Inputs[0]));
model.AddLayer(new ArgMax(node.Name, node.Inputs[0], 1));

not sure, would need to dig more into what TreeEnsembleClassifier does exactly, it has a lot of options.
https://onnx.ai/onnx/operators/onnx_aionnxml_TreeEnsembleClassifier.html

you need to create a custom layer which handles the options and calls backend.Argmax then fetches the according class in the dict

https://onnx.ai/onnx/operators/onnx_aionnxml_Scaler.html

Seems that it’s not quite a scale bias since there isn’t any broadcast rule.
So if your inputs are of length one that is ScalarBias if not Mul then Sub to get the vector ops

1 Like

Hello, the project we are currently working on also needs to use a model that utilizes the TreeEnsembleClassifier. Is the custom layer implementation of it is ready? Is it available for download? Thank you very much!