Skip to main content

Core-SG

PyPI version Python versions Tests License

Core-SG - Core Support Graph for efficient computation of multiple MSTs and HDBSCAN-style hierarchy outputs over varying values of k. The recommended public workflow is the scikit-learn-style CoreSGClusterer, which builds reusable graph support at k_max and then extracts hierarchy artifacts for smaller values of k <= k_max without rebuilding the full structure each time.

In practice this means that CoreSGClusterer lets you fit once at k_max and reuse the result straight away for many smaller k values with little or no extra setup, while keeping familiar HDBSCAN-like outputs such as labels_, probabilities_, cluster_persistence_, condensed_tree_, single_linkage_tree_, and minimum_spanning_tree_.

Core-SG is ideal for exploratory multi-k density-based analysis; it is a practical approach for workflows where you want to compare smoothing levels on the same dataset and inspect graph-level artifacts, not only final labels.

Based on the papers:

Antonio Cavalcante Araujo Neto, Murilo Coelho Naldi, Ricardo J. G. B. Campello, and Jorg Sander. CORE-SG: Efficient Computation of Multiple MSTs for Density-Based Methods. In: 2022 IEEE 38th International Conference on Data Engineering (ICDE), IEEE, pp. 951-964. 2022.

Leland McInnes and John Healy. Accelerated Hierarchical Density Based Clustering. In: 2017 IEEE International Conference on Data Mining Workshops (ICDMW), IEEE, pp. 33-42. 2017.

R. Campello, D. Moulavi, and J. Sander. Density-Based Clustering Based on Hierarchical Density Estimates. In: Advances in Knowledge Discovery and Data Mining, Springer, pp. 160-172. 2013.

Documentation and project overview are available at https://midas-core-sg.github.io/core-sg/. Notebooks comparing Core-SG to HDBSCAN and illustrating the intended multi-k workflow are available in notebooks/.

What Core-SG is for

Core-SG is designed for workflows where you need to compare multiple k values on the same dataset and you care about graph-level artifacts, not only final labels. Most users should start with CoreSGClusterer; the lower-level reusable object acts behind the estimator and remains available for advanced internal workflows.

In practice, Core-SG helps you:

  • reuse support across repeated k evaluations
  • extract minimum spanning trees for different k
  • keep an HDBSCAN-like workflow (labels_, probabilities_, cluster_persistence_)
  • inspect tree artifacts (condensed_tree_, single_linkage_tree_, minimum_spanning_tree_)

Installing

Install from PyPI:

pip install core-sg

Install for local development:

pip install -e .

Install with development tooling:

pip install -e ".[dev]"

Dependencies:

  • numpy>=1.24,<3
  • pandas>=2.0
  • scikit-learn>=1.3
  • hdbscan>=0.8.39
  • pynndescent>=0.5.13

The package metadata, runtime dependencies, and optional extras are defined in pyproject.toml.

How to use Core-SG

Use CoreSGClusterer for the public user-facing workflow:

from sklearn.datasets import make_blobs
from core_sg import CoreSGClusterer

X, _ = make_blobs(
    n_samples=1000,
    n_features=10,
    centers=10,
    random_state=42,
)

clusterer = CoreSGClusterer(k_max=15)
clusterer.fit(X, k=10)

labels = clusterer.labels_

In this API, k_max is a constructor parameter because it defines the reusable support graph capacity and is visible through get_params() / set_params(). The first fit(X, y=None, *, k=...) builds the internal reusable Core-SG object once. Later calls to fit(...) reuse core_sg_ and only extract the hierarchy for the requested k. The decision to build or extract is based on whether core_sg_ already exists, not on whether k == k_max.

The k argument defines the specific clustering extraction exposed by labels_ and the other fitted attributes. If k=None, fit uses the fitted k_max_.

clusterer.fit(X, k=10)
labels_10 = clusterer.labels_

clusterer.fit(X, k=8)  # reuses the same core_sg_ object
labels_8 = clusterer.labels_

