Concepts / DBSCAN and Clustering Evaluation

DBSCAN and Clustering Evaluation

The first number in the bincount result is always the number of noise points. Reading that one number tells you how much of the dataset DBSCAN could not place in a dense group.

  • Programming

A Surprising Result on Face Data

This article begins with a result that most learners do not expect. A short script runs DBSCAN on a dataset of face images and prints the unique labels that come back. The printed output is [-1]. Many learners read that as a clustering that failed in some strange way, or as a list with a stray value in it. The source treats this output as the starting point of the lesson, because once you understand why the output looks this way, DBSCAN's parameters and the process of evaluating a clustering result become much easier to reason about.

The data has already been transformed with PCA before clustering. The source describes this PCA representation as a more semantic description of the face images than raw pixels, and notes that it makes computation faster. The clustering runs on that transformed data, which the code refers to as X_pca. Every label and every cluster size in this article describes the PCA-transformed faces, not the original pixel values.

Reading the Labels DBSCAN Returns

DBSCAN gives every data point a label. Each point is either a member of a cluster or noise. Cluster members receive non-negative integer labels: 0, 1, 2, and so on. Noise points receive the label -1. Because of this rule, the label list tells you which groups exist and whether any points were left out, but it does not tell you how many points belong to each group.

point 1label -1noiseno clusterpoint 2label 0cluster 0dense grouppoint 3label 0cluster 1dense grouppoint 4label 1point 5label -1-1-1001
Each point receives one integer label. Points labeled -1 are noise and belong to no cluster; points with non-negative labels belong to the cluster with that number.
python
Output (expected)
[-1]
Notes on the code
  • DBSCAN() with no arguments uses every default parameter value
  • fit_predict fits the model and assigns a label to each point in one call
  • np.unique prints each distinct label once, so the list shows which labels exist and nothing about how many points carry each one

In the source run, the output [-1] means that the only label present is -1. Every point was classified as noise, and the algorithm formed no clusters at all. The source states this directly: all of the data was labeled as noise.

Counting Points per Label

A label list is only a summary. A result that contains both -1 and 0 tells you that a cluster exists, but it does not tell you how large that cluster is or how much of the data is noise. To answer those questions, you count. The source counts labels with np.bincount, which takes a list of non-negative integers and returns how many times each integer appears. Because bincount does not accept negative numbers, the source adds 1 to every label before counting. This shifts the noise label from -1 to 0, so the noise bin lands at index 0 of the count array.

python
Notes on the code
  • labels + 1 moves -1 to 0, which makes the noise label countable
  • The first entry of the count array is always the number of noise points
  • Each later entry is the size of one cluster, in label order
Key point

The first number in the bincount result is always the number of noise points. Reading that one number tells you how much of the dataset DBSCAN could not place in a dense group.

How eps and min_samples Shape the Result

When every point comes back as noise, the source identifies two parameters to consider. The eps parameter controls the size of the neighborhood around each point, so raising it lets each point see more of its surroundings. The min_samples parameter controls how many points are needed before a group counts as a cluster, so lowering it allows smaller groups to qualify. Both parameters push in the same direction: each one makes it easier for points to end up in a group rather than being left as noise. The source's experiment shows that the two do not have equal effect, as the subsections below explain.

label list[-1]label list-1 and non-negative labelsnoise countall pointsnoise countfewer pointsclustersnoneclustersone or moreraise epsraise epsraise eps
Before adjustment, the default run labels every point as noise. After raising eps, points can gather into clusters, so the label list gains non-negative values alongside -1.

The before and after columns above describe the change in qualitative terms. The source does not give a general rule for predicting the exact number of clusters from a parameter value, so use the counting method from the previous section to verify each change rather than assuming it.

Noise Points as Outliers

A noise point is a point DBSCAN could not place in any density-based group. The reason is that it has too few neighbors within the eps distance to form a dense group on its own or to join one. Because noise is simply the set of points that do not belong to a cluster, DBSCAN can be used to find the odd ones out. Finding them in this way is called outlier detection.

python
Output (expected)
27
Notes on the code
  • labels == -1 is a boolean mask that is True only for noise points
  • Indexing X_pca with the mask pulls out just the noise points
  • The output 27 matches the number of noise points the source reported for the eps=15 run
In the real world

The source looked at the 27 noise images one by one. One image showed a person drinking from a glass. Several showed people wearing hats. One had a hand in front of the face. Others had odd angles or crops that were too close or too wide. Comparing them with typical faces suggested why each was labeled as noise. The source adds that some of these problems 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.

Sweeping eps Across Several Values

A single trial is rarely enough to choose eps. The source loops over several eps values while holding min_samples constant, and prints both the clusters present and the size of each one. The loop is the most direct way to see how the result changes as the neighborhood grows. The source notes that the search range should sit between 15 and the default of 0.5, which signals that the useful setting lies in the lower part of the range that was tried.

python
Notes on the code
  • The eps values are an illustrative spread from the default upward, not the exact sweep the source ran
  • min_samples is held constant across the loop, so only eps changes
  • counts[0] gives the noise size and the remaining entries give each cluster size

Read the sweep from both directions. At the low end, the output shows that noise dominates. Near the middle, the output contains many small clusters 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.

Worked example

Interpreting a single sweep result

A sweep prints a count array in which the first entry is large and the remaining entries are small. What does this result suggest about the eps value used?

  1. 1
    Read the noise count

    The first entry of the bincount result is the number of noise points, so a large first entry means most points are noise.

  2. 2
    Compare the cluster sizes

    The remaining entries are cluster sizes. If they are small, no group has gathered much of the data.

  3. 3
    Locate the setting on the sweep

    This pattern matches the low end of the sweep, where noise dominates, so the eps value is probably too small for this data.

  4. 4
    Decide the next step

    Raise eps and repeat the count, rather than interpreting the small clusters as the structure of the faces.

