-
Notifications
You must be signed in to change notification settings - Fork 196
[ENH] Add online regressor support and River adapter #1068
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
patelchaitany
wants to merge
5
commits into
sktime:main
Choose a base branch
from
patelchaitany:enh/river-online-regressor
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
bbbc1f4
Add River online regressor adapter and base class
patelchaitany 5b9a862
Add ConformalResidualRegressor
patelchaitany 8c679cd
Keep bootstrap models frozen on update
patelchaitany 723f20b
Set capability:pred_int consistently across compositions
patelchaitany 4346f4c
Merge remote-tracking branch 'upstream/main' into enh/river-online-re…
patelchaitany File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,6 @@ | ||
| """Adapters for probabilistic regressors.""" | ||
| """Adapters for probabilistic and online regressors.""" | ||
| # copyright: skpro developers, BSD-3-Clause License (see LICENSE file) | ||
|
|
||
| from skpro.regression.adapters._coerce import coerce_to_skpro_regressor | ||
|
|
||
| __all__ = ["coerce_to_skpro_regressor"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| """Coerce foreign regressors to skpro online regressor adapters.""" | ||
| # copyright: skpro developers, BSD-3-Clause License (see LICENSE file) | ||
|
|
||
| __author__ = ["patelchaitany"] | ||
|
|
||
| from skpro.regression.adapters.river._utils import is_river_estimator | ||
| from skpro.regression.base import BaseProbaRegressor | ||
|
|
||
|
|
||
| def coerce_to_skpro_regressor(estimator): | ||
| """Wrap foreign online regressors for use in skpro meta-estimators. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| estimator : object | ||
| Estimator passed by the user to a meta-estimator such as | ||
| ``BaggingRegressor``. | ||
|
|
||
| Returns | ||
| ------- | ||
| estimator : skpro regressor | ||
| ``estimator`` unchanged if already an skpro regressor; otherwise a | ||
| suitable adapter instance. | ||
| """ | ||
| if isinstance(estimator, BaseProbaRegressor): | ||
| return estimator | ||
|
|
||
| if is_river_estimator(estimator): | ||
| from skpro.regression.adapters.river import RiverRegressor | ||
|
|
||
| return RiverRegressor(estimator) | ||
|
|
||
| return estimator |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| """River adapters for online regressors.""" | ||
| # copyright: skpro developers, BSD-3-Clause License (see LICENSE file) | ||
|
|
||
| from skpro.regression.adapters.river._river import RiverRegressor | ||
|
|
||
| __all__ = ["RiverRegressor"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| """Clone plugin for River estimators.""" | ||
| # copyright: skpro developers, BSD-3-Clause License (see LICENSE file) | ||
|
|
||
| __author__ = ["patelchaitany"] | ||
|
|
||
| from copy import deepcopy | ||
|
|
||
| from skbase.base._clone_plugins import BaseCloner | ||
|
|
||
| from skpro.regression.adapters.river._utils import is_river_estimator | ||
|
|
||
|
|
||
| class _RiverDeepcopyCloner(BaseCloner): | ||
| """Clone River estimators via deepcopy. | ||
|
|
||
| River models do not implement sklearn-style ``get_params``; this plugin | ||
| allows ``RiverRegressor.clone()`` to produce independent River model copies. | ||
| """ | ||
|
|
||
| def _check(self, obj): | ||
| return is_river_estimator(obj) | ||
|
|
||
| def _clone(self, obj): | ||
| return deepcopy(obj) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| """Adapter for River online regressors.""" | ||
| # copyright: skpro developers, BSD-3-Clause License (see LICENSE file) | ||
|
|
||
| __author__ = ["patelchaitany"] | ||
| __all__ = ["RiverRegressor"] | ||
|
|
||
| from copy import deepcopy | ||
|
|
||
| import pandas as pd | ||
|
|
||
| from skpro.regression.adapters.river._clone import _RiverDeepcopyCloner | ||
| from skpro.regression.adapters.river._utils import ( | ||
| _learn_batch, | ||
| _predict_batch, | ||
| is_river_estimator, | ||
| ) | ||
| from skpro.regression.base import BaseProbaRegressor | ||
|
|
||
|
|
||
| class RiverRegressor(BaseProbaRegressor): | ||
| """Adapter for River online regressors to the skpro point-prediction API. | ||
|
|
||
| Wraps a River regressor and exposes ``fit``, ``update``, and ``predict`` | ||
| with skpro datatype conversion on the public interface. Probabilistic | ||
| prediction is intentionally not provided; use a meta-estimator such as | ||
| ``BaggingRegressor`` for distributional output. | ||
|
|
||
| On ``fit`` and ``update``, the River model is trained incrementally via | ||
| ``learn_many`` when available, otherwise ``learn_one``. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| estimator : river.base.Estimator | ||
| River regressor instance to wrap. | ||
|
|
||
| Attributes | ||
| ---------- | ||
| estimator_ : river estimator | ||
| Deep copy of the River model after fitting. | ||
|
|
||
| Examples | ||
| -------- | ||
| >>> from skpro.regression.adapters.river import RiverRegressor | ||
| >>> from river import linear_model | ||
| >>> from sklearn.datasets import load_diabetes | ||
| >>> from sklearn.model_selection import train_test_split | ||
| >>> | ||
| >>> X, y = load_diabetes(return_X_y=True, as_frame=True) | ||
| >>> X_train, X_test, y_train, y_test = train_test_split(X, y) | ||
| >>> y_train = y_train.to_frame("target") | ||
| >>> | ||
| >>> reg = RiverRegressor(linear_model.LinearRegression()) | ||
| >>> reg.fit(X_train, y_train) | ||
| RiverRegressor(...) | ||
| >>> reg.update(X_test[:10], y_test[:10].to_frame("target")) | ||
| RiverRegressor(...) | ||
| >>> y_pred = reg.predict(X_test[10:]) | ||
| """ | ||
|
|
||
| _tags = { | ||
| "authors": ["patelchaitany"], | ||
| "maintainers": ["patelchaitany", "fkiraly"], | ||
| "object_type": "regressor_proba", | ||
| "estimator_type": "regressor", | ||
| "python_dependencies": "river", | ||
| "capability:update": True, | ||
| "capability:pred_int": False, | ||
| "capability:multioutput": False, | ||
| "capability:missing": False, | ||
| "tests:vm": True, | ||
| } | ||
|
|
||
| def __init__(self, estimator): | ||
| if not is_river_estimator(estimator): | ||
| raise TypeError( | ||
| "estimator must be a River estimator instance, " | ||
| f"but found type {type(estimator)}" | ||
| ) | ||
| self.estimator = estimator | ||
| super().__init__() | ||
|
|
||
| @classmethod | ||
| def _get_clone_plugins(cls): | ||
| parent_plugins = super()._get_clone_plugins() | ||
| if parent_plugins is None: | ||
| parent_plugins = [] | ||
| return [_RiverDeepcopyCloner] + list(parent_plugins) | ||
|
|
||
| def _fit(self, X, y, C=None): | ||
| if len(y.columns) != 1: | ||
| raise ValueError( | ||
| "RiverRegressor supports single-output regression only, " | ||
| f"but y has {len(y.columns)} columns." | ||
| ) | ||
|
|
||
| self.estimator_ = deepcopy(self.estimator) | ||
| _learn_batch(self.estimator_, X, y) | ||
| return self | ||
|
|
||
| def _update(self, X, y, C=None): | ||
| if len(y.columns) != 1: | ||
| raise ValueError( | ||
| "RiverRegressor supports single-output regression only, " | ||
| f"but y has {len(y.columns)} columns." | ||
| ) | ||
|
|
||
| _learn_batch(self.estimator_, X, y) | ||
| return self | ||
|
|
||
| def _predict(self, X): | ||
| preds = _predict_batch(self.estimator_, X) | ||
| columns = self._get_columns(method="predict") | ||
| return pd.DataFrame(preds, index=X.index, columns=columns) | ||
|
|
||
| @classmethod | ||
| def get_test_params(cls, parameter_set="default"): | ||
| """Return testing parameter settings for the estimator.""" | ||
| from river import linear_model | ||
|
|
||
| params1 = {"estimator": linear_model.LinearRegression()} | ||
| return [params1] |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain the motivation for this new tag?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Until now all skpro regressors supported probabilistic prediction, so this tag wasn't needed. The River adapter is the first point-prediction-only estimator, so capability:pred_int is needed to distinguish which regressors support predict_interval/predict_proba - matching sktime's convention.