Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion skpro/model_selection/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Tuning and model selection."""

__all__ = ["GridSearchCV", "RandomizedSearchCV"]
__all__ = ["GridSearchCV", "RandomizedSearchCV", "ProbaRegOptCV"]

from skpro.model_selection._tuning import GridSearchCV, RandomizedSearchCV
from skpro.model_selection._hyperactive import ProbaRegOptCV
58 changes: 58 additions & 0 deletions skpro/model_selection/_hyperactive.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# copyright: skpro developers, BSD-3-Clause License (see LICENSE file)
"""Hyperactive Search CV tuning for probabilistic regressors."""

from skpro.registry._placeholder_rec import _placeholder_record
from skpro.regression.base._delegate import _DelegatedProbaRegressor

@_placeholder_record(
dependency="hyperactive",
import_path="hyperactive.integrations.skpro.ProbaRegOptCV"
)
class ProbaRegOptCV(_DelegatedProbaRegressor):
"""Hyperparameter search cross-validation using Hyperactive tuner.

Performs hyperparameter optimization of probabilistic regressors
using the hyperactive optimization backend.
"""

_tags = {
"estimator_type": "regressor",
"capability:multioutput": True,
"capability:missing": True,
"python_dependencies": "hyperactive",
"tests:vm": True,
}

def __init__(
self,
estimator,
optimizer,
cv=None,
scoring=None,
refit=True,
error_score=None,
backend=None,
backend_params=None,
):
self.estimator = estimator
self.optimizer = optimizer
self.cv = cv
self.scoring = scoring
self.refit = refit
self.error_score = error_score
self.backend = backend
self.backend_params = backend_params

super().__init__()

# Clone tags from base estimator
tags_to_clone = [
"capability:multioutput",
"capability:missing",
"capability:survival",
]
self.clone_tags(estimator, tags_to_clone)

def _fit(self, X, y, C=None):
"""Fit stub placeholder."""
pass
2 changes: 2 additions & 0 deletions skpro/registry/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
)
from skpro.registry._craft import craft, deps, imports
from skpro.registry._lookup import all_objects, all_tags
from skpro.registry._placeholder_rec import _placeholder_record
from skpro.registry._scitype import scitype
from skpro.registry._tags import (
OBJECT_TAG_LIST,
Expand All @@ -33,4 +34,5 @@
"get_test_class_for_str",
"imports",
"scitype",
"_placeholder_record",
]
41 changes: 41 additions & 0 deletions skpro/registry/_placeholder_rec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# copyright: skpro developers, BSD-3-Clause License (see LICENSE file)
"""Placeholder registry utilities for optional soft dependencies."""

import importlib
from functools import wraps

def _placeholder_record(dependency, import_path):
"""Decorator to mark a class as a placeholder for a soft dependency.

If the soft dependency is installed, the class is transparently
replaced with the actual class from the external package.
If it is not installed, the stub class is returned. Any attempt
to instantiate it will raise an ImportError explaining how to
install the soft dependency.
"""
def decorator(cls):
from skbase.utils.dependencies import _check_soft_dependencies

# Check if the soft dependency is installed in the environment
if _check_soft_dependencies(dependency, severity="none"):
try:
module_path, class_name = import_path.rsplit(".", 1)
module = importlib.import_module(module_path)
real_class = getattr(module, class_name)
return real_class
except (ImportError, AttributeError):
pass

# If not installed, wrap __init__ to raise a clear soft-dependency error
original_init = cls.__init__

@wraps(original_init)
def new_init(self, *args, **kwargs):
from skbase.utils.dependencies import _check_soft_dependencies
_check_soft_dependencies(dependency, severity="error", obj=self)
original_init(self, *args, **kwargs)

cls.__init__ = new_init
return cls

return decorator