induwara.lk
induwara.lkAI · Clustering metrics

Silhouette Score Calculator

Paste your data points and cluster labels to get the silhouette score, the per-cluster means, and the full a(i)/b(i)/s(i) working for every point — with misassigned points flagged. Matches scikit-learn silhouette_score. No signup, nothing uploaded.

By Induwara AshinsanaUpdated Jun 11, 2026
Silhouette score calculator

One point per line. Coordinates separated by commas or spaces.

One label per point, same order. Numbers or names (e.g. 0, 0, 1).

Decimals
Examples
Silhouette score
0.9448
Strong structure

Clusters are dense and clearly separated. This labelling holds up well.

Points
4
Clusters
2
Dimensions
2
Flagged
0

Cross-check. The mean of all per-point s(i) is 0.9448; computed independently as the size-weighted average of the per-cluster means it is 0.9448. The two aggregations reconcile, as they must.

Per-cluster mean silhouette

ClusterSizeMean s(i)Reading
020.9289Strong structure
120.9606Strong structure

Per-sample silhouette

PointClustera(i)b(i)Nearests(i)
#100.50997.072510.9279
#200.50997.280110.9300
#310.28287.315700.9613
#410.28287.037000.9598

Worked formula for one point

Point #1 = [5, 2] · cluster 0 · euclidean (l2) distance
mean dist → cluster 0 = 0.5099= a(i)
mean dist → cluster 1 = 7.0725= b(i) (nearest)
s(i) = (b − a) / max(a, b) = (7.0725 0.5099) / 7.0725 = 0.9279

Method: a(i) = mean intra-cluster distance, b(i) = nearest other-cluster mean, s(i) = (b − a) / max(a, b); score = mean s(i). Matches scikit-learn silhouette_score. Sources: scikit-learn docs, Rousseeuw (1987), Kaufman & Rousseeuw (1990). Nothing leaves this page.

How it works

The silhouette score measures how well each point fits its assigned cluster compared with the nearest neighbouring cluster. It needs no ground-truth labels, which makes it an internal validity index — the standard way to judge a k-means, hierarchical, or DBSCAN result, and to compare different choices of k. It was introduced by Peter Rousseeuw in 1987 and is what scikit-learn returns from silhouette_score.

For a point i in cluster C, the tool computes three quantities:

  1. a(i) — cohesion. The mean distance from i to every other point in its own cluster: a(i) = (1 / (|C| − 1)) · Σ d(i, j) over j in C, j ≠ i. Lower is better — the point is close to its cluster-mates.
  2. b(i) — separation. For every other cluster C′, take the mean distance from i to all of its points, then keep the smallest: b(i) = min over C′ of (1 / |C′|) · Σ d(i, j). That nearest rival cluster is the one the point would most plausibly belong to instead.
  3. s(i) — the silhouette. s(i) = (b(i) − a(i)) / max(a(i), b(i)), which falls between −1 and 1. Near 1 means the point is far from other clusters and snug in its own; near 0 means it sits on a boundary; negative means it is closer to a neighbour and probably misassigned. A point alone in its cluster gets s(i) = 0 by convention.

The overall score is the plain average of s(i) across all N points. Distance d(·,·) is Euclidean √(Σ (xₖ − yₖ)²) by default — matching scikit-learn — or Manhattan Σ |xₖ − yₖ| when selected. The computation is O(N²) in the number of points, which stays instant in the browser for the few-thousand-point inputs this tool accepts. As a credibility check it also recomputes the score a second way — as the size-weighted average of the per-cluster mean silhouettes — and confirms the two routes agree. To read the result, common practice (Kaufman & Rousseeuw, 1990) treats above 0.70 as strong structure, 0.51–0.70 as reasonable, 0.26–0.50 as weak or artificial, and 0.25 or below as no substantial structure.

Worked examples

Well-separated clusters (1-D) — points 1, 2, 10, 11; labels 0, 0, 1, 1

  1. Point 1 (cl 0): a = |1−2| = 1; b = mean(9, 10) = 9.5; s = 8.5/9.5 = 0.8947
  2. Point 2 (cl 0): a = 1; b = mean(8, 9) = 8.5; s = 7.5/8.5 = 0.8824
  3. Point 10 (cl 1): a = 1; b = 8.5; s = 0.8824
  4. Point 11 (cl 1): a = 1; b = 9.5; s = 0.8947
  5. Score = (0.8947 + 0.8824 + 0.8824 + 0.8947)/4 = 0.8885 → strong structure

One misassigned point (2-D) — A = {(0,0),(0,1)}, B = {(0,2),(20,20)}

  1. (0,0) A: a = 1; b = mean(2, √800=28.2843) = 15.1421; s = 0.9340
  2. (0,1) A: a = 1; b = mean(1, √761=27.5862) = 14.2931; s = 0.9300
  3. (0,2) B: a = √724 = 26.9072; b = mean(2, 1) = 1.5; s = −0.9443 (flagged)
  4. (20,20) B: a = 26.9072; b = mean(28.2843, 27.5862) = 27.9353; s = 0.0368
  5. Score = (0.9340 + 0.9300 − 0.9443 + 0.0368)/4 = 0.2391 → weak / questionable

Single-point cluster (s = 0 convention) — points 0, 0.5, 10; labels 0, 0, 1

  1. Point 0 (cl 0): a = 0.5; b = dist to 10 = 10; s = 9.5/10 = 0.9500
  2. Point 0.5 (cl 0): a = 0.5; b = 9.5; s = 9/9.5 = 0.9474
  3. Point 10 (cl 1): only member of its cluster ⇒ s = 0 (scikit-learn rule)
  4. Score = (0.9500 + 0.9474 + 0)/3 = 0.6325 → reasonable structure

Frequently asked questions

Sources & references

Related tools

Rate this tool
Be the first to rate

Comments & feedback

Spotted a bug or want an improvement? Tell us — our team reviews every comment, and good ideas get built. Comments are public and anonymous.

Found a bug, edge case, or want to suggest an improvement?

Email me at [email protected] — most fixes ship within 24 hours.