CoreSGClusterer exposes fitted artifacts for the selected k:

  • labels_
  • probabilities_
  • cluster_persistence_
  • condensed_tree_
  • single_linkage_tree_
  • minimum_spanning_tree_
  • k_
  • k_max_
  • core_sg_

fit_predict(X, y=None, *, k=...) is also available and returns labels_. predict(...) is intentionally not implemented yet because Core-SG does not currently define assignment semantics for unseen samples.

More details are available in doc/estimators.md.

Quick workflow

The most common usage pattern is:

  1. choose a largest neighborhood value k_max
  2. create CoreSGClusterer(k_max=...)
  3. call fit(X, k=...) for each k value that you want to compare
  4. inspect labels_, probabilities_, persistence values, and tree objects

Primary example

from sklearn.datasets import make_blobs
from core_sg import CoreSGClusterer

# Example dataset used only to illustrate the workflow.
X, _ = make_blobs(
    n_samples=1000,
    n_features=10,
    centers=10,
    random_state=42,
)

# Build reusable support once and expose outputs for k=10.
clusterer = CoreSGClusterer(k_max=15, metric="euclidean", p=2)
clusterer.fit(X, k=10)

# Read the HDBSCAN-style outputs exposed on the estimator.
labels = clusterer.labels_
probabilities = clusterer.probabilities_
cluster_persistence = clusterer.cluster_persistence_

# Later calls reuse the same internal core_sg_ object.
clusterer.fit(X, k=8)
labels_8 = clusterer.labels_

In this example, k_max=15 is the largest neighborhood size used during the initial fit, while k=10 and k=8 are extracted afterward from the same internal fitted support graph.

Key parameters

  • k_max: largest neighborhood size configured on CoreSGClusterer; this is the reference value that defines what smaller k values can later be extracted
  • k: neighborhood size passed to fit(X, k=...); it must satisfy 2 <= k <= k_max
  • metric: distance metric used to build the support graph
  • p: metric power parameter for distance families such as Minkowski
  • algorithm: choose "core-sg" for the default exact workflow or "score-sg" for the approximate anti-hub reinforced variant
  • no_noise: when True, applies an optional post-processing step so final labels do not remain at -1
  • noise_label_strategy: selects the post-processing strategy used when no_noise=True

Algorithms

algorithm="core-sg" is the default exact path. It builds dense pairwise distance information internally, constructs reusable support at k_max, and is the recommended first choice when the exact graph construction cost is acceptable. Because this path materializes dense pairwise distance information, it has a practical n_samples limitation as datasets grow.

algorithm="score-sg" is the approximate path. It uses PyNNDescent for approximate neighbor discovery, selects anti-hubs by directed in-degree, and uses random_state plus approx_knn_kwargs to control reproducibility and approximate-neighbor behavior. It can be useful when dense all-pairs distance construction is too expensive, but the resulting support graph may be disconnected for some data and parameter settings. In practice, this is the scalable path to try when the traditional exact CoreSG construction becomes limited by sample size.

Using the approximate variant

To enable the approximate anti-hub reinforced variant, set algorithm="score-sg":

clusterer = CoreSGClusterer(
    k_max=15,
    metric="euclidean",
    p=2,
    algorithm="score-sg",
    random_state=42,
)
clusterer.fit(X, k=10)

Extracting only an MST

The estimator exposes the current HDBSCAN-style MST wrapper after fit(...):

clusterer.fit(X, k=10)
mst = clusterer.minimum_spanning_tree_

Extracting hierarchy outputs

Call fit(X, k=...) when you want clustering outputs and tree artifacts similar to HDBSCAN:

clusterer.fit(X, k=10)

labels = clusterer.labels_
probabilities = clusterer.probabilities_
cluster_persistence = clusterer.cluster_persistence_

After hierarchy extraction, the current instance also exposes:

  • condensed_tree_
  • single_linkage_tree_
  • minimum_spanning_tree_

