Source code for mlprodict.onnx_conv.scorers.register

# -*- encoding: utf-8 -*-
"""
@file
@brief Registers new converters.
"""
import copy
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn import __all__ as sklearn__all__, __version__ as sklearn_version
from skl2onnx import (
    update_registered_converter,
    update_registered_parser)
from skl2onnx.common.data_types import guess_tensor_type
from skl2onnx.common._apply_operation import apply_identity


[docs]class CustomScorerTransform(BaseEstimator, TransformerMixin): """ Wraps a scoring function into a transformer. Function @see fn register_scorers must be called to register the converter associated to this transform. It takes two inputs, expected values and predicted values and returns a score for each observation. """
[docs] def __init__(self, name, fct, kwargs): """ @param name function name @param fct python function @param kwargs parameters function """ BaseEstimator.__init__(self) TransformerMixin.__init__(self) self.name_fct = name self._fct = fct self.kwargs = kwargs
[docs] def __repr__(self): # pylint: disable=W0222 return "{}('{}', {}, {})".format( self.__class__.__name__, self.name_fct, self._fct.__name__, self.kwargs)
[docs]def custom_scorer_transform_parser(scope, model, inputs, custom_parsers=None): """ This function updates the inputs and the outputs for a @see cl CustomScorerTransform. :param scope: Scope object :param model: A scikit-learn object (e.g., *OneHotEncoder* or *LogisticRegression*) :param inputs: A list of variables :param custom_parsers: parsers determines which outputs is expected for which particular task, default parsers are defined for classifiers, regressors, pipeline but they can be rewritten, *custom_parsers* is a dictionary ``{ type: fct_parser(scope, model, inputs, custom_parsers=None) }`` :return: A list of output variables which will be passed to next stage """ if custom_parsers is not None: # pragma: no cover raise NotImplementedError( "Case custom_parsers not empty is not implemented yet.") if isinstance(model, str): raise RuntimeError( # pragma: no cover "Parameter model must be an object not a " "string '{0}'.".format(model)) if len(inputs) != 2: raise RuntimeError( # pragma: no cover "Two inputs expected not {}.".format(len(inputs))) alias = 'Mlprodict' + model.__class__.__name__ this_operator = scope.declare_local_operator(alias, model) this_operator.inputs = inputs scores = scope.declare_local_variable( 'scores', guess_tensor_type(inputs[0].type)) this_operator.outputs.append(scores) return this_operator.outputs
[docs]def custom_scorer_transform_shape_calculator(operator): """ Computes the output shapes for a @see cl CustomScorerTransform. """ if len(operator.inputs) != 2: raise RuntimeError("Two inputs expected.") # pragma: no cover if len(operator.outputs) != 1: raise RuntimeError("One output expected.") # pragma: no cover N = operator.inputs[0].type.shape[0] operator.outputs[0].type = copy.deepcopy(operator.inputs[0].type) operator.outputs[0].type.shape = [N, 1]
[docs]def custom_scorer_transform_converter(scope, operator, container): """ Selects the appropriate converter for a @see cl CustomScorerTransform. """ op = operator.raw_operator name = op.name_fct this_operator = scope.declare_local_operator('fct_' + name) this_operator.raw_operator = op this_operator.inputs = operator.inputs score_name = scope.declare_local_variable( 'scores', operator.inputs[0].type) this_operator.outputs.append(score_name) apply_identity(scope, score_name.full_name, operator.outputs[0].full_name, container)
[docs]def register_scorers(): """ Registers operators for @see cl CustomScorerTransform. """ from .cdist_score import score_cdist_sum, convert_score_cdist_sum done = [] update_registered_parser( CustomScorerTransform, custom_scorer_transform_parser) update_registered_converter( CustomScorerTransform, 'MlprodictCustomScorerTransform', custom_scorer_transform_shape_calculator, custom_scorer_transform_converter) done.append(CustomScorerTransform) update_registered_converter( score_cdist_sum, 'fct_score_cdist_sum', None, convert_score_cdist_sum, options={'cdist': [None, 'single-node']}) return done