Concepts / Evaluating Clustering Algorithms

Evaluating Clustering Algorithms

DBSCAN stands for density-based spatial clustering of applications with noise.

  • Programming

Starting With the Smallest Possible Run

DBSCAN stands for density-based spatial clustering of applications with noise. It is a clustering algorithm that groups points by how crowded their neighborhoods are, and it can also flag points that belong to no group at all. This article begins with code rather than theory, because the most useful way to understand DBSCAN is to run it and look at what comes back.

python
Notes on the code
  • DBSCAN() with no arguments uses the default eps and min_samples values
  • fit_predict performs both the fitting and the labeling in one call
  • np.unique lists each distinct label once, so the output summarizes the whole result

What do you think happens?

If the printed output is [-1], what has DBSCAN done with the data?

Reveal answer
Answer:

Every point was labeled as noise, so DBSCAN formed no clusters at all.

The label -1 is reserved for noise. A result containing only -1 means no point satisfied the density rule, so no cluster was born. The source treats this as a signal to adjust parameters, not as evidence about the structure of the data.

How DBSCAN Decides Without a Cluster Count

Many clustering methods ask you to choose the number of clusters before they run. DBSCAN does not. It looks for points that sit in crowded regions of the feature space, where many data points lie close together. These crowded regions are called dense regions. The core idea is that a cluster is a dense region of data, and clusters are separated from one another by regions that are comparatively empty.

DBSCAN has exactly two parameters, and every label it returns is a consequence of them. The first is eps, a distance. Two points count as close when the distance between them is eps or less. The second is min_samples, a count. It is the minimum number of data points that must lie within eps of a given point before that point counts as belonging to a dense region.

Key point

eps controls what counts as close. min_samples controls the minimum size of a dense group and how many points end up labeled as noise. Neither parameter sets a number of clusters; the number of clusters is an outcome.

There is a trade-off in exchange for this flexibility. The source notes that DBSCAN is somewhat slower than agglomerative clustering and k-means, although it still scales to relatively large datasets.

Core, Boundary, and Noise Points

After DBSCAN finishes, every point falls into exactly one of three kinds. Core points are dense enough to satisfy the min_samples rule: they have at least min_samples points within eps. Boundary points lie within distance eps of a core point but do not satisfy the rule themselves. Noise points are the rest; they belong to no cluster and receive the label -1.

eps neighborhooddistance that definesclosenessCore sampleat least min_samples pointswithin epsBoundary pointwithin eps of a core, notcore itselfNoise pointbelongs to no cluster,label -1counts neighbors withinlies within eps ofno core nearby
Given eps and min_samples, how do I tell which points are core samples, which are boundary points, and which are noise, and how do they relate within a neighborhood?

The distinction between core and boundary points matters for reproducibility. Running DBSCAN repeatedly on the same dataset always gives the same clustering of core points, and the same points are always labeled as noise. A boundary point, however, may sit next to core samples from more than one cluster. Its membership then depends on the order in which points are visited. The source points out that there are usually only a few boundary points, so this dependence is rarely important in practice.

Tracing How One Cluster Grows

DBSCAN does not look at all points at once. It works through the dataset one unvisited point at a time, deciding for each point whether it starts a new cluster, joins an existing one, or is noise. Follow one starting point through this flow. If it lacks enough neighbors, it is set aside as noise and the algorithm moves on. If it has enough neighbors, a cluster is born, and growth proceeds outward through core samples only. A neighbor that is not itself a core sample joins the cluster but does not extend it further.

Unvisited pointEnough neighborswithin eps?Start new clusterVisit next neighborNeighbor is a coresample?Extend clusterthrough itLabel as noise (-1)Join as boundarypointexaminenoyescollect neighborscheckyesnorepeat until nothing reachable
When a core point is found, which neighboring points are pulled into the same cluster, and how does the cluster keep growing until nothing more can be reached?

Read the flowchart as a loop. A cluster grows only when a newly reached point is itself a core sample. A boundary point is reached and labeled, but its own neighbors are not used to pull in further points. This is the mechanism behind the core and boundary distinction from the previous section.

Reading the Labels Array

