Expand source code
import numpy as np
from typing import List
from imodels.rule_set.rule_fit import RuleFit
from imodels.util.score import score_linear
from sklearn.base import ClassifierMixin, RegressorMixin, BaseEstimator
from .util import extract_ensemble
class StableLinear(RuleFit):
def __init__(self,
weak_learners: List[BaseEstimator],
max_complexity: int,
min_mult: int = 1,
penalty='l1',
n_estimators=100,
tree_size=4,
sample_fract='default',
max_rules=30,
memory_par=0.01,
tree_generator=None,
lin_trim_quantile=0.025,
lin_standardise=True,
exp_rand_tree_size=True,
include_linear=False,
alpha=None,
random_state=None):
super().__init__(n_estimators,
tree_size,
sample_fract,
max_rules,
memory_par,
tree_generator,
lin_trim_quantile,
lin_standardise,
exp_rand_tree_size,
include_linear,
alpha,
random_state)
self.max_complexity = max_complexity
self.weak_learners = weak_learners
self.penalty = penalty
self.min_mult = min_mult
def fit(self, X, y=None, feature_names=None):
super().fit(X, y, feature_names=feature_names)
return self
def _extract_rules(self, X, y) -> List[str]:
return extract_ensemble(self.weak_learners, X, y, self.min_mult)
def _score_rules(self, X, y, rules):
X_concat = np.zeros([X.shape[0], 0])
# standardise linear variables if requested (for regression model only)
if self.include_linear:
# standard deviation and mean of winsorized features
self.winsorizer.train(X)
winsorized_X = self.winsorizer.trim(X)
self.stddev = np.std(winsorized_X, axis=0)
self.mean = np.mean(winsorized_X, axis=0)
if self.lin_standardise:
self.friedscale.train(X)
X_regn = self.friedscale.scale(X)
else:
X_regn = X.copy()
X_concat = np.concatenate((X_concat, X_regn), axis=1)
X_rules = self.transform(X, rules)
if X_rules.shape[0] > 0:
X_concat = np.concatenate((X_concat, X_rules), axis=1)
# no rules fit and self.include_linear == False
if X_concat.shape[1] == 0:
return [], [], 0
return score_linear(X_concat, y, rules,
alpha=self.alpha,
penalty=self.penalty,
prediction_task=self.prediction_task,
max_rules=self.max_rules, random_state=self.random_state)
class StableLinearRegressor(StableLinear, RegressorMixin):
def _init_prediction_task(self):
self.prediction_task = 'regression'
class StableLinearClassifier(StableLinear, ClassifierMixin):
def _init_prediction_task(self):
self.prediction_task = 'classification'
Classes
class StableLinear (weak_learners: List[sklearn.base.BaseEstimator], max_complexity: int, min_mult: int = 1, penalty='l1', n_estimators=100, tree_size=4, sample_fract='default', max_rules=30, memory_par=0.01, tree_generator=None, lin_trim_quantile=0.025, lin_standardise=True, exp_rand_tree_size=True, include_linear=False, alpha=None, random_state=None)-
Rulefit class. Rather than using this class directly, should use RuleFitRegressor or RuleFitClassifier
Parameters
n_estimators:int, default=100- Number of trees grown to generate candidate rules.
tree_size:int, default=4- Number of terminal nodes in generated trees. If exp_rand_tree_size=True, this is the mean number of terminal nodes.
sample_fract:floator"default", default="default"- Fraction of randomly chosen training observations used to produce each tree (Friedman and Popescu 2004, Sec. 2).
max_rules:int, default=30- Total number of terms included in the final model (both linear terms and rules). The approximate number of candidate rules generated is also based on this; the actual number is usually lower because of duplicates.
memory_par:float, default=0.01- Scale multiplier (shrinkage factor) applied to each new tree when sequentially induced (Friedman and Popescu 2004, Sec. 2).
tree_generator:estimator, optional- Used as provided to generate the rules, overriding most of the parameters above. Must be GradientBoostingRegressor(), GradientBoostingClassifier() or RandomForestRegressor(). A copy is fitted on the training data, so the object passed in is left untouched (and any previous fit of it is not reused). n_estimators, max_leaf_nodes and random_state are set on that copy while the trees are grown, so tuning them on the generator has no effect.
lin_trim_quantile:float, default=0.025- If lin_standardise is True, this quantile is used to trim linear terms before standardisation.
lin_standardise:bool, default=True- If True, linear terms are standardised as in Friedman and Popescu (Sec. 3.2), by multiplying the winsorised variable by 0.4 / stdev.
exp_rand_tree_size:bool, default=True- If True, each boosted tree has a different maximum number of terminal nodes, drawn from an exponential distribution about tree_size (Sec. 3.3).
include_linear:bool, default=True- Include linear terms as well as rules.
alpha:float, optional- Regularization strength; overrides max_rules.
cv:bool, default=True- Whether to use cross-validation scores to select the regularization strength, out of all values that satisfy max_rules. If False, the least regularization possible is used.
random_state:int, optional- Seed for the random objects, for repeatability.
verbose:int, default=0- Verbosity.
Attributes
rule_ensemble:RuleEnsemble- The rule ensemble.
feature_names:listofstr, optional- The names of the features (columns).
Expand source code
class StableLinear(RuleFit): def __init__(self, weak_learners: List[BaseEstimator], max_complexity: int, min_mult: int = 1, penalty='l1', n_estimators=100, tree_size=4, sample_fract='default', max_rules=30, memory_par=0.01, tree_generator=None, lin_trim_quantile=0.025, lin_standardise=True, exp_rand_tree_size=True, include_linear=False, alpha=None, random_state=None): super().__init__(n_estimators, tree_size, sample_fract, max_rules, memory_par, tree_generator, lin_trim_quantile, lin_standardise, exp_rand_tree_size, include_linear, alpha, random_state) self.max_complexity = max_complexity self.weak_learners = weak_learners self.penalty = penalty self.min_mult = min_mult def fit(self, X, y=None, feature_names=None): super().fit(X, y, feature_names=feature_names) return self def _extract_rules(self, X, y) -> List[str]: return extract_ensemble(self.weak_learners, X, y, self.min_mult) def _score_rules(self, X, y, rules): X_concat = np.zeros([X.shape[0], 0]) # standardise linear variables if requested (for regression model only) if self.include_linear: # standard deviation and mean of winsorized features self.winsorizer.train(X) winsorized_X = self.winsorizer.trim(X) self.stddev = np.std(winsorized_X, axis=0) self.mean = np.mean(winsorized_X, axis=0) if self.lin_standardise: self.friedscale.train(X) X_regn = self.friedscale.scale(X) else: X_regn = X.copy() X_concat = np.concatenate((X_concat, X_regn), axis=1) X_rules = self.transform(X, rules) if X_rules.shape[0] > 0: X_concat = np.concatenate((X_concat, X_rules), axis=1) # no rules fit and self.include_linear == False if X_concat.shape[1] == 0: return [], [], 0 return score_linear(X_concat, y, rules, alpha=self.alpha, penalty=self.penalty, prediction_task=self.prediction_task, max_rules=self.max_rules, random_state=self.random_state)Ancestors
- RuleFit
- sklearn.base.BaseEstimator
- sklearn.utils._estimator_html_repr._HTMLDocumentationLinkMixin
- sklearn.utils._metadata_requests._MetadataRequester
- sklearn.base.TransformerMixin
- sklearn.utils._set_output._SetOutputMixin
- RuleSet
- RulesMixin
- TextMixin
Subclasses
Inherited members
class StableLinearClassifier (weak_learners: List[sklearn.base.BaseEstimator], max_complexity: int, min_mult: int = 1, penalty='l1', n_estimators=100, tree_size=4, sample_fract='default', max_rules=30, memory_par=0.01, tree_generator=None, lin_trim_quantile=0.025, lin_standardise=True, exp_rand_tree_size=True, include_linear=False, alpha=None, random_state=None)-
Rulefit class. Rather than using this class directly, should use RuleFitRegressor or RuleFitClassifier
Parameters
n_estimators:int, default=100- Number of trees grown to generate candidate rules.
tree_size:int, default=4- Number of terminal nodes in generated trees. If exp_rand_tree_size=True, this is the mean number of terminal nodes.
sample_fract:floator"default", default="default"- Fraction of randomly chosen training observations used to produce each tree (Friedman and Popescu 2004, Sec. 2).
max_rules:int, default=30- Total number of terms included in the final model (both linear terms and rules). The approximate number of candidate rules generated is also based on this; the actual number is usually lower because of duplicates.
memory_par:float, default=0.01- Scale multiplier (shrinkage factor) applied to each new tree when sequentially induced (Friedman and Popescu 2004, Sec. 2).
tree_generator:estimator, optional- Used as provided to generate the rules, overriding most of the parameters above. Must be GradientBoostingRegressor(), GradientBoostingClassifier() or RandomForestRegressor(). A copy is fitted on the training data, so the object passed in is left untouched (and any previous fit of it is not reused). n_estimators, max_leaf_nodes and random_state are set on that copy while the trees are grown, so tuning them on the generator has no effect.
lin_trim_quantile:float, default=0.025- If lin_standardise is True, this quantile is used to trim linear terms before standardisation.
lin_standardise:bool, default=True- If True, linear terms are standardised as in Friedman and Popescu (Sec. 3.2), by multiplying the winsorised variable by 0.4 / stdev.
exp_rand_tree_size:bool, default=True- If True, each boosted tree has a different maximum number of terminal nodes, drawn from an exponential distribution about tree_size (Sec. 3.3).
include_linear:bool, default=True- Include linear terms as well as rules.
alpha:float, optional- Regularization strength; overrides max_rules.
cv:bool, default=True- Whether to use cross-validation scores to select the regularization strength, out of all values that satisfy max_rules. If False, the least regularization possible is used.
random_state:int, optional- Seed for the random objects, for repeatability.
verbose:int, default=0- Verbosity.
Attributes
rule_ensemble:RuleEnsemble- The rule ensemble.
feature_names:listofstr, optional- The names of the features (columns).
Expand source code
class StableLinearClassifier(StableLinear, ClassifierMixin): def _init_prediction_task(self): self.prediction_task = 'classification'Ancestors
- StableLinear
- RuleFit
- sklearn.base.BaseEstimator
- sklearn.utils._estimator_html_repr._HTMLDocumentationLinkMixin
- sklearn.utils._metadata_requests._MetadataRequester
- sklearn.base.TransformerMixin
- sklearn.utils._set_output._SetOutputMixin
- RuleSet
- RulesMixin
- TextMixin
- sklearn.base.ClassifierMixin
Inherited members
class StableLinearRegressor (weak_learners: List[sklearn.base.BaseEstimator], max_complexity: int, min_mult: int = 1, penalty='l1', n_estimators=100, tree_size=4, sample_fract='default', max_rules=30, memory_par=0.01, tree_generator=None, lin_trim_quantile=0.025, lin_standardise=True, exp_rand_tree_size=True, include_linear=False, alpha=None, random_state=None)-
Rulefit class. Rather than using this class directly, should use RuleFitRegressor or RuleFitClassifier
Parameters
n_estimators:int, default=100- Number of trees grown to generate candidate rules.
tree_size:int, default=4- Number of terminal nodes in generated trees. If exp_rand_tree_size=True, this is the mean number of terminal nodes.
sample_fract:floator"default", default="default"- Fraction of randomly chosen training observations used to produce each tree (Friedman and Popescu 2004, Sec. 2).
max_rules:int, default=30- Total number of terms included in the final model (both linear terms and rules). The approximate number of candidate rules generated is also based on this; the actual number is usually lower because of duplicates.
memory_par:float, default=0.01- Scale multiplier (shrinkage factor) applied to each new tree when sequentially induced (Friedman and Popescu 2004, Sec. 2).
tree_generator:estimator, optional- Used as provided to generate the rules, overriding most of the parameters above. Must be GradientBoostingRegressor(), GradientBoostingClassifier() or RandomForestRegressor(). A copy is fitted on the training data, so the object passed in is left untouched (and any previous fit of it is not reused). n_estimators, max_leaf_nodes and random_state are set on that copy while the trees are grown, so tuning them on the generator has no effect.
lin_trim_quantile:float, default=0.025- If lin_standardise is True, this quantile is used to trim linear terms before standardisation.
lin_standardise:bool, default=True- If True, linear terms are standardised as in Friedman and Popescu (Sec. 3.2), by multiplying the winsorised variable by 0.4 / stdev.
exp_rand_tree_size:bool, default=True- If True, each boosted tree has a different maximum number of terminal nodes, drawn from an exponential distribution about tree_size (Sec. 3.3).
include_linear:bool, default=True- Include linear terms as well as rules.
alpha:float, optional- Regularization strength; overrides max_rules.
cv:bool, default=True- Whether to use cross-validation scores to select the regularization strength, out of all values that satisfy max_rules. If False, the least regularization possible is used.
random_state:int, optional- Seed for the random objects, for repeatability.
verbose:int, default=0- Verbosity.
Attributes
rule_ensemble:RuleEnsemble- The rule ensemble.
feature_names:listofstr, optional- The names of the features (columns).
Expand source code
class StableLinearRegressor(StableLinear, RegressorMixin): def _init_prediction_task(self): self.prediction_task = 'regression'Ancestors
- StableLinear
- RuleFit
- sklearn.base.BaseEstimator
- sklearn.utils._estimator_html_repr._HTMLDocumentationLinkMixin
- sklearn.utils._metadata_requests._MetadataRequester
- sklearn.base.TransformerMixin
- sklearn.utils._set_output._SetOutputMixin
- RuleSet
- RulesMixin
- TextMixin
- sklearn.base.RegressorMixin
Inherited members