mojolearn.AgglomerativeClustering#
- class mojolearn.AgglomerativeClustering(n_clusters=2, *, metric='euclidean', connectivity='pairwise', linkage='single', c=15, memory=None, compute_full_tree='auto', distance_threshold=None, compute_distances=False, prediction_data=False)[source]#
Bases:
objectAgglomerative hierarchical clustering.
Builds a merge tree bottom-up and cuts it into
n_clustersclusters or atdistance_threshold. Supports scikit-learn’s single, complete, average and Ward linkages, connectivity matrices and per-merge distances. Input is a dense array, converted to float32.Two defaults differ from scikit-learn’s and change the result:
linkageis ‘single’ (scikit-learn: ‘ward’) andconnectivityis ‘pairwise’, the full dense graph (scikit-learn’s None). cuML’sAgglomerativeClusteringalso defaults to single linkage, but to ‘knn’ connectivity, which is not available here; passconnectivity='pairwise'explicitly when moving cuML code.Label integers can differ from scikit-learn’s for the same partition: compare partitions (for example with
adjusted_rand_score), not the label values. Likewise,children_rows can differ in order and orientation from scikit-learn’s when merge distances tie.- Parameters:
n_clusters (int or None, default 2) – Number of clusters, between 1 and the number of samples. Must be None when
distance_thresholdis set.metric (str, default ‘euclidean’) – One of ‘euclidean’, ‘l2’, ‘l1’, ‘manhattan’, ‘cityblock’, ‘cosine’ or ‘precomputed’ (
Xis then a square distance matrix). Any other value, including a callable, raises NotImplementedError. Ward linkage requires ‘euclidean’ or ‘l2’; ‘cosine’ rejects rows that are all zeros.connectivity (‘pairwise’, None, array-like, sparse matrix or callable, default ‘pairwise’) – ‘pairwise’ and None both mean no constraint (the full dense graph). A matrix of shape (n_samples, n_samples), or a callable that returns one from
X, restricts merges to its nonzero entries, as in scikit-learn. ‘knn’ raises NotImplementedError.linkage ({‘single’, ‘complete’, ‘average’, ‘ward’}, default ‘single’) – Merge criterion.
c (int, default 15) – Kept for cuML compatibility, where it tunes the ‘knn’ graph. Any other value raises NotImplementedError.
memory (None) – Must be None; anything else raises NotImplementedError.
compute_full_tree (‘auto’ or bool, default ‘auto’) – With a connectivity matrix, whether to build the full tree or stop at
n_clusters, with scikit-learn’s ‘auto’ rule. Without one the full tree is always built. Must be True or ‘auto’ whendistance_thresholdis set.distance_threshold (float or None, default None) – Merge distance at or above which clusters are no longer merged. Exactly one of
n_clustersanddistance_thresholdmust be set.compute_distances (bool, default False) – Store the merge distances in
distances_even withoutdistance_threshold.prediction_data (bool, default False) – Keep a copy of the training rows so that
predictandsavework. Only single linkage with the ‘euclidean’ or ‘l2’ metric can predict.
- Variables:
labels_ (Array of shape (n_samples,), int32) – Cluster of each training row.
n_clusters_ (int) – Number of clusters found.
children_ (Array of shape (n_merges, 2), int32) – The merges, one per row; values below n_samples are rows, larger values are earlier merges. n_merges is n_samples - 1 for a full tree.
distances_ (Array of shape (n_merges,), float32) – Merge distances. Set only with
distance_thresholdorcompute_distances=True.n_leaves_ (int) – Number of leaves (n_samples).
n_connected_components_ (int) – Connected components of the connectivity graph. A constrained fit with more than one warns and completes the graph, as scikit-learn does.
n_boruvka_rounds_ (int) – Not a scikit-learn attribute: the number of Boruvka rounds of the single-linkage euclidean fit without a connectivity matrix; -1 on other fits and on a CPU-only install.
n_features_in_ (int) – Number of features seen in
fit.
Examples
>>> import numpy as np, mojolearn >>> X = np.random.default_rng(0).random((1000, 8), dtype=np.float32) >>> model = mojolearn.AgglomerativeClustering(n_clusters=4, prediction_data=True).fit(X) >>> labels = model.predict(X[:10])
- __init__(n_clusters=2, *, metric='euclidean', connectivity='pairwise', linkage='single', c=15, memory=None, compute_full_tree='auto', distance_threshold=None, compute_distances=False, prediction_data=False)[source]#
Methods
fit(X[, y])Build the merge tree of
Xand cut it into clusters.fit_predict(X[, y])Fit the model on
Xand return the training labels.load(path)Load a model written by
save.predict(X)Label new rows with the cluster of their nearest training row.
save(path)Save the model's prediction data to
path.- fit(X, y=None)[source]#
Build the merge tree of
Xand cut it into clusters.- Parameters:
X (array-like of shape (n_samples, n_features)) – Dense training rows, or a square distance matrix with
metric='precomputed'. Converted to float32. Sparse input raises NotImplementedError.y (ignored) – Present for scikit-learn compatibility.
- Returns:
self (AgglomerativeClustering) – The fitted estimator.
- Raises:
TypeError – If
prediction_datais not a bool.NotImplementedError – If
Xis sparse.ValueError – If there are fewer than 2 rows,
n_clustersexceeds the number of rows,Xcontains NaN or infinity, a precomputed or connectivity matrix has the wrong shape, ormetric='cosine'meets an all-zero row. With single linkage, the euclidean metric, no connectivity matrix and no merge distances requested, more than 46,340 rows also raises (the dense graph would overflow), except infastmode on Apple with at most 64 features.
- Warns:
UserWarning – If a connectivity matrix has more than one connected component.
- fit_predict(X, y=None)[source]#
Fit the model on
Xand return the training labels.- Parameters:
X (array-like of shape (n_samples, n_features)) – Dense training rows, or a square distance matrix with
metric='precomputed'.y (ignored) – Present for scikit-learn compatibility.
- Returns:
labels (Array of shape (n_samples,), int32) – The fitted
labels_.
- predict(X)[source]#
Label new rows with the cluster of their nearest training row.
Neither scikit-learn nor cuML has this method. For single linkage, the closest cluster to a new row is the one containing its nearest training row (squared euclidean distance); ties go to the lowest cluster label, then the lowest training index. A training row predicts its own fitted label unless an exact duplicate of it was cut into a cluster with a lower label, which happens only when
n_clustersexceeds the number of distinct rows.Only single linkage with the ‘euclidean’ or ‘l2’ metric can predict, and only after a fit with
prediction_data=True(or a model loaded withload).- Parameters:
X (array-like of shape (n_queries, n_features)) – Rows to label, with the number of features seen in
fit.- Returns:
labels (Array of shape (n_queries,), int32) – Cluster of each row, numbered as
labels_.- Raises:
ValueError – If the model is not fitted or was fitted without
prediction_data=True.NotImplementedError – If the linkage or metric has no prediction rule.
- save(path)[source]#
Save the model’s prediction data to
path.Writes an npz file with the training rows,
labels_,n_clusters_,n_features_in_,n_leaves_, the metric and the numeric mode.children_andn_boruvka_rounds_are not saved, so the same fit writes the same bytes on every device; a loaded model has neither attribute. A loaded model predicts, including on a CPU-only install.- Parameters:
path (str or path-like) – File to write.
- Raises:
RuntimeError – If the model is not fitted.
ValueError – If it was fitted without
prediction_data=True.NotImplementedError – If the linkage or metric has no prediction rule.
- classmethod load(path)[source]#
Load a model written by
save.The loaded model can
predict. Every array is read at its saved dtype and never cast.- Parameters:
path (str or path-like) – File written by
save.- Returns:
model (AgglomerativeClustering) – The loaded model.
- Raises:
ValueError – If the file is not a saved AgglomerativeClustering or its arrays are inconsistent.