Shapelet transform - interpretable time-series classification.
Classes
class algorithms.timeseries.classification.shapelets.ShapeletTransformClassifier(TimeSeriesClassifier)
Classification by which short subsequences a series contains.
MiniRocketClassifier is accurate but opaque and DTWNeighborsClassifier compares whole series, this method answers "what does the model actually look for?" with an exhibit: the fitted shapelets are real subsequences from the training data that you can plot next to a series and read.__init__( self, n_shapelets: int = 100, n_candidates: int = 1000, min_length: float = 0.05, max_length: float = 0.5, quality: str = 'f_stat', remove_similar: bool = True, estimator: Optional[Any] = None, random_state: Optional[int] = None, )
Overview
- Sample candidate subsequences at random positions and lengths from
- For every candidate, compute its distance to every training series —
- Score each candidate by how well those distances separate the classes.
- Keep the best, discarding candidates that overlap an already-kept one.
- Represent each series by its distance to every kept shapelet, and fit a
Theory
The distance from series X to shapelet S of length m is
where \hat{z} z-normalises the window. Normalising each window makes the match invariant to local offset and scale — a shapelet found in a high-amplitude series still matches the same shape at low amplitude — and dividing by \sqrt{m} keeps shapelets of different lengths comparable.
Because the shapelet is z-normalised, the squared distance collapses to 2m - 2\langle X_{p:p+m}, S \rangle / \sigma_p, so the window normalisation never has to be materialised. The C++ kernel uses that, with running sums for \sigma_p.
Exhaustive shapelet search is O(n^2 L^4) and was the method's original obstacle. This class samples n_candidates instead, which is the standard modern remedy and costs little accuracy in practice.
Parameters
n_shapelets
n_candidates
min_length
max_length
quality
'f_stat' is a one-way ANOVA on the distances — vectorised over all candidates and much faster; 'information_gain' is the classical criterion, :math:`O(n)` splits per candidate.
remove_similar
estimator
LogisticRegression.
random_state
Attributes
shapelets_
shapelet_info_
series (training row it came from), start, length, channel and quality.
estimator_
classes_
fit.
Notes
Complexity. Fitting is O(c \, n \, L \, m) for c candidates, n training series of length L and shapelet length m — the candidate scan dominates, and it runs in the shared C++ kernel tuiml._cpp_ext.timeseries.shapelet_distances. Transforming is O(k \, n \, L \, m) for k kept shapelets.
When to use. Choose shapelets when someone will ask why — clinical, industrial or regulatory settings where a prediction has to be defended. Expect to give up some accuracy against MINIROCKET for that; if nobody needs the explanation, MINIROCKET is faster and usually better. Shapelets also suit problems where the class is defined by a local pattern that can appear anywhere in the series, which is exactly what the min-over- windows distance looks for.
Multivariate panels are searched channel by channel, and each shapelet records the channel it came from, so the explanation stays specific.
References
See Also
>>> import numpy as np
>>> from tuiml.algorithms.timeseries.classification import ShapeletTransformClassifier
>>> rng = np.random.default_rng(0)
>>> # Class 1 hides a triangular spike somewhere in the noise; class 0 does not.
>>> X = rng.normal(0, 0.3, (60, 120))
>>> y = np.array([0, 1] * 30)
>>> spike = np.concatenate([np.linspace(0, 3, 8), np.linspace(3, 0, 8)])
>>> for i in np.flatnonzero(y == 1):
... start = rng.integers(0, 100)
... X[i, start:start + 16] += spike
>>> model = ShapeletTransformClassifier(
... n_shapelets=10, n_candidates=200, random_state=0).fit(X, y)
>>> float((model.predict(X) == y).mean())
1.0
The fitted shapelets are real subsequences you can inspect and plot:
>>> len(model.shapelets_)
10
>>> sorted(model.shapelet_info_[0])
['channel', 'length', 'quality', 'series', 'start']
Methods
fit
(self, X: np.ndarray, y: np.ndarray) -> 'ShapeletTransformClassifier'
fit
(self, X: np.ndarray, y: np.ndarray) -> 'ShapeletTransformClassifier'
Search for shapelets and fit the head on the distance features.
Parameters
X
y
Returns
self
transform
(self, X: np.ndarray) -> np.ndarray
transform
(self, X: np.ndarray) -> np.ndarray
Return the shapelet-distance features of a panel.
Parameters
X
Returns
features
predict_proba
(self, X: np.ndarray) -> np.ndarray
predict_proba
(self, X: np.ndarray) -> np.ndarray
Return class probabilities from the head.
Parameters
X
Returns
proba