Source code for sgtlearn.ensemble.RandomSGForestRegressor

"""Bootstrap ensemble of :class:`sgtlearn.base.SGTRegressor` estimators."""

from __future__ import annotations

from typing import Any, Optional, Union

import numpy as np
from sklearn.base import RegressorMixin
from sklearn.utils.validation import check_X_y

from sgtlearn.base import SGTRegressor
from sgtlearn.ensemble._random_sgforest import RandomSGForest


[docs] class RandomSGForestRegressor(RegressorMixin, RandomSGForest): """Random forest of Shape Generalized Trees for regression. Bootstrap ensemble of :class:`sgtlearn.SGTRegressor` base estimators. Prediction semantics match :class:`sklearn.ensemble.RandomForestRegressor`: :meth:`predict` returns the mean of the per-tree :meth:`predict` outputs. Parameters ---------- n_estimators : int, default=100 Number of trees in the forest. criterion : {"squared_error", "mse", "absolute_error", "mae"}, default="squared_error" Loss forwarded to each base tree's outer splits. num_partitions : int, default=2 Arity of the shape function at each outer split. See :class:`sgtlearn.SGTRegressor`. max_depth, max_leaf_nodes, min_samples_leaf, min_impurity_decrease : \ see :class:`sgtlearn.SGTRegressor` Outer-tree stopping criteria forwarded to each base estimator. inner_max_depth, inner_max_leaf_nodes, inner_min_samples_leaf, \ inner_min_impurity_decrease : see :class:`sgtlearn.SGTRegressor` Inner-tree (shape function) controls forwarded to each base estimator. coordinate_descent_max_iters, coordinate_descent_patience, \ coordinate_descent_smart_init : see :class:`sgtlearn.SGTRegressor` Coordinate-descent controls forwarded to each base estimator. Note that ``coordinate_descent_smart_init`` is ignored by the regression trainer. max_features : int, float, {"sqrt", "log2"} or None, default="sqrt" Per-split feature subsampling for each base tree. Defaults to ``"sqrt"`` to follow ``RandomForestRegressor`` convention. See :class:`sgtlearn.SGTRegressor` for the full semantics. bootstrap : bool, default=True If ``True``, each tree is fit on a bootstrap resample (with replacement) of the training set. If ``False``, every tree is fit on the full training set — diversity then comes only from ``random_state`` and ``max_features``. max_samples : int or float, optional Size of each bootstrap sample. ``int`` gives an absolute count; ``float`` in ``(0, 1]`` gives a fraction of ``n_samples``. ``None`` (default) uses ``n_samples``. Only valid when ``bootstrap=True``. random_state : int, RandomState, optional Controls bootstrap resampling and the per-tree seeds. n_jobs : int, optional Number of joblib workers used to fit trees. ``None`` means one job (sequential); ``-1`` uses all processors. Joblib's threading backend is used. verbose : int, default=0 Verbosity of the joblib ``Parallel`` driver. Attributes ---------- estimators_ : list of SGTRegressor The collection of fitted base estimators. n_features_in_ : int Number of features seen during :meth:`fit`. mean_feature_importances_ : ndarray of shape (n_logical_features,) Mean of per-tree :attr:`~sgtlearn.SGTRegressor.feature_importances_`, aligned with :attr:`processed_features_`. std_feature_importance_ : ndarray of shape (n_logical_features,) Population standard deviation of per-tree importances across the forest (same alignment as :attr:`mean_feature_importances_`). processed_features_ : ProcessedFeatures Logical features resolved once and shared by every base tree. See Also -------- sgtlearn.SGTRegressor : Single-tree base estimator. sgtlearn.ensemble.RandomSGForestClassifier : Classification counterpart. sklearn.ensemble.RandomForestRegressor : Standard CART forest with the same prediction semantics. Examples -------- >>> from sklearn.datasets import make_regression >>> from sgtlearn.ensemble import RandomSGForestRegressor >>> X, y = make_regression(n_samples=500, random_state=0) >>> reg = RandomSGForestRegressor(n_estimators=20, random_state=0).fit(X, y) >>> reg.predict(X[:5]).shape (5,) """ _estimator_name = "RandomSGForestRegressor" def __init__( self, n_estimators: int = 100, *, criterion: str = "squared_error", num_partitions: int = 2, max_depth: Optional[int] = None, max_leaf_nodes: Optional[int] = None, min_samples_leaf: int = 1, min_impurity_decrease: float = 0.0, inner_max_depth: int = 3, inner_max_leaf_nodes: int = 8, inner_min_samples_leaf: int = 1, inner_min_impurity_decrease: float = 0.0, coordinate_descent_max_iters: int = 20, coordinate_descent_patience: int = 5, coordinate_descent_smart_init: bool = True, max_features: Optional[Union[int, float, str]] = "sqrt", bootstrap: bool = True, max_samples: Optional[Union[int, float]] = None, random_state: Optional[Union[int, np.random.RandomState]] = None, tao_n_runs: int = 10, tao_lambda: float = 0.0, n_jobs: Optional[int] = None, verbose: int = 0, ) -> None: super().__init__( n_estimators=n_estimators, criterion=criterion, num_partitions=num_partitions, max_depth=max_depth, max_leaf_nodes=max_leaf_nodes, min_samples_leaf=min_samples_leaf, min_impurity_decrease=min_impurity_decrease, inner_max_depth=inner_max_depth, inner_max_leaf_nodes=inner_max_leaf_nodes, inner_min_samples_leaf=inner_min_samples_leaf, inner_min_impurity_decrease=inner_min_impurity_decrease, coordinate_descent_max_iters=coordinate_descent_max_iters, coordinate_descent_patience=coordinate_descent_patience, coordinate_descent_smart_init=coordinate_descent_smart_init, max_features=max_features, bootstrap=bootstrap, max_samples=max_samples, random_state=random_state, tao_n_runs=tao_n_runs, tao_lambda=tao_lambda, n_jobs=n_jobs, verbose=verbose, ) def _check_X_y(self, X: np.ndarray, y: np.ndarray) -> tuple[np.ndarray, np.ndarray]: return check_X_y( X, y, accept_sparse=False, dtype=np.float64, ensure_all_finite="allow-nan", y_numeric=True, ) def _make_tree(self, tree_seed: int, tree_kw: dict[str, Any]) -> SGTRegressor: return SGTRegressor(**tree_kw, random_state=tree_seed) def predict(self, X: np.ndarray) -> np.ndarray: X32 = self._check_predict_X(X) acc = np.zeros(X.shape[0], dtype=np.float64) for est in self.estimators_: acc += est.predict(X32) acc /= float(len(self.estimators_)) return acc
__all__ = ["RandomSGForestRegressor"]