Frozen HDBSCAN deployment¶
Design established before implementation for issue #97.
What an accepted environment means¶
An accepted query attaches to a density cluster in the frozen reference hierarchy, in the same per-element PCA coordinates used for selection. It does not create a cluster, change reference density, or establish a force-error bound. OOD means that this attachment is unsupported by the selected density partition. It is conditional on the reference library and its granularity.
The fitting engine and parameters remain sklearn HDBSCAN, Euclidean distance,
min_samples = min_cluster_size, EOM selection, allow_single_cluster=True,
and the existing cluster_selection_epsilon scan. Labels, medoids, noise
promotion, representative selection, and L/R/F retain their existing meaning.
No switch to the contrib fitting engine is required.
Density attachment rule¶
Freeze each reference point’s core distance: distance to its
mth nearest reference point, including itself, wherem = min_samplesin sklearn. Reconstruct these distances with the same KD-tree path as sklearn’s dense Euclidean fit, avoiding a numerically different brute-force calculation.For a novel query, its core distance is the distance to its
(m-1)th nearest reference point: the query supplies its own zero-distance self. Queries never count each other, so batching cannot change density.Find the reference point minimizing mutual reachability
max(query_core, reference_core, Euclidean_distance). Search the whole reference, with bounded distance blocks. Resolve equal minima by reference row order. Convert this attachment distance to lambda (inverse distance; zero distance gives positive infinity).Cap attachment lambda at the anchor’s departure lambda in the condensed tree. Climb to the ancestor present at that density, then resolve its selected ancestor using the actual sklearn fitted labels, including epsilon merges. Reject an attachment outside a selected cluster. At a non-root cluster’s birth boundary, use the parent (strict birth test).
A selected root needs an additional support boundary because it has no birth split. Use sklearn’s own root membership rule: attachment lambda must reach the root’s maximum outgoing lambda when epsilon is zero, or
1 / cluster_selection_epsilonotherwise. The latter is specifically sklearn’s selected-root density cut, not a general OOD radius.
This is Atom-HiFi’s frozen hierarchy attachment policy, not a claim of
equivalence to refitting HDBSCAN with queries appended or to contrib
approximate_predict. Reference core distances and hierarchy stay frozen.
In particular, a query equal to a reference row is still evaluated as a
query; training-label reproduction at density ties is not guaranteed.
Selection groups versus deployment groups¶
ClusterFit.n_groups continues to count all coverable groups. A promoted
noise representative keeps its group and noise_derived=True for selection
and inspection. It does not become a supported deployment target.
n_deployable_groups counts the selected density groups with prediction state;
an all-noise fit is a valid predictor with zero deployment targets and rejects
every query.
ClusterFit.classify returns two lists with n_groups + 1 slots. For HDBSCAN,
both lists contain accepted indices in backend-local density slots and rejected
indices in the trailing slot; promoted slots are empty. There is no forced
label for rejection. KMeans and DECAF retain their existing second-list
unconditional assignment convention. Consumers needing OOD always use the
first list’s trailing slot. Saved-Judge CSV output maps accepted labels through
the saved permutation and element offset; rejected HDBSCAN rows have
group_id=-1, ood=1.
Persistence and compatibility¶
Persist versioned numeric prediction state, the PCA projection, reference core distances, condensed-tree ancestry/departure scales, and selected-node-to-local label mapping. No fitted sklearn estimator or neighbor index is needed at deployment. Loading and predicting must not fit HDBSCAN or PCA. The sklearn private-tree adapter is confined to fitting and must validate its reconstructed partition against sklearn’s labels before exposing a predictor.
A legacy HDBSCAN fit without this state remains usable for inspection and selection. Classification raises an actionable error requesting an explicit new fit from the original reference descriptors; loading never repairs it by refitting. Selection caches are not deployable Judges.
On the scan path the existing PCA projection may be lazy. Judge.save
materializes it explicitly before writing an HDBSCAN Judge. Generic pickle
serialization and joblib transport do not compute it. This keeps repeated
scan fits cheap while ensuring the saved-Judge prediction path needs only a
matrix multiplication. The numeric hierarchy state has its own schema version;
unknown schemas fail classification rather than silently changing semantics.
Prediction uses exact distances to the reference, so work scales as
N_query × N_reference × embedding_dimension. Distance blocks bound working
memory; queries can also be streamed in external batches with identical results.
The hierarchy and core distances are stored once. At float64, the reference
array shares the embedder’s storage and pickle memoization avoids a second copy.
Run the saved-Judge example¶
Use the feature checkout explicitly; do not reinstall the package in the shared environment. The output directory must be new.
cd /work1/SKTable_Injector/atom-hifi-hdbscan-deploy
export PYTHONPATH="$PWD"
export PYTHONDONTWRITEBYTECODE=1
export OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 MKL_NUM_THREADS=1
/home/yhsong/.virtualenvs/test/bin/python -u scripts/example_hdbscan_deployment.py \
--epsilon 0.05 --output-dir /tmp/hdbscan-saved-judge-example
# A separate process loads the saved fit and classifies its reference descriptors.
/home/yhsong/.virtualenvs/test/bin/python -u scripts/predict_ood.py \
--judge /tmp/hdbscan-saved-judge-example/judge_final.pkl \
--desc /tmp/hdbscan-saved-judge-example/reference_desc.pkl \
--lib /tmp/hdbscan-saved-judge-example/reference.xyz \
--out /tmp/hdbscan-saved-judge-example/prediction-reloaded.csv
The example uses 20 checked-in Ni–O structures (317 atoms), generates ED-SOAP,
fits a fixed HDBSCAN operating point and the N//2 microstate reference, saves
the refined Judge/mapping, and compares CSV versus patient OOD after loading.
Its summary.json includes selection and deployment counts separately. These
are reference-only checks, not a held-out accuracy or lifetime study.
Integrating the later HDBSCAN lifetime arm¶
Use branch
feat/native-hdbscan-deploymentin a separate checkout. The implementation baseline is2d5544ec6231bdbe1bc3996fc8f6f9c099346f45. Keep the active KMeans checkout and shared environment unchanged:git -C /work1/SKTable_Injector/atom-hifi fetch origin feat/native-hdbscan-deployment git -C /work1/SKTable_Injector/atom-hifi worktree add \ -b study/hdbscan-lifetime /work1/SKTable_Injector/atom-hifi-hdbscan-lifetime \ origin/feat/native-hdbscan-deployment cd /work1/SKTable_Injector/atom-hifi-hdbscan-lifetime export PYTHONPATH="$PWD" export PYTHONDONTWRITEBYTECODE=1 /home/yhsong/.virtualenvs/test/bin/python -c \ 'import atom_hifi; print(atom_hifi.__file__)'
The printed module path must be this HDBSCAN checkout. Record its exact
git rev-parse HEADin the arm’s manifest. The validated environment is Python 3.12, sklearn 1.8.0 and NumPy 2.2.2; no dependency change is required. The existing NumPy >=2.4 positive-epsilon fitting guard remains in force.For each lifetime reference interval, fit a new reference-only HDBSCAN Judge using the arm’s established descriptor configuration, focus atoms, PCA path, microstate reference, scan and operating-point rule. Set
cluster.backend: hdbscan, the intendedcluster.min_cluster_size, andoutput.save_judge: true; give the arm a freshpaths.output_dir. HDBSCAN keeps thec_factor/epsilon axis; a KMeans k orlambda_openis not an HDBSCAN operating point. Keep reference/query membership and ordering matched to the study protocol. Query descriptors must not enter fitting or operating-point selection. Do not reuse KMeans clustering/selection caches or promote its saved Judge by changing a backend name. Shared descriptor inputs may be read only when their configuration and row mapping match.Save after
judge.apply_refined_group_ids()when constructing Judges directly; normalplot_final_fitalready does this. Save the associated mapping CSV. A legacy HDBSCAN Judge orel_fit_cache.npzlacks deployment state and requires an explicit reference refit in the new output directory.Load that interval’s Judge once and freeze it for every later query batch:
import numpy as np from atom_hifi import Judge judge = Judge.load("HDBSCAN_ARM/reference_interval/judge_final.pkl") fit = judge.cluster_per_el[element] slots, _ = fit.classify(fit.embedder.embed(query_descriptors)) labels = np.full(len(query_descriptors), -1, dtype=int) for backend_id, rows in enumerate(slots[:-1]): labels[rows] = backend_id ood_count = len(slots[-1]) accepted = labels >= 0 global_ids = np.full(len(labels), -1, dtype=int) order = judge.group_order_per_el[element].local_of_old global_ids[accepted] = ( order[labels[accepted]] + judge.group_id_offset[element])
Alternatively use
scripts/predict_ood.py --judge ... --desc ... --lib ...on each batch; it applies the same mapping. Mode B (--config ... --xyz ...) computes descriptors with the reference run’s descriptor settings.Report atom OOD over all queried focus atoms. Keep
fit.n_groups,fit.n_density_groups, promoted count, andfit.n_deployable_groupsseparate. If reporting visited-state coverage, use deployable density groups as the denominator; an all-noise reference has zero such states, so state coverage is undefined, not 100%. Its atom OOD is 100% for a nonempty query. Promoted groups retain their selection costs and L/R/F contribution. Group IDs are local to one fitted reference and cannot be matched across intervals as chemical identities.Run this bounded example and the focused deployment tests before launching the arm under the study’s own resource and stopping rules. No PIT-WATER lifetime run is part of this implementation. Integration into
mainstill requires explicit approval.
Sources and scope¶
sklearn HDBSCAN: fitting parameters and self-inclusive
min_samples.sklearn tree implementation: condensation, selected labels, and root membership rule.
Contrib prediction: frozen-tree attachment as distinct from reclustering.
Epsilon prediction issue: why deployment must preserve the fitted merged namespace.
This feature provides deployment semantics. It does not validate HDBSCAN’s scientific usefulness for PIT-WATER or launch its lifetime arm.