Result

The eps value is likely too small. The next step is to increase eps and recount, checking whether one large cluster and some noise remain.

The sweep is also an evaluation result, not only a parameter result. The source reads the pattern, in which there is never more than one large cluster, as a sign that the faces do not split into several very distinct kinds. Instead, they are roughly equally similar or dissimilar to one another. That reading is a hypothesis to test by inspecting the groups, not a proven fact about the faces.

Where an Unexpected Result First Appears

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. The flowchart below follows the faces experiment from the first fit to the final inspection. In that sequence, the first place an unexpected result appears is usually the label check, which is why the lesson begins there.

PCA dataX_pcaFit DBSCANfit_predictInspect labelsnp.uniqueOnly -1?all noiseAdjust epsthen min_samplesCount per labelnp.bincountInspect groupsjudge meaningyesrefitno
The workflow runs from the first fit through label inspection to a parameter change. An all-noise label list sends the analyst back to the parameter step rather than forward to interpreting clusters.

The check at label inspection is the one most worth automating in your own work. If the label list is [-1], stop there, adjust parameters, and refit. Only after the labels contain non-negative values does it make sense to count points and inspect the groups.

Comparing DBSCAN with k-means

The source applies k-means to the same PCA data to show how a different algorithm behaves. The key difference is that k-means must be told how many clusters to produce, and it assigns every point to one of those clusters. With n_clusters set to 10, the source reports cluster sizes ranging from 64 to 386, which it describes as relatively similarly sized. That is quite different from the DBSCAN result, where cluster sizes were very uneven and noise was present.

FeatureDBSCANk-means
Number of clustersFound from eps and min_samplesChosen in advance with n_clusters
Treatment of every pointPoints can be labeled -1 as noiseEvery point is assigned to a cluster
Typical size pattern on the facesVery uneven sizes, with noise presentRelatively similar sizes, from 64 to 386 in the source run
Ability to flag outliersYes, through the -1 labelNo concept of noise
Effect of far-off pointsLabeled as noise if too few neighborsForced into the nearest cluster, so assignments can look arbitrary

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

The difference in cluster sizes follows from how each algorithm assigns points. DBSCAN grows clusters only where points are dense enough and sets the rest aside as noise, so its groups can be large or small and noise can absorb a significant share of the data. k-means has no such option. Points that sit far from a cluster center are still forced into that cluster, which keeps the sizes relatively even but can make individual assignments look somewhat arbitrary.

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

Common Mistakes When Reading Clusters

  • Common mistake

    Treating the label -1 as a cluster

    What it looks like

    Reporting that the faces form a group called -1 with a large number of members.

    Why it fails

    The label -1 is a bin for points DBSCAN could not place in a density-based group, so it is noise rather than a cluster.

    Do this instead

    Separate -1 from the non-negative labels, and count noise on its own.

  • Common mistake

    Reading the label list instead of counting points

    What it looks like

    Seeing that the labels include 0 and 1, and concluding the two clusters are of similar size.

    Why it fails

    A label list does not show how many points carry each label or how much data is noise.

    Do this instead

    Use np.bincount on labels + 1 and read the sizes, including the noise count in the first entry.

  • Common mistake

    Changing only min_samples and judging the data has no groups

    What it looks like

    Lowering min_samples, still getting [-1], and concluding the faces contain no structure.

    Why it fails

    In the source experiment, lowering min_samples alone did not produce clusters, and eps had to increase as well.

    Do this instead

    Change eps, observe the labels, and then decide whether min_samples also needs adjusting.

  • Common mistake

    Expecting k-means to flag outliers

    What it looks like

    Looking for a noise group in the k-means output and finding none.

    Why it fails

    k-means partitions every point and has no concept of noise, so far-off points are forced into a cluster.

    Do this instead

    Use DBSCAN's noise label, or another method, when outlier detection is the goal.

  • Common mistake

    Assuming a clustering reflects real structure without inspecting the groups

Practice Reading a Result

MEDIUM

A colleague runs DBSCAN on the PCA-transformed faces and reports that the unique labels are [-1]. They conclude that the faces contain no groups. Explain what the result actually means, state which parameter you would adjust first, and describe what you would check after the change.

Hints
  • What does the label -1 represent in DBSCAN?
  • The source tried min_samples first, so consider what lowering it alone achieved.
  • After a change, which quantities should you count before judging the groupings?
HARD

Using the sweep idea from earlier, describe what you would expect to see at a very small eps, at a middle value, and at a large eps, and state how you would verify each prediction by counting labels.

Hints
  • Recall the three regions of the sweep: noise dominates, many small clusters appear, and one large cluster accounts for most of the data.
  • np.unique with return_counts reports how many points carry each label.

Key Takeaways

  • A DBSCAN result of [-1] means every point was labeled as noise and no cluster was formed, so the next step is to adjust parameters rather than interpret the output as a clustering.
  • Non-negative labels are clusters and -1 marks noise; counting points per label, not reading the label list, shows how much of the data each cluster covers.
  • Raising eps widens each point's neighborhood and can turn an all-noise result into clusters, while lowering min_samples alone may not be enough.
  • Noise points are outlier candidates, and k-means differs because it forces every point into a cluster, which explains its different size pattern and low agreement with DBSCAN.
  • Unexpected results usually first appear at label inspection, so check parameters and labels before judging whether the groups reflect real structure.

Related concepts

More concepts starting with D