Source code for snapboost.linear_learner

"""Weighted linear base learners for optional SnapBoost pools."""

from numbers import Real

import numpy as np
from sklearn.base import BaseEstimator, RegressorMixin
from sklearn.linear_model import Ridge
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.utils.validation import check_array, check_is_fitted, check_X_y


[docs] class WeightedLinearRegressor(BaseEstimator, RegressorMixin): """Standardized weighted ridge regression for Newton working targets.""" def __init__(self, alpha=1.0, scale_features=True): self.alpha = alpha self.scale_features = scale_features def fit(self, X, y, sample_weight=None): X, y = check_X_y(X, y, dtype=float, y_numeric=True) if ( isinstance(self.alpha, (bool, np.bool_)) or not isinstance(self.alpha, Real) or not np.isfinite(self.alpha) or self.alpha <= 0 ): raise ValueError("alpha must be a finite number > 0.") if not isinstance(self.scale_features, (bool, np.bool_)): raise ValueError("scale_features must be a boolean.") if sample_weight is not None: sample_weight = np.asarray(sample_weight, dtype=float) if sample_weight.ndim != 1 or sample_weight.shape[0] != X.shape[0]: raise ValueError("sample_weight must have one value per sample.") if not np.all(np.isfinite(sample_weight)) or np.any(sample_weight < 0): raise ValueError("sample_weight must be finite and non-negative.") positive = sample_weight > 0 if not np.any(positive): raise ValueError("sample_weight must have a positive total weight.") sample_weight = sample_weight[positive] sample_weight *= positive.sum() / sample_weight.sum() X, y = X[positive], y[positive] steps = [] if self.scale_features: steps.append(("scale", StandardScaler())) steps.append(("ridge", Ridge(alpha=self.alpha))) pipeline = Pipeline(steps) fit_params = {} if sample_weight is not None: fit_params["ridge__sample_weight"] = sample_weight if self.scale_features: fit_params["scale__sample_weight"] = sample_weight pipeline.fit(X, y, **fit_params) self.pipeline_ = pipeline self.n_features_in_ = X.shape[1] return self def predict(self, X): check_is_fitted(self, ["pipeline_", "n_features_in_"]) X = check_array(X, dtype=float) if X.shape[1] != self.n_features_in_: raise ValueError( f"X has {X.shape[1]} features, but model was trained with " f"{self.n_features_in_}." ) return self.pipeline_.predict(X)