Skip to content
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
602ada2
SpectralClustering estimator
aamijar Oct 21, 2025
287a009
rng_state instead of seed
aamijar Nov 11, 2025
81c54b4
Update to 26.02 (#7493)
AyodeAwe Nov 17, 2025
a6d4721
Revert "Forward-merge release/25.12 into main" (#7495)
AyodeAwe Nov 17, 2025
65bba07
refactor
aamijar Nov 20, 2025
6db0615
remove unused
aamijar Nov 20, 2025
37a5077
input dataset api
aamijar Nov 21, 2025
f2c8d51
add pytests
aamijar Nov 21, 2025
1f4a8e0
refactor
aamijar Nov 21, 2025
8600479
add docstrings
aamijar Nov 21, 2025
340bf45
docs and readme
aamijar Nov 21, 2025
ac6d6d4
style
aamijar Nov 21, 2025
ee6eec3
style
aamijar Nov 22, 2025
365c7c3
Use strict priority in CI conda tests (#7524)
bdice Nov 22, 2025
c1dbb5c
add spectral_clustering function to init
aamijar Nov 24, 2025
8e918c8
default='nearest_neighbors'
aamijar Nov 24, 2025
cc8c900
fix test_pickle and param names tests
aamijar Nov 25, 2025
241223e
Update python/cuml/cuml/cluster/spectral_clustering.pyx
aamijar Nov 25, 2025
74585ca
UserWarning on conversion
aamijar Nov 25, 2025
dcd3ae8
code example
aamijar Nov 25, 2025
54f5b2c
remove delayed import
aamijar Nov 25, 2025
f1d6808
Update python/cuml/cuml/cluster/spectral_clustering.pyx
aamijar Nov 25, 2025
0c4889c
eigen_tol='auto' default
aamijar Nov 25, 2025
ed313b9
revert to nearest_neighbors
aamijar Nov 25, 2025
ac6de1e
clean test case
aamijar Nov 25, 2025
a78ad24
shared params test
aamijar Nov 25, 2025
19bb555
comprehensive tests
aamijar Nov 25, 2025
200b4a9
fix conflicts
aamijar Nov 25, 2025
d33e7a4
fix conflicts
aamijar Nov 25, 2025
427d1c4
fix conflicts
aamijar Nov 25, 2025
5c9e23a
fix conflicts
aamijar Nov 25, 2025
54cde75
fix conflicts
aamijar Nov 25, 2025
a3878fc
fix conflicts
aamijar Nov 25, 2025
0728b0c
fix conflicts
aamijar Nov 25, 2025
a9654cc
fix conflicts
aamijar Nov 25, 2025
10b487d
fix conflicts
aamijar Nov 25, 2025
78e89dd
fix conflicts
aamijar Nov 25, 2025
e1a3d50
Improve the hypothesis property-based testing.
csadorf Nov 25, 2025
3b07729
Add test for spectral clustering convergence failure
csadorf Nov 25, 2025
4c8e4ce
add notes docstring
aamijar Nov 25, 2025
ed594f3
Update python/cuml/cuml/cluster/spectral_clustering.pyx
aamijar Nov 25, 2025
bfbd5bb
Update python/cuml/cuml/cluster/spectral_clustering.pyx
aamijar Nov 25, 2025
241e2ff
refactor
aamijar Nov 25, 2025
9a2818e
rename
aamijar Nov 25, 2025
3c9316a
return type docstring
aamijar Nov 25, 2025
222a029
compare y_sklearn and y_cuml score
aamijar Nov 25, 2025
f74949d
Merge branch 'release/25.12' into spectral-clustering
aamijar Nov 25, 2025
8f69c01
Raise a nicer exception on conversion issues.
csadorf Nov 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ repo](https://github.com/rapidsai/notebooks-contrib).
| | Hierarchical Density-Based Spatial Clustering of Applications with Noise (HDBSCAN) | |
| | K-Means | Multi-node multi-GPU via Dask |
| | Single-Linkage Agglomerative Clustering | |
| | Spectral Clustering | |
| **Dimensionality Reduction** | Principal Components Analysis (PCA) | Multi-node multi-GPU via Dask|
| | Incremental PCA | |
| | Truncated Singular Value Decomposition (tSVD) | Multi-node multi-GPU via Dask |
Expand Down
5 changes: 4 additions & 1 deletion cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,10 @@ if(BUILD_CUML_CPP_LIBRARY)
endif()

if(all_algo OR spectralclustering_algo)
target_sources(cuml_objs PRIVATE src/spectral/spectral.cu src/spectral/spectral_embedding.cu)
target_sources(
cuml_objs PRIVATE src/spectral/spectral.cu src/spectral/spectral_clustering.cu
src/spectral/spectral_embedding.cu
)
endif()

if(all_algo OR svm_algo)
Expand Down
79 changes: 79 additions & 0 deletions cpp/include/cuml/cluster/spectral_clustering.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

#include <raft/core/device_coo_matrix.hpp>
#include <raft/core/device_mdspan.hpp>
#include <raft/core/resources.hpp>

namespace ML {
namespace SpectralClustering {

/**
* @brief Spectral clustering parameters
*/
struct params {
/** @brief Number of clusters to find */
int n_clusters;
/** @brief Number of eigenvectors to use */
int n_components;
/** @brief Number of times to run k-means with different seeds */
int n_init;
/** @brief Number of neighbors for kNN graph construction */
int n_neighbors;
/** @brief Tolerance for the eigensolver */
float eigen_tol;
/** @brief Random seed for reproducibility */
uint64_t seed;
};

/**
* @brief Perform spectral clustering on input dataset by constructing
* a k-nearest neighbors graph
*
* @param[in] handle cuML resources handle
* @param[in] config Parameters for spectral clustering
* @param[in] dataset Input dataset (row-major)
* @param[out] labels Cluster labels for each sample
*/
void fit_predict(raft::resources const& handle,
params config,
raft::device_matrix_view<float, int, raft::row_major> dataset,
raft::device_vector_view<int, int> labels);

/**
* @brief Perform spectral clustering on a precomputed connectivity graph
* using COO sparse matrix view
*
* @param[in] handle cuML resources handle
* @param[in] config Parameters for spectral clustering
* @param[in] connectivity_graph COO sparse matrix view of the connectivity graph
* @param[out] labels Cluster labels for each sample
*/
void fit_predict(raft::resources const& handle,
params config,
raft::device_coo_matrix_view<float, int, int, int> connectivity_graph,
raft::device_vector_view<int, int> labels);

/**
* @brief Perform spectral clustering on a precomputed connectivity graph
* using separate vector views for COO components
*
* @param[in] handle cuML resources handle
* @param[in] config Parameters for spectral clustering
* @param[in] rows Row indices of the COO sparse matrix
* @param[in] cols Column indices of the COO sparse matrix
* @param[in] vals Values of the COO sparse matrix
* @param[out] labels Cluster labels for each sample
*/
void fit_predict(raft::resources const& handle,
params config,
raft::device_vector_view<int, int> rows,
raft::device_vector_view<int, int> cols,
raft::device_vector_view<float, int> vals,
raft::device_vector_view<int, int> labels);

} // namespace SpectralClustering
} // namespace ML
80 changes: 80 additions & 0 deletions cpp/src/spectral/spectral_clustering.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/

#include <cuml/cluster/spectral_clustering.hpp>

#include <raft/core/device_coo_matrix.hpp>
#include <raft/core/device_mdspan.hpp>
#include <raft/core/resources.hpp>

#include <cuvs/cluster/spectral.hpp>
#include <cuvs/preprocessing/spectral_embedding.hpp>

namespace cuvs::cluster::spectral {
struct params;
} // end namespace cuvs::cluster::spectral

namespace ML {
namespace SpectralClustering {

cuvs::cluster::spectral::params to_cuvs(ML::SpectralClustering::params& config)
{
cuvs::cluster::spectral::params cuvs_params;
cuvs_params.n_clusters = config.n_clusters;
cuvs_params.n_components = config.n_components;
cuvs_params.n_init = config.n_init;
cuvs_params.n_neighbors = config.n_neighbors;
cuvs_params.tolerance = config.eigen_tol;
cuvs_params.rng_state = raft::random::RngState(config.seed);

return cuvs_params;
}

void fit_predict(raft::resources const& handle,
params config,
raft::device_matrix_view<float, int, raft::row_major> dataset,
raft::device_vector_view<int, int> labels)
{
int n_samples = dataset.extent(0);

// Create connectivity graph from dataset using spectral embedding helpers
auto graph = raft::make_device_coo_matrix<float, int, int, int>(handle, n_samples, n_samples);

cuvs::preprocessing::spectral_embedding::params embed_params;
embed_params.n_neighbors = config.n_neighbors;
embed_params.seed = config.seed;

cuvs::preprocessing::spectral_embedding::helpers::create_connectivity_graph(
handle, embed_params, dataset, graph);

// Call spectral clustering with the connectivity graph
ML::SpectralClustering::fit_predict(handle, config, graph.view(), labels);
}

void fit_predict(raft::resources const& handle,
params config,
raft::device_coo_matrix_view<float, int, int, int> connectivity_graph,
raft::device_vector_view<int, int> labels)
{
cuvs::cluster::spectral::fit_predict(handle, to_cuvs(config), connectivity_graph, labels);
}

void fit_predict(raft::resources const& handle,
params config,
raft::device_vector_view<int, int> rows,
raft::device_vector_view<int, int> cols,
raft::device_vector_view<float, int> vals,
raft::device_vector_view<int, int> labels)
{
auto connectivity_graph_view = raft::make_device_coo_matrix_view<float, int, int, int>(
vals.data_handle(),
raft::make_device_coordinate_structure_view<int, int, int>(
rows.data_handle(), cols.data_handle(), labels.size(), labels.size(), vals.size()));

ML::SpectralClustering::fit_predict(handle, config, connectivity_graph_view, labels);
}

} // namespace SpectralClustering
} // namespace ML
7 changes: 7 additions & 0 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,13 @@ HDBSCAN

.. autofunction:: cuml.cluster.hdbscan.approximate_predict

Spectral Clustering
-------------------
.. autoclass:: cuml.cluster.SpectralClustering
:members:

.. autofunction:: cuml.cluster.spectral_clustering


Dimensionality Reduction and Manifold Learning
==============================================
Expand Down
1 change: 1 addition & 0 deletions python/cuml/cuml/cluster/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ set(cython_sources "")
add_module_gpu_default("agglomerative.pyx" ${agglomerative_algo} ${cluster_algo})
add_module_gpu_default("dbscan.pyx" ${dbscan_algo} ${cluster_algo})
add_module_gpu_default("kmeans.pyx" ${kmeans_algo} ${cluster_algo})
add_module_gpu_default("spectral_clustering.pyx" ${cluster_algo})

add_subdirectory(hdbscan)

Expand Down
4 changes: 4 additions & 0 deletions python/cuml/cuml/cluster/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@
from cuml.cluster.dbscan import DBSCAN
from cuml.cluster.hdbscan import HDBSCAN
from cuml.cluster.kmeans import KMeans
from cuml.cluster.spectral_clustering import (
SpectralClustering,
spectral_clustering,
)
Loading
Loading