DBSCAN labels each data point either as noise or as a member of a cluster. Cluster members receive non-negative integer labels such as 0, 1, and 2. Noise points receive the label -1. A result of [-1] therefore means every point was classified as noise and the algorithm formed no clusters. The position of each label in the returned array matches the position of the input point it describes, so labels[i] is the label for the i-th row of the data.

A useful way to think about -1 is that it is not a cluster at all. It is a bin for points that DBSCAN could not place in any density-based group. Because -1 is negative, it cannot be counted directly with a function that only accepts non-negative integers, so the source shifts every label up by one before counting. The noise bin then lands at index 0 of the count array, and the first number in the count is always the number of noise points.

python
Notes on the code
  • labels + 1 shifts every label so that the noise bin is non-negative
  • counts[0] is the noise bin because -1 has become 0
  • counts[1:] gives the size of each real cluster in label order
  • Common mistake

    Treating -1 as a real cluster when counting or plotting

    Why it fails

    The label -1 marks points that belong to no cluster. Including it as an ordinary group distorts the cluster count and sizes.

    Do this instead

    Handle -1 explicitly, for example by masking it out before summarizing clusters.

  • Common mistake

    Using -1 as a direct index into another array

    Why it fails

    Python interprets -1 as the last element, so the lookup silently pulls the wrong row.

    Do this instead

    Select noise with a boolean mask such as labels == -1 rather than indexing with the label values.

Changing eps and min_samples

The source uses a two-moons dataset, which consists of two interleaved half-circles. The data is rescaled to zero mean and unit variance before clustering, and DBSCAN runs with its default settings. With those defaults, the source reports that DBSCAN finds the two half-circles and separates them, which is the desired result. The default eps is 0.5.

What do you think happens?

If eps is lowered from 0.5 to 0.2 on the same data, how many clusters do you expect?

  • One cluster

  • Two clusters, as before

  • Many small clusters

Reveal answer
Answer:

Eight clusters, which the source describes as clearly too many.

A smaller eps means fewer points count as close, so dense regions break into fragments. Raising eps to 0.7 does the opposite and produces one cluster. Changing one number changes the whole answer.

eps 0.5 defaulttwo half-circles foundeps 0.2eight clusterseps 0.7one clusterdecrease epsincrease eps
If eps increases or decreases, how do the resulting cluster labels change, and which clusters merge or split?
Worked example

Why lowering min_samples alone was not enough

When every point comes back as noise, which parameter should change first, and what does the source's experiment show?

  1. 1
    Identify the two adjustable parameters

    eps sets the neighborhood size around each point. min_samples sets how many points are needed before a group counts as a cluster.

  2. 2
    Change min_samples first

    Lowering min_samples lets smaller groups qualify, which seems like the direct fix for an all-noise result.

  3. 3
    Observe the labels

    In the source experiment, lowering min_samples alone did not produce any clusters.

  4. 4
    Increase eps as well

    Because the neighborhood also has to reach far enough, eps must increase along with min_samples to form clusters.

Result

Change one parameter, observe the labels, and decide what the result tells you before changing the next parameter.

A single trial is rarely enough to choose eps. The source loops over several eps values with min_samples held constant and prints the clusters present and the size of each one. Read that sweep from both directions. At the low end, noise dominates. Near the middle, many small clusters sit alongside a large noise group. At the high end, one big cluster accounts for most of the data. The source observes that there is never more than one large cluster at any setting.

Noise Points as Outliers

Once DBSCAN has produced a result with both noise and clusters, the noise points can be pulled out and examined. The source uses a boolean mask, labels == -1, to select the images DBSCAN labeled as noise. Those images did not fit any dense group. Finding the odd one out in this way is called outlier detection, and DBSCAN can perform it, because noise is simply the set of points that do not belong to a cluster.

python
Notes on the code
  • labels == -1 produces a boolean mask over the input points
  • Indexing with the mask keeps only the rows DBSCAN labeled as noise

