HBOS - Histogram-Based Outlier Score.
Classes
HBOS scores outliers by per-feature histogram density.
__init__( self, n_bins: int | str = 'auto', strategy: str = 'equal_frequency', contamination: float = 0.1, tol: float = 1e-12, )
Overview
- Build a univariate histogram of each feature over the training data,
- Normalise each histogram to a density.
- Score a point by summing \log(1 / \text{density}) over
Theory
With \hat{p}_j the fitted density of feature j, the score is
which is, up to sign and constants, the negative log-likelihood under a naive density model that assumes independent features. That assumption is exactly the trade: it buys linear-time scoring and costs the ability to see any anomaly defined by a combination of otherwise ordinary values.
Bin choice matters more than any other decision here. Equal-width bins follow the classic formulation but degrade badly on skewed or heavy-tailed features, where nearly all mass lands in one bin; equal-frequency (dynamic) bins adapt to the empirical distribution and are the better default on real tabular data.
Parameters
n_bins
'auto' uses the Birge-Rozenholc rule :math:`\lceil n^{1/3} \rceil` clipped to [5, 100], which grows with the sample size without overfitting small data.
strategy
contamination
tol
Attributes
edges_
density_
n_bins_
threshold_
n_features_in_
fit.
Notes
Complexity. Training is O(n d \log n) for equal-frequency binning (a sort per feature) or O(n d) for equal-width. Prediction is O(m d \log b) for b bins. Memory is O(d b) — unlike ECOD, the training data is not retained, so the fitted model is tiny regardless of n. Binning and lookup run in the shared C++ kernel tuiml._cpp_ext.stats.
When to use. Reach for HBOS when speed dominates, when the model must stay small, or as a cheap first stage in a cascade. Its blind spot is correlated features: on data where anomalies are joint rather than marginal, prefer IsolationForestDetector or LocalOutlierFactorDetector. Against ECODDetector, HBOS is faster to score and far smaller in memory, but needs its bin count chosen and is not invariant to monotone transforms.
References
See Also
>>> import numpy as np
>>> from tuiml.algorithms.anomaly import HBOSDetector
>>> rng = np.random.default_rng(0)
>>> X = np.vstack([rng.normal(0, 1, (300, 4)), rng.normal(9, 1, (15, 4))])
>>> detector = HBOSDetector(contamination=0.05).fit(X)
>>> int((detector.predict(X)[-15:] == -1).sum())
15
>>> detector.n_bins_
7
Methods
fit
(self, X: np.ndarray, _y: Optional[np.ndarray]=None) -> 'HBOSDetector'
fit
(self, X: np.ndarray, _y: Optional[np.ndarray]=None) -> 'HBOSDetector'
Fit one histogram per feature.
Parameters
X
_y
Returns
self
feature_contributions
(self, X: np.ndarray) -> np.ndarray
feature_contributions
(self, X: np.ndarray) -> np.ndarray
Return each feature's contribution to a sample's outlier score.
Parameters
X
Returns
contributions