BOSS - Bag-of-SFA-Symbols dictionary classification.
Classes
class algorithms.timeseries.classification.dictionary.BOSSClassifier(TimeSeriesClassifier)
BOSS classifies by which symbolic patterns a series contains.
BOSS turns each series into a bag of words. Every sliding window is reduced to its lowest Fourier coefficients, those are quantised into letters, and the resulting words are counted. Two series are similar when they contain the same patterns in similar proportions — regardless of where those patterns occur.
The low-pass step is what distinguishes it: keeping only low-frequency coefficients discards high-frequency detail, which is where much of the noise lives.
__init__( self, window_size: float = 0.25, word_length: int = 8, alphabet_size: int = 4, norm_mean: bool = True, n_neighbors: int = 1, )
Overview
- Slide a window over each series and take the DFT of each window.
-
Keep the lowest
word_lengthcoefficients, dropping the DC term and
-
Quantise each coefficient into one of
alphabet_sizeletters, using
- Drop a word identical to its predecessor, so a slowly varying stretch
- Count the surviving words per series and classify by nearest neighbour
Theory
For histograms B_a, B_b the BOSS distance is
The restriction to words present in a makes it asymmetric: d(a, b) \neq d(b, a) in general. That is deliberate, not an oversight — a reference series carrying extra noise words should not be penalised for them when the query does not contain them.
Numerosity reduction — collapsing runs of identical consecutive words — matters more than it looks. Without it a long flat stretch dominates the histogram purely because it is long, and the representation stops describing structure and starts describing duration.
Parameters
window_size
(0, 1] is a fraction of the series length. Sets the time scale of the patterns BOSS can see.
word_length
alphabet_size
norm_mean
n_neighbors
Attributes
breakpoints_
histograms_
vocabulary_
fit.
classes_
fit.
Notes
Complexity. Fitting is O(n L \ell) for n series of length L and word length \ell — the sliding DFT is advanced by the momentary Fourier transform in the shared C++ kernel tuiml._cpp_ext.timeseries.sfa_transform, so each window costs O(\ell) rather than O(w \ell). Prediction is O(m n V) for a vocabulary of size V, since it is a nearest neighbour search over histograms.
When to use — and where it does not win. BOSS represents a series by what patterns it contains and how often, discarding where they occur. That is a genuinely different view from every other member of this family, and it shows up where position-invariant content is the signal. Measured on two synthetic problems, 160 train / 160 test:
================================= ====== ========== ========= ===== ========= problem BOSS MiniRocket Shapelet DTW Euclidean ================================= ====== ========== ========= ===== ========= motif count (2 vs 6 repeats 0.844 1.000 0.956 0.950 0.588 at random positions) frequency under heavy noise 0.775 0.944 0.831 0.656 0.869 (sd 3.0) ================================= ====== ========== ========= ===== =========
Read that honestly: BOSS beats a Euclidean neighbour decisively when position varies (0.844 against 0.588) and beats DTW under noise, but MiniRocketClassifier beat it on both. If you want one classifier, use MINIROCKET. BOSS earns its place as a diverse component — a symbolic, frequency-domain view that fails differently from convolutional and elastic methods, which is precisely why every strong meta-ensemble in the literature includes a dictionary member. Combine it through VotingClassifier.
Its cost also grows with the training set, like DTWNeighborsClassifier and unlike MINIROCKET, so it suits small to moderate datasets.
The published method ensembles many (window_size, word_length, norm_mean) settings and keeps those within 92% of the best cross-validated accuracy. This class implements a single parameter set, which is weaker; on the noise problem above, sweeping window sizes from 25 to 150 and word lengths from 4 to 10 moved accuracy only from 0.775 to 0.781, so the gap to MINIROCKET there is not a tuning artefact.
References
See Also
>>> import numpy as np
>>> from tuiml.algorithms.timeseries.classification import BOSSClassifier
>>> rng = np.random.default_rng(0)
>>> t = np.linspace(0, 8 * np.pi, 160)
>>> # Two classes distinguished by frequency, buried in heavy noise.
>>> slow = np.sin(t) + rng.normal(0, 0.8, (40, 160))
>>> fast = np.sin(3 * t) + rng.normal(0, 0.8, (40, 160))
>>> X = np.vstack([slow, fast])
>>> y = np.array([0] * 40 + [1] * 40)
>>> model = BOSSClassifier(window_size=40, word_length=6).fit(X, y)
>>> bool((model.predict(X) == y).mean() > 0.9)
True
Methods
fit
(self, X: np.ndarray, y: np.ndarray) -> 'BOSSClassifier'
fit
(self, X: np.ndarray, y: np.ndarray) -> 'BOSSClassifier'
Fit the quantisation breakpoints and build training histograms.
Parameters
X
y
Returns
self
transform
(self, X: np.ndarray) -> np.ndarray
transform
(self, X: np.ndarray) -> np.ndarray
Return the word-count histogram of each series.
Parameters
X
Returns
histograms
predict_proba
(self, X: np.ndarray) -> np.ndarray
predict_proba
(self, X: np.ndarray) -> np.ndarray
Return the neighbour vote share for each class.
Parameters
X
Returns
proba