HIVE-COTE - a meta-ensemble over distinct time-series representations.
Classes
class algorithms.timeseries.classification.hive_cote.HIVECOTEClassifier(TimeSeriesClassifier)
Combine different representations of a series, weighted by competence.
Every other classifier in this package looks at a series one way: elastic alignment, convolutional response, local subsequences, symbolic word counts, interval statistics. Each is strong somewhere and blind elsewhere. HIVE-COTE's insight is that those blind spots barely overlap, so combining the views beats tuning any one of them.
Crucially it is not a majority vote. Each component's probabilities are weighted by its own cross-validated accuracy raised to a power, so a component that is right on this dataset dominates one that is not — and the ensemble degrades gracefully when a member is simply unsuited.
__init__( self, components: Optional[List[Tuple[str, Any]]] = None, alpha: float = 4.0, cv: int = 3, random_state: Optional[int] = None, )
Overview
- Cross-validate every component on the training data.
-
Raise each accuracy to
alphato get its weight, so the gap between
- Fit every component on the full training set.
- At prediction time, take the weighted sum of the components'
Theory
With component c achieving cross-validated accuracy a_c and predicting P_c(y \mid x), the ensemble predicts
The exponent \alpha controls how sharply competence is rewarded. At \alpha = 0 every component counts equally; as \alpha \to \infty only the best survives. The published value of 4 sits deliberately between: a component 10% more accurate than another receives roughly 1.46 times the weight, enough to matter without letting one noisy cross-validation estimate take over.
The weights are estimated by cross-validation on the training set, not on the training predictions themselves — a component that memorises its training data would otherwise earn a weight of 1 and swamp the rest.
Parameters
components
(name, classifier) pairs. Defaults to one member per representation: MINIROCKET (convolutional), BOSS (dictionary), TimeSeriesForest (interval) and DTW-1NN (elastic distance).
alpha
cv
random_state
Attributes
components_
(name, fitted classifier) pairs.
weights_
component_accuracy_
classes_
fit.
Notes
Complexity. Fitting costs cv + 1 fits of every component, so it is the most expensive classifier here by a wide margin. Prediction costs one pass per component. This buys robustness, not speed: if a single model is wanted, use MiniRocketClassifier.
When to use — and be sceptical. The case for HIVE-COTE is that you cannot say in advance whether the signal is a motif, a frequency, a trend in one stretch, or a global shape. Measured across three synthetic problems built to favour different views, 120 train / 120 test:
============== ======== ========== ======== ======== ========== problem rocket dictionary interval distance HIVE-COTE ============== ======== ========== ======== ======== ========== localised 1.000 0.825 1.000 1.000 1.000 trend local motif, 1.000 0.783 0.958 1.000 1.000 random position frequency 1.000 0.983 1.000 0.983 0.992 under noise worst case 1.000 0.783 0.958 0.983 0.992 ============== ======== ========== ======== ======== ==========
The weighting works as designed — the dictionary component was down-weighted to 0.10-0.13 where it was weak and to 0.25 where all four were equal — and the ensemble tracks the best member without being told which it is. But MINIROCKET alone matched or beat it on every row, at roughly a quarter of the cost. That is the usual outcome when one component is already near-perfect: an ensemble insures against picking wrong, and insurance is a loss when you would have picked right.
So: fit the components individually first and read component_accuracy_. If one dominates, use it and keep the compute. Reach for the ensemble when the components disagree, when several are close, or when the deployment will see data unlike the sample you tuned on — the case the table above cannot show.
The published HIVE-COTE 2.0 uses four specific components with tuned internals. This class keeps the structure — cross-validated competence weighting over diverse representations — while letting the components be chosen, because the structure is what carries the benefit and a fixed component list would rot.
References
See Also
>>> import numpy as np
>>> from tuiml.algorithms.timeseries.classification import (
... HIVECOTEClassifier, MiniRocketClassifier, TimeSeriesForestClassifier)
>>> rng = np.random.default_rng(0)
>>> X = rng.normal(0, 1.0, (60, 80))
>>> y = np.arange(60) % 2
>>> X[y == 1, 20:50] += np.linspace(0, 4, 30)
>>> model = HIVECOTEClassifier(
... components=[("rocket", MiniRocketClassifier(n_features=840, random_state=0)),
... ("interval", TimeSeriesForestClassifier(n_estimators=50, random_state=0))],
... cv=2, random_state=0).fit(X, y)
>>> float((model.predict(X) == y).mean())
1.0
>>> sorted(model.component_accuracy_)
['interval', 'rocket']
Methods
fit
(self, X: np.ndarray, y: np.ndarray) -> 'HIVECOTEClassifier'
fit
(self, X: np.ndarray, y: np.ndarray) -> 'HIVECOTEClassifier'
Weight the components by cross-validated accuracy, then fit them.
Parameters
X
y
Returns
self
predict_proba
(self, X: np.ndarray) -> np.ndarray
predict_proba
(self, X: np.ndarray) -> np.ndarray
Return the weighted average of the components' probabilities.
Parameters
X
Returns
proba