MINIROCKET - fast random convolutional features for time series.
Classes
class algorithms.timeseries.classification.rocket.MiniRocketClassifier(TimeSeriesClassifier)
MINIROCKET: near state-of-the-art accuracy at a tiny fraction of the cost.
__init__( self, n_features: int = 9996, estimator: Optional[Any] = None, random_state: Optional[int] = None, )
Overview
-
Build the 84 fixed kernels: length 9, weights from
{-1, 2}with
- Pick exponentially spaced dilations that fit inside the series.
- For each kernel and dilation, set biases at quantiles of the actual
- Transform each series to one PPV feature per (kernel, dilation, bias).
- Fit a linear classifier on those features.
Theory
Every kernel w has weights in \{-1, 2\} with three 2s, so \sum_i w_i = 3 \cdot 2 + 6 \cdot (-1) = 0. A constant offset therefore cancels wherever the whole kernel overlaps real data — though not at the zero-padded edges, where it does not; see the normalisation note below. The feature for kernel w, dilation d and bias b is
PPV, rather than the max pooling used by earlier convolutional transforms, is what carries most of MINIROCKET's accuracy: it measures how often a pattern matches, not merely how strongly it matches once.
The speed comes from an algebraic trick. A kernel is -1 everywhere except at three positions holding +2, so it equals the all--1 kernel plus a correction of +3 at those three positions. The all--1 convolution is computed once per dilation and the nine possible corrections cached, after which each of the 84 kernels costs three vector additions rather than a fresh convolution. That is the difference between MINIROCKET and random-kernel ROCKET.
Parameters
n_features
estimator
LogisticRegression. Any TuiML classifier works; the transform is the method, the head is a choice.
random_state
Attributes
dilations_
features_per_dilation_
biases_
n_features_
estimator_
classes_
fit.
Notes
Complexity. Fitting the transform is O(84 \, k \, L) for k dilations, independent of the training-set size — biases come from sampled series. Transforming is O(n \, 84 \, k \, L), run in parallel over series by the shared C++ kernel tuiml._cpp_ext.timeseries. The head then dominates.
When to use. MINIROCKET is the right default for time-series classification at any scale where DTWNeighborsClassifier is too slow — which is most of them, since DTW's cost grows with the training set while this transform's does not. Unlike DTW it is not warping-invariant: it detects whether patterns occur, at what scale and how often, which is usually what distinguishes classes, but if two classes differ only by a global time-warp DTW remains the better tool.
Measured on a synthetic problem where the class is the frequency of a short burst hidden at a random position, with amplitude, phase, sign and position randomised and each series z-normalised so no energy cue survives (400 train / 400 test, length 256):
=============== ========== =============== model accuracy predict time =============== ========== =============== MINIROCKET 0.983 168 ms Euclidean 1NN 0.895 39 ms DTW-1NN (10%) 0.772 12 935 ms RandomForest 0.590 9 ms =============== ========== ===============
DTW is both the slowest and among the least accurate here, because warping invariance actively smears the frequency information that defines the classes — the same trade-off documented on DTWNeighborsClassifier. Note also what the cost columns do as data grows: on an easier problem, going from 200 to 1000 training series left MINIROCKET's prediction time flat (83 ms to 76 ms) while DTW's rose with the training set (144 ms to 670 ms). That asymptotic difference, not any single benchmark row, is the reason to reach for this first.
Z-normalise each series first. The kernel weights sum to zero, so a constant offset cancels wherever the whole kernel fits inside the series — but the convolution is zero-padded at the edges, where only part of the kernel overlaps real data and the weights no longer cancel. Half the features are scored over that padded range, so offset invariance holds for the valid-centre features and not for the padded ones. Scale is never cancelled. Normalising removes both concerns.
Multivariate input is handled channel-independently: the transform is applied to each channel and the features concatenated. That is a simplification of the paper's multivariate variant, which samples channel subsets per kernel; it costs feature-count efficiency, not correctness, and cross-channel interactions are left to the head.
References
See Also
>>> import numpy as np
>>> from tuiml.algorithms.timeseries.classification import MiniRocketClassifier
>>> rng = np.random.default_rng(0)
>>> t = np.linspace(0, 4 * np.pi, 64)
>>> shifts = rng.uniform(0, 2 * np.pi, 80)
>>> sines = np.sin(t + shifts[:40, None]) + rng.normal(0, 0.1, (40, 64))
>>> squares = np.sign(np.sin(t + shifts[40:, None])) + rng.normal(0, 0.1, (40, 64))
>>> X = np.vstack([sines, squares])
>>> y = np.array([0] * 40 + [1] * 40)
>>> model = MiniRocketClassifier(n_features=840, random_state=0).fit(X, y)
>>> float((model.predict(X) == y).mean())
1.0
Methods
fit
(self, X: np.ndarray, y: np.ndarray) -> 'MiniRocketClassifier'
fit
(self, X: np.ndarray, y: np.ndarray) -> 'MiniRocketClassifier'
Fit the transform and the head.
Parameters
X
y
Returns
self
transform
(self, X: np.ndarray) -> np.ndarray
transform
(self, X: np.ndarray) -> np.ndarray
Return the PPV feature matrix for a panel of series.
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
class algorithms.timeseries.classification.rocket.MiniRocketTransformer(MiniRocketClassifier)
The MINIROCKET transform on its own, with no classifier attached.
__init__( self, n_features: int = 9996, random_state: Optional[int] = None, )
Parameters
n_features
random_state
Attributes
dilations_
biases_
n_features_
Notes
fit accepts y=None.>>> import numpy as np
>>> from tuiml.algorithms.timeseries.classification import MiniRocketTransformer
>>> rng = np.random.default_rng(0)
>>> X = rng.normal(size=(20, 64))
>>> transformer = MiniRocketTransformer(n_features=840, random_state=0).fit(X)
>>> features = transformer.transform(X)
>>> features.shape[0]
20
>>> bool(((features >= 0.0) & (features <= 1.0)).all()) # PPV is a proportion
True
Methods
fit
(self, X: np.ndarray, y: Optional[np.ndarray]=None) -> 'MiniRocketTransformer'
fit
(self, X: np.ndarray, y: Optional[np.ndarray]=None) -> 'MiniRocketTransformer'
Fit the transform. Labels are not used.
Parameters
X
y
Returns
self
fit_transform
(self, X: np.ndarray, y: Optional[np.ndarray]=None) -> np.ndarray
fit_transform
(self, X: np.ndarray, y: Optional[np.ndarray]=None) -> np.ndarray
Fit the transform and return the features of X.
Parameters
X
y
Returns
features