Python
OPTICS
Clustering Algorithm
Data Science
Machine Learning

Python Implementation of OPTICS Clustering Algorithm

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

OPTICS is a density-based clustering algorithm designed for data sets where clusters may have different local densities. Instead of committing to one global distance threshold early, it produces an ordering and reachability values that help you inspect cluster structure more flexibly than plain DBSCAN.

Why Use OPTICS

DBSCAN is popular because it can discover arbitrarily shaped clusters and mark outliers as noise. Its main weakness is that one eps value must work everywhere. If one region is dense and another is sparse, a single threshold often merges one cluster or splits another.

OPTICS addresses that by computing an ordering of points together with two useful values:

  • Core distance, which measures whether a point is dense enough to seed local expansion
  • Reachability distance, which measures how far a point is from the cluster structure found so far

You can then extract clusters from that ordering using different rules. In scikit-learn, the common options are cluster_method="xi" and cluster_method="dbscan".

A Runnable Python Example

Scikit-learn includes a production-ready implementation, so most projects do not need to code OPTICS from scratch. The example below creates a synthetic data set with clusters of different densities, scales it, trains OPTICS, and prints a small summary.

python
1import numpy as np
2from sklearn.cluster import OPTICS
3from sklearn.datasets import make_blobs
4from sklearn.metrics import silhouette_score
5from sklearn.preprocessing import StandardScaler
6
7# Dense cluster, sparse cluster, and mild overlap
8X, _ = make_blobs(
9    n_samples=[120, 180, 100],
10    centers=[(-2, -2), (2, 2), (4, -1)],
11    cluster_std=[0.25, 0.8, 0.45],
12    random_state=7,
13)
14
15X = StandardScaler().fit_transform(X)
16
17model = OPTICS(
18    min_samples=10,
19    xi=0.05,
20    min_cluster_size=0.08,
21    cluster_method="xi",
22)
23
24labels = model.fit_predict(X)
25
26cluster_ids = sorted(label for label in np.unique(labels) if label != -1)
27noise_count = int(np.sum(labels == -1))
28
29print("Clusters found:", cluster_ids)
30print("Noise points:", noise_count)
31
32non_noise_mask = labels != -1
33if len(set(labels[non_noise_mask])) > 1:
34    score = silhouette_score(X[non_noise_mask], labels[non_noise_mask])
35    print("Silhouette score:", round(score, 3))
36else:
37    print("Silhouette score: not enough non-noise clusters")
38
39print("First 10 reachability values:")
40print(np.round(model.reachability_[:10], 3))

This example is runnable as-is once scikit-learn is installed. The labels use -1 for noise, just like DBSCAN. The reachability values are useful for plotting or debugging why a given point fell into a cluster or remained noise.

Interpreting the Output

Three model attributes matter most:

  • 'labels_: Final cluster assignment for each sample'
  • 'ordering_: The order in which points were processed'
  • 'reachability_: Reachability distance aligned with the original sample indices'

If you want a quick visual inspection, plotting the ordered reachability values is often more informative than plotting labels alone. Valleys in that plot often correspond to cluster structure.

Here is a small plotting example:

python
1import matplotlib.pyplot as plt
2
3ordered_reachability = model.reachability_[model.ordering_]
4ordered_labels = labels[model.ordering_]
5
6plt.figure(figsize=(10, 4))
7plt.bar(
8    range(len(ordered_reachability)),
9    ordered_reachability,
10    color=["tab:gray" if label == -1 else "tab:blue" for label in ordered_labels],
11    width=1.0,
12)
13plt.title("OPTICS Reachability Plot")
14plt.xlabel("Ordered sample index")
15plt.ylabel("Reachability distance")
16plt.tight_layout()
17plt.show()

Large peaks often signal transitions between clusters, while low stable regions often indicate dense groups.

Parameter Choices That Matter

min_samples controls how many neighbors define local density. Larger values make the algorithm more conservative and reduce sensitivity to tiny groups.

xi controls how steep a drop or rise must be before scikit-learn declares a cluster boundary when cluster_method="xi" is used. Smaller values can produce more clusters; larger values can merge structure.

min_cluster_size prevents tiny accidental clusters from appearing in noisy data. When working with business data, choosing this value from domain knowledge is often better than leaving it at a very small default.

Standardizing features also matters. OPTICS is distance-based, so a column with larger raw scale can dominate the result if you skip normalization.

Common Pitfalls

The first pitfall is expecting OPTICS to return the same style of clusters as k-means. It does not optimize around spherical centroids. Instead, it captures density-connected regions, so cluster labels can look less tidy but often reflect the geometry of the data better.

Another common mistake is evaluating the model on all labels, including noise. Many metrics assume every point belongs to a cluster. If you use silhouette score or similar measures, consider filtering out noise points first.

A third issue is ignoring feature scaling. Even a correct implementation can produce poor clusters if one numeric column dominates Euclidean distance.

Finally, OPTICS is not a free pass around parameter tuning. It is more flexible than DBSCAN, but min_samples, xi, and min_cluster_size still affect the output substantially. Run small experiments and inspect the reachability plot instead of relying on one default configuration.

Summary

  • OPTICS is useful when your data contains clusters with different densities.
  • In Python, the practical implementation is usually sklearn.cluster.OPTICS.
  • The most important outputs are labels_, ordering_, and reachability_.
  • Scale numeric features before fitting because OPTICS depends on distance calculations.
  • Inspect noise points and reachability plots instead of trusting cluster labels blindly.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.