@kanaries/ml
API Reference/Clustering

HDBSCAN

Learn what HDBSCAN does, when to use it, and how to run HDBScan in JavaScript or TypeScript with @kanaries/ml for browser and Node.js applications.

Algorithm overview

HDBSCAN (Hierarchical Density-Based Spatial Clustering of Applications with Noise) finds clusters of varying density and identifies noise points without forcing every observation into a cluster. Unlike DBSCAN, it does not depend on a single global eps radius: it builds a density hierarchy and extracts the most stable clusters from it, so a tight cluster and a sparse cluster can be recovered in the same run. Choose it when:

  • Your clusters have significantly different densities (the classic DBSCAN failure mode).
  • You do not know an exact cluster count in advance.
  • Outlier/noise detection is important for your downstream workflow.

The HDBScan class in @kanaries/ml is a full implementation aligned with scikit-learn's sklearn.cluster.HDBSCAN:

  1. Core distances — the distance from each point to its min_samples-th nearest neighbor (counting the point itself, as scikit-learn does).
  2. Mutual reachability — pairwise distances max(core_a, core_b, d(a, b)).
  3. Minimum spanning tree — Prim's algorithm on the mutual reachability graph.
  4. Condensed tree and stability extraction — the single linkage hierarchy is condensed by min_cluster_size, and flat clusters are selected with the Excess of Mass (EOM) stability criterion.

Quick start

HDBScan in Python vs JavaScript / TypeScript

If you searched for "HDBScan in JavaScript" or "HDBScan in TypeScript", this section maps the familiar scikit-learn call to the equivalent @kanaries/ml usage for browser and Node.js runtimes.

Python
scikit-learn
from sklearn.cluster import HDBSCAN

X = [[0, 0], [0.1, 0.2], [5, 5], [5.2, 5.1], [9, 0]]

model = HDBSCAN(min_cluster_size=2)
labels = model.fit_predict(X)
JavaScript / TypeScript
@kanaries/ml
import { Clusters } from '@kanaries/ml';

const X = [[0, 0], [0.1, 0.2], [5, 5], [5.2, 5.1], [9, 0]];

const model = new Clusters.HDBScan(2);
const labels = model.fitPredict(X);

Quick JavaScript example

import { Clusters } from '@kanaries/ml';

const X = [[0, 0], [0.1, 0.2], [5, 5], [5.2, 5.1], [9, 0]];

const model = new Clusters.HDBScan(2);
const labels = model.fitPredict(X);

Detailed API reference

constructor(
    min_cluster_size: number = 5,
    min_samples: number | null = null,
    cluster_selection_epsilon: number = 0.0,
    metric: Distance.IDistanceType = 'euclidean',
    allow_single_cluster: boolean = false
)
  • min_cluster_size — the smallest group of points that counts as a cluster. Splits producing a side smaller than this are treated as points falling out of the parent cluster. This is the main tuning knob.
  • min_samples — controls how conservative the density estimate is (the k used for core distances, counting the point itself). Defaults to min_cluster_size. Larger values declare more points noise.
  • cluster_selection_epsilon — an extraction threshold (not a DBSCAN eps): selected clusters born below this distance are merged upward until their parent's birth distance exceeds it. Leave at 0.0 (the default, matching scikit-learn) unless you want to prevent micro-clusters from splitting.
  • metric — any distance supported by the Distance module.
  • allow_single_cluster — when true, the hierarchy root may be selected, allowing the whole dataset to form one cluster.

fitPredict(samplesX: number[][]): number[] returns cluster labels. Noise points are marked as -1.

getLabels(): number[] returns the labels from the last fitPredict call.

getProbabilities(): number[] returns the cluster membership strength of each sample in [0, 1]; noise points have probability 0.

const hdb = new Clusters.HDBScan(8);
const labels = hdb.fitPredict(X);
const probabilities = hdb.getProbabilities();

Implementation workflow

  1. Scale features so distance comparisons are meaningful.
  2. Fit the model and inspect cluster labels plus noise assignments.
  3. Tune min_cluster_size first; use min_samples to adjust how aggressively sparse points are declared noise.

JavaScript deployment notes

  • Use this class when cluster count is unknown, densities vary across clusters, and you expect some observations to remain noise.
  • The implementation builds a dense pairwise distance matrix (O(n²) memory and time), so it is suited to datasets up to a few thousand points. In browser workflows, run it off the main thread for larger inputs.
  • Results match Python sklearn.cluster.HDBSCAN labels on the same data and parameters.