Search code examples
pythonmachine-learningscikit-learncoreml

How to convert a Sci-kit pipeline containing a custom function so it can be used by iOS device? (if possible using .mlmodel and CoreML))


I would like to use the pipeline described bellow on iOS device. It is not possible to just convert it using CoreML because my pipeline contains a custom function that is not in sklearn.preprocessing.

I have a pipeline which contains a function that is not supported by CoreML. If I try to convert my pipeline using coreML, I have:

ValueError: Transformer '<class '__main__.Prepare_input'>' not supported; supported transformers are coremltools.converters.sklearn._dict_vectorizer,coremltools.converters.sklearn._one_hot_encoder,coremltools.converters.sklearn._normalizer,coremltools.converters.sklearn._standard_scaler,coremltools.converters.sklearn._imputer,coremltools.converters.sklearn._NuSVC,coremltools.converters.sklearn._NuSVR,coremltools.converters.sklearn._SVC,coremltools.converters.sklearn._SVR,coremltools.converters.sklearn._linear_regression,coremltools.converters.sklearn._LinearSVC,coremltools.converters.sklearn._LinearSVR,coremltools.converters.sklearn._logistic_regression,coremltools.converters.sklearn._random_forest_classifier,coremltools.converters.sklearn._random_forest_regressor,coremltools.converters.sklearn._decision_tree_classifier,coremltools.converters.sklearn._decision_tree_regressor,coremltools.converters.sklearn._gradient_boosting_classifier,coremltools.converters.sklearn._gradient_boosting_regressor.

I have my custom function here:

class Prepare_input(BaseEstimator):
    def __init__(self, *args, **kwargs):
        return super().__init__(*args, **kwargs)

    def fit(self, x, y=None):
        return self

    def transform(self, X, y=None):
        x= self.extract_features(x)
        return x

    def extract_features(signal):
        print("transforming...")
        signal = some_modif(signal)
        return signal

I use it to create a pipeline here:

classifier1= RandomForestClassifier(max_depth=700, n_estimators=100, random_state = 42)
pipeline1 = Pipeline([('Prepare_input', input_transform), ('classifier', classifier1)])

Then I fit and convert:

pipeline1.fit(train_data, train_labels)

coreml_model = coremltools.converters.sklearn.convert(pipeline1)
coreml_model.save('PPG_classif.mlmodel')

... And I have the error above.

  • Do you have any idea of how I can use my pipeline on iOS?
  • How to write a custom converter in CoreML? Do you have any example in mind that I could use?
  • Do you know if some tools than CoreML could support this type of conversion?

Thank you very much!


Solution

  • It doesn't appear that the coremltools scikit-learn converter knows how to handle custom functions. They are only supported inside neural network models.

    Since your custom function is applied before the classifier, you could just implement this in Swift or Obj-C and then call the Core ML model to do the classification.

    It's also possible to add the custom function by hand into the Core ML model (either by adding a neural network model with a custom layer, or by adding a "custom model" in a Core ML pipeline), but that is cumbersome and you'd need to implement the actual logic for that function in Swift or Obj-C anyway...