In the source's eps=15 run, DBSCAN produced 27 noise points. Because there were so few, it was practical to inspect every one. Comparing them with typical faces suggested why each was labeled as noise. One image showed a person drinking from a glass, several showed people wearing hats, one had a hand in front of the face, and others had odd angles or crops that were too close or too wide. The source adds that some of these issues can be fixed by better cropping, while others, such as hats or hands in front of faces, must simply be handled by any algorithm applied to this data.

DBSCAN Versus k-Means Cluster Sizes

The source then applies k-means to the same PCA data. The key difference is that k-means must be told how many clusters to produce, and it partitions every point into one of them. With n_clusters set to 10, the source reports cluster sizes ranging from 64 to 386, which it describes as relatively similarly sized. This differs strongly from the DBSCAN result, where cluster sizes were very uneven and noise was present.

AspectDBSCANk-means
Cluster countEmerges from eps and min_samplesChosen in advance with n_clusters
Every point assigned?No, points can be noise labeled -1Yes, every point is partitioned
Cluster sizesCan be very unevenRelatively even in the source example
Outlier handlingFlags far points as noiseForces far points into a cluster
SpeedSomewhat slower, still scalesGenerally faster per the source

DBSCAN and k-means on the same PCA-transformed faces dataset

The source also notes a consequence of k-means partitioning everything. Points far from a cluster center are still forced into that cluster, so their assignments can look arbitrary. Because k-means has no concept of noise, it cannot flag these points the way DBSCAN does. A larger number of clusters might reveal finer distinctions, but more clusters also make manual inspection harder.

To ask whether two methods agree, the source uses the adjusted Rand index, written ARI. It runs agglomerative clustering with 10 clusters and computes the ARI between its labels and the k-means labels. An ARI of 0.13 indicates the two partitions have little in common. The source reads this as expected, because points far from k-means centers have little in common with each other.

Finding Where a Result Goes Wrong

Most unexpected clustering results trace back to one of a few places in the workflow: the parameter values, the interpretation of labels, or the assumption that a clustering reflects real structure. Work through the pipeline in order and check each stage before blaming the algorithm. The earliest stage that looks wrong is usually where the surprise begins.

  1. 1
    Load the data and confirm its shape and feature units.
  2. 2
    Scale the features. The source's two-moons example rescales the data to zero mean and unit variance before clustering; features measured in different units can otherwise distort the distances DBSCAN relies on.
  3. 3
    Choose eps and min_samples, starting from the defaults and changing one parameter at a time.
  4. 4
    Fit the model and read the labels, checking for -1 explicitly.
  5. 5
    Count clusters and noise, then inspect the points in each group against what you expect.

Predicting Labels Before Running the Code

MEDIUM

A DBSCAN run on your data returns mostly -1 labels, with a few small groups. Before changing anything, predict whether lowering eps or raising min_samples would increase or decrease the number of noise points, and explain your reasoning in terms of the core, boundary, and noise definitions.

Hints
  • Recall that eps defines which points count as close.
  • Recall that min_samples defines how many neighbors a point needs to be core.
  • Think about what happens to a boundary point when its core neighbors stop qualifying.
HARD

Write a short loop that tries three eps values with min_samples held constant, and prints the number of noise points and the size of each cluster. Predict the direction of change in noise count before you run it, then check the output.

Hints
  • Use labels == -1 to count the noise points.
  • Use np.unique with return_counts=True to get the cluster sizes.

Key Takeaways From the Evaluation

  • DBSCAN builds clusters from dense regions, not from a preset cluster count, and it can flag points as noise.
  • eps defines closeness and min_samples defines how many neighbors make a point core; together they govern every label.
  • Core points give stable clusters, boundary points can depend on visit order, and noise points carry the label -1.
  • When a result looks wrong, check the parameters and the handling of -1 labels before concluding that the algorithm failed.

At a glance

  • DBSCAN groups points by density and proximity and does not need the number of clusters set in advance.
  • eps sets the distance for closeness and min_samples sets the neighbor count needed for a dense region, so both parameters shape every label.
  • Core samples, boundary points, and noise points are the three kinds of result; noise points carry the label -1.
  • Noise points can be selected with labels == -1 as one form of outlier detection.
  • An unexpected result usually traces back to parameter values, label handling, or scaling, so check those stages first.

Related concepts

More concepts starting with E