import numpy as np
from sklearn.base import RegressorMixin, ClassifierMixin
from ..base import ModelBaseRegressor, ModelBaseClassifier
[docs]
class MoRegressor(RegressorMixin, ModelBaseRegressor):
"""
A model wrapper for arbitrary regression models with predict and fit functions.
Parameters
----------
predict_function : callable
Callable function for making predictions. It takes 2D numpy array as inputs and outputs 1D numpy array.
fit_function : callable, default=None
Callable function for fitting the model. It takes X, y, sample_weights, and hyperparameters as inputs and trains the model.
name : str, default=None
Optional name for the model.
**kwargs : dict
Hyperparameters to store as attributes for compatibility with scikit-learn hyperparameter tuning.
"""
def __init__(self, predict_function, fit_function=None, name=None, **kwargs):
self.name = name
self.predict_function = predict_function
self.fit_function = fit_function
self.hyperparameters = kwargs
if fit_function is None:
self.is_fitted_ = True
[docs]
def get_params(self, deep=True):
"""
Get parameters for this estimator.
Parameters
----------
deep : bool, default=True
If True, will return the parameters for this estimator and
contained subobjects that are estimators.
Returns
-------
params : dict
Parameter names mapped to their values.
"""
params = {"predict_function": self.predict_function,
"fit_function": self.fit_function,
"name": self.name}
params.update(self.hyperparameters)
return params
[docs]
def set_params(self, **params):
"""Set the parameters of this estimator.
The method works on simple estimators as well as on nested objects
(such as :class:`~sklearn.pipeline.Pipeline`). The latter have
parameters of the form ``<component>__<parameter>`` so that it's
possible to update each component of a nested object.
Parameters
----------
**params : dict
Estimator parameters.
Returns
-------
self : estimator instance
"""
for key, value in params.items():
if key in {"predict_function", "fit_function", "name"}:
setattr(self, key, value)
else:
self.hyperparameters[key] = value
return self
[docs]
def fit(self, X, y, sample_weight=None):
"""
Fits the model using the provided data.
Parameters
----------
X : array-like
Input features.
y : array-like
Target values.
sample_weight : array-like, default=None
Optional weights for the samples.
Returns
-------
self : object
Fitted instance of the model.
"""
if not callable(self.fit_function):
raise ValueError("The provided fit function is not callable.")
self.fit_function(X, y, sample_weight, **self.hyperparameters)
self.is_fitted_ = True
return self
def _predict(self, X):
"""
Makes predictions using the fitted model.
Parameters
----------
X : array-like
Input features.
Returns
-------
array-like
The predicted values.
"""
if not callable(self.predict_function):
raise ValueError("The provided predict function is not callable.")
return self.predict_function(X, **self.hyperparameters)
[docs]
class MoClassifier(ClassifierMixin, ModelBaseClassifier):
"""
A model wrapper for arbitrary classification models with predict, predict_proba, and fit functions.
Parameters
----------
predict_proba_function : callable
Callable function for predicting probabilities. It takes 2D numpy array as inputs and outputs 2D numpy array.
fit_function : callable, default=None
Callable function for fitting the model. It takes X, y, sample_weights, and hyperparameters as inputs and trains the model.
name : str, default=None
Optional name for the model.
**kwargs : dict
Hyperparameters to store as attributes for compatibility with scikit-learn hyperparameter tuning.
"""
def __init__(self, predict_proba_function, fit_function=None, name=None, **kwargs):
self.name = name
self.predict_proba_function = predict_proba_function
self.fit_function = fit_function
self.hyperparameters = kwargs
self.is_fitted_ = True
self.classes_ = [0, 1]
[docs]
def get_params(self, deep=True):
"""
Get parameters for this estimator.
Parameters
----------
deep : bool, default=True
If True, will return the parameters for this estimator and
contained subobjects that are estimators.
Returns
-------
params : dict
Parameter names mapped to their values.
"""
params = {
"predict_proba_function": self.predict_proba_function,
"fit_function": self.fit_function,
"name": self.name,
}
params.update(self.hyperparameters)
return params
[docs]
def set_params(self, **params):
"""Set the parameters of this estimator.
The method works on simple estimators as well as on nested objects
(such as :class:`~sklearn.pipeline.Pipeline`). The latter have
parameters of the form ``<component>__<parameter>`` so that it's
possible to update each component of a nested object.
Parameters
----------
**params : dict
Estimator parameters.
Returns
-------
self : estimator instance
"""
for key, value in params.items():
if key in {"predict_proba_function", "fit_function", "name"}:
setattr(self, key, value)
else:
self.hyperparameters[key] = value
return self
[docs]
def fit(self, X, y, sample_weight=None):
"""
Fits the model using the provided data.
Parameters
----------
X : array-like
Input features.
y : array-like
Target values.
sample_weight : array-like, default=None
Optional weights for the samples.
Returns
-------
self : object
Fitted instance of the model.
"""
if not callable(self.fit_function):
raise ValueError("The provided fit function is not callable.")
self.fit_function(X, y, sample_weight, **self.hyperparameters)
self.is_fitted_ = True
self.classes_ = np.unique(y)
return self
def _predict_proba(self, X):
"""
Predicts class probabilities for the input features.
Parameters
----------
X : array-like
Input features.
Returns
-------
array-like
The predicted probabilities.
"""
if not callable(self.predict_proba_function):
raise ValueError("The provided predict proba function is not callable.")
return self.predict_proba_function(X)