Coding Now – Best AI & Full Stack Courses in Delhi NCR | 100% Placement
Limited Offer: Get 50% OFF on AI & Full Stack Courses
📞 Call Now: +91 9667708830
Back to Machine Learning Notes
Topic #1408

DBSCAN in Python

A complete DBSCAN workflow — parameter selection via the k-distance plot, fitting, visualizing clusters and noise separately, and comparing directly against K-Means on the same data.

The Full Workflow

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import DBSCAN, KMeans

# A crescent-moon shaped dataset -- classic case where K-Means fails and DBSCAN succeeds
X, _ = make_moons(n_samples=300, noise=0.08, random_state=42)
X_scaled = StandardScaler().fit_transform(X)

dbscan_model = DBSCAN(eps=0.25, min_samples=5)
dbscan_labels = dbscan_model.fit_predict(X_scaled)

kmeans_model = KMeans(n_clusters=2, random_state=42, n_init=10)
kmeans_labels = kmeans_model.fit_predict(X_scaled)

fig, axes = plt.subplots(1, 2, figsize=(12, 5))
axes[0].scatter(X[:,0], X[:,1], c=dbscan_labels, cmap="viridis")
axes[0].set_title("DBSCAN -- correctly traces the two crescents")
axes[1].scatter(X[:,0], X[:,1], c=kmeans_labels, cmap="viridis")
axes[1].set_title("K-Means -- forces round clusters, gets it wrong")
plt.show()

Expected result: DBSCAN correctly identifies the two crescent-moon shapes as separate clusters, since it follows local density rather than distance to a single centroid; K-Means, constrained to round clusters, typically splits the two crescents incorrectly (e.g. cutting each moon roughly in half instead of separating them).

Counting Clusters and Noise Points

n_clusters = len(set(dbscan_labels)) - (1 if -1 in dbscan_labels else 0)
n_noise = list(dbscan_labels).count(-1)
print(f"Clusters found: {n_clusters}")
print(f"Noise points: {n_noise}")

Tuning eps Systematically

from sklearn.neighbors import NearestNeighbors

neighbors = NearestNeighbors(n_neighbors=5).fit(X_scaled)
distances, _ = neighbors.kneighbors(X_scaled)
k_distances = np.sort(distances[:, -1])

plt.plot(k_distances)
plt.ylabel("5th nearest neighbor distance")
plt.xlabel("Points, sorted")
plt.show()
# Pick eps around the visually apparent "knee" in this curve

Common Mistakes

  • Comparing DBSCAN and K-Means results without scaling features first for both — an unfair, misleading comparison.
  • Not checking how many points ended up labeled noise — a very high noise count usually means eps is too small or min_samples too high for the data's actual density.
  • Assuming DBSCAN will always outperform K-Means — for genuinely round, evenly-sized, evenly-dense clusters, K-Means is often simpler, faster, and just as effective.

Interview Relevance

Q: "Show me a dataset shape where DBSCAN clearly outperforms K-Means." Two interleaved crescent moons (or concentric circles) — K-Means, constrained to round/convex clusters via centroid distance, cannot separate these shapes correctly regardless of tuning, while DBSCAN's density-based approach traces the actual non-convex cluster shapes directly.

Practice Question

Modify the workflow above to test eps values of 0.15, 0.25, and 0.4, and compare how the number of detected clusters and noise points changes.

Related ML Notes

Want to go beyond the notes?

Join CodingNow's Machine Learning course — live mentorship, real projects, and 100% placement support.

Enroll Now — Free Demo Available
💬 Talk to Advisor
1
WhatsApp

Latest from Our Blog

Insights on AI, Data Science, Full Stack & Career

View All Articles →