Reassigning noise labels

If you prefer a full assignment with no final -1 labels, keep the post-processing step enabled with no_noise=True (the default). The current strategy, noise_label_strategy="mst_label_propagation", updates only labels_ after hierarchy extraction and leaves the remaining hierarchy artifacts unchanged.

clusterer = CoreSGClusterer(
    k_max=15,
    metric="euclidean",
    p=2,
    no_noise=True,
    noise_label_strategy="mst_label_propagation",
)

clusterer.fit(X, k=10)
labels = clusterer.labels_

This is useful when you want a final label assignment for every point, while still preserving the original extracted hierarchy objects.

This post-processing flow is inspired by the density-connectivity label-propagation view discussed in:

  • Gertrudes, J. C., Zimek, A., Sander, J., and Campello, R. J. G. B.
    A unified view of density-based methods for semi-supervised clustering and classification.
    Data Mining and Knowledge Discovery, 33, 1894-1952 (2019).
    DOI: 10.1007/s10618-019-00651-1

Inspecting tree objects

If you need direct access to the current extracted hierarchy objects:

condensed_tree = clusterer.condensed_tree_
single_linkage_tree = clusterer.single_linkage_tree_
minimum_spanning_tree = clusterer.minimum_spanning_tree_

Accessing artifacts stored at k_max

The estimator keeps the internal reusable object at clusterer.core_sg_ for advanced inspection. Most users can stay on the estimator attributes above.

fitted = clusterer.core_sg_.get_fitted_hdbscan_objects(wrapped=True)

Returned keys:

  • labels_
  • probabilities_
  • cluster_persistence_
  • condensed_tree_
  • single_linkage_tree_
  • minimum_spanning_tree_

Direct cached wrappers at fit time:

  • condensed_tree_k_max_
  • single_linkage_tree_k_max_
  • minimum_spanning_tree_k_max_

Performance (multi-k workflows)

Core-SG is optimized for repeated k analysis, not necessarily for a single one-off run.

In notebooks/01-HDBSCAN_comparision.ipynb, for a synthetic setup (n=5000, d=2, centers=10) with repeated evaluations from k=30 down to k=10, cumulative runtime was:

  • Core-SG: 9.76 s
  • HDBSCAN: 32.44 s

This notebook demonstrates the intended tradeoff: higher upfront cost at k_max, lower cumulative cost when reusing across multiple smaller k values.

For larger sample sizes, prefer the approximate algorithm="score-sg" path. The exact algorithm="core-sg" path still relies on dense pairwise distance information and can become constrained by n_samples. The current ScoreSG benchmarks show substantially better cumulative runtime in repeated multi-k workloads: at n=50000, ScoreSG completes the tested 49-value workflow in 224.36 s, compared with 525.45 s for optimized exact CoreSG and 1342.44 s for optimized HDBSCAN best.

Known limitations

  • Core-SG provides strongest gains in repeated multi-k usage
  • exact algorithm="core-sg" can be limited by n_samples because it uses dense pairwise distance information
  • use algorithm="score-sg" when that dense exact construction becomes too costly and an approximate sparse-neighbor workflow is acceptable
  • for single k workflows, plain HDBSCAN may be simpler
  • current hierarchy pipeline still depends on HDBSCAN ecosystem components

Python version

Core-SG supports Python >=3.10.

Help and support

Contributing

Contributions are welcome. Please follow the contribution workflow in CONTRIBUTING.md, including the local test commands and development checks documented there.

Acknowledgment

Core-SG is structurally inspired by and technically based on the hdbscan ecosystem.

Core-SG also interoperates with internal hdbscan APIs to reconstruct and expose HDBSCAN-style hierarchy artifacts. See THIRD_PARTY_NOTICES.md for third-party attribution and the reproduced upstream BSD-3-Clause notice.

Citing

If Core-SG contributes to your research, publication, or technical results, please cite the following paper:

Antonio Cavalcante Araujo Neto, Murilo Coelho Naldi, Ricardo J. G. B. Campello, and Jorg Sander. CORE-SG: Efficient Computation of Multiple MSTs for Density-Based Methods. In: 2022 IEEE 38th International Conference on Data Engineering (ICDE), pp. 951-964, IEEE, 2022.

BibTeX:

@inproceedings{neto2022core_sg,
  author = {Neto, Antonio Cavalcante Araujo and Naldi, Murilo Coelho and Campello, Ricardo J. G. B. and Sander, Jorg},
  title = {{CORE-SG}: Efficient Computation of Multiple MSTs for Density-Based Methods},
  booktitle = {2022 IEEE 38th International Conference on Data Engineering (ICDE)},
  pages = {951--964},
  year = {2022},
  publisher = {IEEE},
  doi = {10.1109/ICDE53745.2022.00076},
  url = {https://doi.org/10.1109/ICDE53745.2022.00076}
}

License

Core-SG is licensed under the BSD 3-Clause License. See LICENSE for details.

This repository also includes third-party attribution and license information for hdbscan in THIRD_PARTY_NOTICES.md.

References

HDBSCAN

Release files for core-sg-mustache 0.4.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for core-sg-mustache 0.4.3
File Size Uploaded
core_sg_mustache-0.4.3.tar.gz 371.6 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for core-sg-mustache 0.4.3
File
core_sg_mustache-0.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ x86-64, Linux glibc 2.17+ x86-64 Details
core_sg_mustache-0.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.17+ x86-64, Linux glibc 2.28+ x86-64 Details
core_sg_mustache-0.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.28+ x86-64, Linux glibc 2.17+ x86-64 Details
core_sg_mustache-0.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.28+ x86-64, Linux glibc 2.17+ x86-64 Details

Total release size: 6.0 MB

Release files / core_sg_mustache-0.4.3.tar.gz

Download URL core_sg_mustache-0.4.3.tar.gz
Size 371.6 kB
Tags Source
SHA-256 checksum
How to use checksums
48f0cad958723d1580392de63822fe5ca6496b4270b4f1be3ca210420b656920
BLAKE2b-256 checksum
How to use checksums
9f14a8ab1e38ddfd0900475f93c1c07826c2bafbd6fc0883bc62bcce57914d1e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / core_sg_mustache-0.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL core_sg_mustache-0.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 1.4 MB
Tags CPython 3.13 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
5766f0acef76b10f26a97d53c21b764e22fbb4f6d01aeb54bfc3048ef5107eaf
BLAKE2b-256 checksum
How to use checksums
09c22eebaf44f03c9be92255c36bbf96fb557e403c6ba8a98db01d327829ac8d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / core_sg_mustache-0.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL core_sg_mustache-0.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 1.4 MB
Tags CPython 3.12 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
2980186b292f1423a394a596c9b95058dd15f2ef04e6c15acdbc4a546d483fe7
BLAKE2b-256 checksum
How to use checksums
2431f9a0061e2d412c63ccea3e9dc81dec92405651ee8a24b4856ddbdc55ae1a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / core_sg_mustache-0.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL core_sg_mustache-0.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 1.4 MB
Tags CPython 3.11 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
14de1a0fee70bba0495e9cd14a5fcd0aca6e3464b0cb2a30deb53a23b6cdc27a
BLAKE2b-256 checksum
How to use checksums
3f746ce8a9ff1bd51b418a793f995964e50a25849cba09df6d15cc34265ff362
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / core_sg_mustache-0.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL core_sg_mustache-0.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 1.4 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
1fb6cc6bfe47795326d94f5bc87d74d2ad4d95f576c7202ea6bc99083b8b341b
BLAKE2b-256 checksum
How to use checksums
a5e39de77a151b59e1d5c5b64b1eefec55529a5c08dabfbd65aab90f7e6e615b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release history Release notifications | RSS feed

0.4.4

5 release files

This release

0.4.3 This release

5 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page