Cluster evaluation metrics in SciPy - Time & Space Complexity
Start learning this pattern below
Jump into concepts and practice - no test required
When we evaluate clusters, we use metrics to check how good the grouping is.
We want to know how the time to calculate these metrics grows as data size grows.
Analyze the time complexity of the following code snippet.
from scipy.spatial.distance import pdist
from scipy.cluster.hierarchy import linkage, fcluster
# data is a 2D array with n samples
D = pdist(data, metric='euclidean') # pairwise distances
Z = linkage(D, method='ward') # hierarchical clustering
labels = fcluster(Z, t=3, criterion='maxclust') # cluster labels
# Calculate silhouette score
from scipy.spatial.distance import cdist
# silhouette calculation
silhouette_vals = []
for i in range(len(data)):
same_cluster = data[labels == labels[i]]
other_clusters = data[labels != labels[i]]
a = cdist(data[i:i+1], same_cluster).mean() # mean intra-cluster distance
b = cdist(data[i:i+1], other_clusters).min() # nearest-cluster distance
silhouette_vals.append((b - a) / max(a, b))
silhouette_score = sum(silhouette_vals) / len(silhouette_vals)
This code computes clusters and then calculates the silhouette score to evaluate clustering quality.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Loop over each data point to compute silhouette values.
- How many times: Once per data point, so n times.
- Inside the loop, distance calculations happen over subsets of data, which can be up to size n.
As the number of data points grows, the number of distance calculations grows quickly.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 100 distance calculations |
| 100 | About 10,000 distance calculations |
| 1000 | About 1,000,000 distance calculations |
Pattern observation: The operations grow roughly with the square of the input size.
Time Complexity: O(n²)
This means if you double the data points, the time to compute the silhouette score roughly quadruples.
[X] Wrong: "Calculating cluster evaluation metrics like silhouette score is fast and scales linearly with data size."
[OK] Correct: Because silhouette score requires comparing each point to many others, the number of comparisons grows much faster than the number of points.
Understanding how cluster evaluation metrics scale helps you explain trade-offs when working with big data and choosing the right methods.
What if we used a sampling method to calculate silhouette score on only a subset of points? How would the time complexity change?
Practice
Solution
Step 1: Understand the role of true labels
Adjusted Rand Index requires true labels to compare clusters, so it is not suitable without labels.Step 2: Identify metrics for unknown labels
Silhouette Score measures how well clusters are separated without needing true labels.Final Answer:
Silhouette Score -> Option BQuick Check:
Unknown labels = Silhouette Score [OK]
- Confusing Adjusted Rand Index as label-free
- Choosing accuracy score which needs labels
- Using mean squared error for clustering
Solution
Step 1: Check common library modules
Silhouette score is available in sklearn.metrics module, not in scipy.cluster or spatial.distance.Step 2: Verify import syntax
The correct import is from sklearn.metrics import silhouette_score.Final Answer:
from sklearn.metrics import silhouette_score -> Option DQuick Check:
Correct import = sklearn.metrics [OK]
- Importing from scipy.cluster directly
- Using scipy.spatial.distance for silhouette_score
- Confusing hierarchy module with vq
from scipy.cluster.vq import kmeans, vq, whiten import numpy as np data = np.array([[1, 2], [1, 4], [1, 0], [10, 2], [10, 4], [10, 0]]) whitened = whiten(data) centroids, _ = kmeans(whitened, 2) cluster_labels, _ = vq(whitened, centroids) from sklearn.metrics import silhouette_score score = silhouette_score(whitened, cluster_labels) print(round(score, 2))
Solution
Step 1: Understand the code flow
The code whitens data, runs kmeans for 2 clusters, assigns labels, then calculates silhouette score.Step 2: Interpret silhouette score meaning
Data clearly forms two groups; silhouette score is around 0.75 indicating good cluster separation.Final Answer:
0.75 -> Option AQuick Check:
Well-separated clusters ≈ 0.75 silhouette [OK]
- Expecting silhouette score of 1.0 always
- Confusing whitened data with original scale
- Misreading cluster labels
from scipy.spatial.distance import davies_bouldin_score labels = [0, 0, 1, 1] data = [[1, 2], [1, 4], [10, 2], [10, 4]] score = davies_bouldin_score(data, labels) print(score)
Solution
Step 1: Check import source
Davies-Bouldin score is in sklearn.metrics, not scipy.spatial.distance.Step 2: Validate data and labels
Data and labels lengths match and data as list works with sklearn, so no error there.Final Answer:
Importing davies_bouldin_score from wrong module -> Option CQuick Check:
Correct import is sklearn.metrics [OK]
- Importing from scipy.spatial.distance
- Assuming data must be numpy array
- Thinking Davies-Bouldin needs true labels
Solution
Step 1: Identify metrics needing true labels
Adjusted Rand Index compares predicted clusters with true labels to measure similarity.Step 2: Exclude label-free metrics
Silhouette, Davies-Bouldin, and Calinski-Harabasz do not use true labels for evaluation.Final Answer:
Adjusted Rand Index -> Option AQuick Check:
True vs predicted labels = Adjusted Rand Index [OK]
- Using silhouette score with true labels
- Confusing Davies-Bouldin as label-based
- Choosing Calinski-Harabasz for label comparison
