Source code for RuleTree.stumps.regression.ShapeletTreeStumpRegressor

"""ShapeletTreeStumpRegressor: the split on the distance from a shapelet, for regression of time series."""

from typing import Optional


from RuleTree.stumps.classification.ShapeletTreeStumpClassifier import ShapeletTreeStumpClassifier
from RuleTree.stumps.regression.DecisionTreeStumpRegressor import DecisionTreeStumpRegressor
from RuleTree.stumps.transformers.ShapeletTransformer import ShapeletTransformer


[docs] class ShapeletTreeStumpRegressor(DecisionTreeStumpRegressor): """ Shapelet stump for regression of time series: a threshold on the distance of the time series from a *shapelet* (``distance <= t`` goes left). A shapelet is a subsequence of one of the time series of the node; the distance of a time series from it is the smallest distance between the shapelet and the subsequences of the series, so it does not depend on where the pattern occurs. At each node, ``n_shapelets`` shapelets are selected among candidate subsequences, and the split is the best threshold on the distance from one of them. In the rules, ``euclidean(TS, shp)`` is the distance from the shapelet. It is a :class:`~RuleTree.stumps.Stump.Stump` made of a ShapeletTransformer and a RegressionSplitter. The time series have shape (n_samples, n_signals, length) and are passed to the trees as ``X_ts``. Parameters ---------- n_shapelets : int, default=8 Number of shapelets selected at each node. n_shapelets_for_selection : int, numpy.inf or 'stratified', default=500 Number of candidate subsequences extracted from the time series, among which the shapelets are selected. 'stratified' draws them according to the class distribution. n_ts_for_selection_per_class : int or numpy.inf, default=100 Number of time series of each class from which the candidates are extracted. sliding_window : int, default=50 Length of the shapelets. selection : {'random', 'mi_reg', 'cluster'}, default='mi_reg' How the shapelets are selected among the candidates: at random, by mutual information with the target, or as the medoids of a k-medoids clustering (requires scikit-learn-extra). distance : {'euclidean', 'sqeuclidean', 'cosine', 'cityblock'} or callable, default='euclidean' Distance between a shapelet and a subsequence; the distance of a time series from a shapelet is the minimum over the positions of the shapelet. mi_n_neighbors : int, default=100 Number of neighbors used to estimate the mutual information. random_state : int, default=42 Seed of the random choices of the candidates and of the shapelets. n_jobs : int, default=1 Number of threads used to compute the distances (-1: all the CPUs). criterion : {'squared_error', 'absolute_error', 'poisson'}, default='squared_error' Impurity measure. min_samples_leaf : int or float, default=1 Minimum number of instances in each child (a fraction of the instances of the node if float). Applies to the numerical features. min_weight_fraction_leaf : float, default=0.0 Minimum fraction of the sample weights of the node in each child. Applies to the numerical features. max_features : int, float, {'sqrt', 'log2'} or None, default=None Number of numerical features considered for the split, drawn at random; None for all. min_impurity_decrease : float, default=0.0 A numerical split is kept only if it decreases the weighted impurity by at least this value. Attributes ---------- transformer_ : ShapeletTransformer The fitted transformer. splitter_ : RegressionSplitter The fitted splitter (feature, threshold, gain and impurity of the split). data_type_ : str Data type the stump was fitted on. feature_original : int Index of the shapelet of the split among the selected ones. threshold_original : float Threshold of the split. See Also -------- ShapeletTreeStumpClassifier : the same stump for classification. RuleTree.utils.shapelet_transform.Shapelets.Shapelets : the selection of the shapelets. Examples -------- >>> import numpy as np >>> from RuleTree import RuleTreeRegressor >>> from RuleTree.stumps.regression import ShapeletTreeStumpRegressor >>> rng = np.random.default_rng(0) >>> X_ts = rng.normal(size=(60, 1, 30)) # 60 time series of length 30 >>> y = X_ts[:, 0, 10:20].mean(axis=1) >>> stump = ShapeletTreeStumpRegressor(n_shapelets=5, sliding_window=10, selection="random") >>> model = RuleTreeRegressor(max_depth=2, base_stumps=stump).fit(X_ts=X_ts, y=y) >>> model.predict(X_ts=X_ts).shape (60,) """ def __init__(self, n_shapelets=8, n_shapelets_for_selection=500, # int, inf, or 'stratified' n_ts_for_selection_per_class=100, # int, inf sliding_window=50, selection='mi_reg', # random, mi_reg, cluster distance='euclidean', mi_n_neighbors=100, random_state=42, n_jobs=1, criterion='squared_error', min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None, min_impurity_decrease=0.0): """Initialize the ShapeletTreeStumpRegressor; see the class documentation for the parameters.""" if selection not in ['random', 'mi_reg', 'cluster']: raise ValueError("'selection' must be 'random', 'mi_reg' or 'cluster'") self.n_shapelets = n_shapelets self.n_shapelets_for_selection = n_shapelets_for_selection self.n_ts_for_selection_per_class = n_ts_for_selection_per_class self.sliding_window = sliding_window self.selection = selection self.distance = distance self.mi_n_neighbors = mi_n_neighbors self.random_state = random_state self.n_jobs = n_jobs self.criterion = criterion self.min_samples_leaf = min_samples_leaf self.min_weight_fraction_leaf = min_weight_fraction_leaf self.max_features = max_features self.min_impurity_decrease = min_impurity_decrease def _splitter_params(self): """ Parameters of the splitter: as in the decision tree stump, but without random_state, which is the one of the shapelet selection. Returns ------- params : dict """ return super()._splitter_params() | {"random_state": None} def _make_transformer(self): """ A new, unfitted ShapeletTransformer with the parameters of the stump. Returns ------- transformer : ShapeletTransformer """ return ShapeletTransformer(n_shapelets=self.n_shapelets, n_shapelets_for_selection=self.n_shapelets_for_selection, n_ts_for_selection_per_class=self.n_ts_for_selection_per_class, sliding_window=self.sliding_window, selection=self.selection, distance=self.distance, mi_n_neighbors=self.mi_n_neighbors, random_state=self.random_state, n_jobs=self.n_jobs) @property def st(self): """The fitted shapelet transform.""" return self.transformer_.st_
[docs] def get_rule(self, columns_names=None, scaler=None, float_precision: Optional[int] = 3): """ Rule of the split, e.g. ``euclidean(TS, shp) <= 1.2``. Parameters ---------- columns_names : list of str, default=None Not used. scaler : TransformerMixin, default=None Not supported: must be None. float_precision : int, default=3 Number of decimals of the threshold. If None, it is not rounded. Returns ------- rule : dict See RuleTreeBaseStump.get_rule. Raises ------ ValueError If a scaler is given. """ return ShapeletTreeStumpClassifier.get_rule(self, columns_names, scaler, float_precision)
[docs] def get_graphviz_rule(self, columns_names=None, scaler=None, float_precision: Optional[int] = 3): """ Attributes of the Graphviz node of the split, with a plot of the shapelet (see ShapeletTreeStumpClassifier.get_graphviz_rule). Parameters ---------- columns_names : list of str, default=None Not used. scaler : TransformerMixin, default=None Not supported: must be None. float_precision : int, default=3 Number of decimals of the threshold. If None, it is not rounded. Returns ------- attributes : dict Attributes of the Graphviz node. """ return ShapeletTreeStumpClassifier.get_graphviz_rule(self, columns_names, scaler, float_precision)