OPTICS聚类算法是基于密度的聚类算法,全称是Ordering points to identify the clustering structure。提到基于密度的聚类算法,应该很快会想到前面介绍的DBSCAN聚类算法,事实上,OPTICS也是为了优化DBSCAN而出现的。
在DBSCAN算法中,有两个比较重要的参数:邻域半径eps和核心对象的最小邻域样本数min_samples,选择不同的参数会导致最终聚类的结果千差万别,而在高维数据中,两个参数的联合调参也不是一件容易的事。OPTICS算法的提出就是为了帮助DBSCAN算法选择合适的参数,降低输入参数的敏感度。实际上,OPTICS并不显式的生成数据聚类结果,只是对数据集中的对象进行排序,得到一个有序的对象列表,通过该有序列表,可以得到一个决策图,通过决策图可以选择不同的eps参数进行DBSCAN聚类。在继续阅读下面的内容之前,需要先了解DBSCAN的相关内容,因为本文的部分概念来自于DBSCAN。
在DBSCAN的基础上,OPTICS定义了两个新的距离概念:
(1)核心距离
对于一个给定的核心对象X,使得X成为核心对象的最小邻域距离 r 就是X的核心距离。这句话乍一看有点绕,其实仔细读两遍就明白了,假如在DBSCAN中我们定义 eps = 1.2 和 min_samples=5,X在eps = 1.2的邻域内有8个样本点,则X是核心对象,但是我们发现距离X最近的第5个点和X的距离是0.8,那么核心对象 X 的核心距离就是 0.8,显然每个核心对象的核心距离并不都是相同的。参考图1,注意在计算 min_samples 的时候,一般也包括样本点自身,所以只需在P点eps邻域内找到7个点,那么P点就是核心点。
(2)可达距离
如果X是核心对象,则对象 Y 到对象 X 的可达距离就是Y到X的欧氏距离和X的核心距离的最大值,如果X不是核心对象,则Y和X之间的可达距离就没有意义(不存在可达距离),显然,数据集中有多少核心对象,那么 Y 就有多少个可达距离。在下文介绍 API 的时候,我们会介绍在OPTICS中,一般默认设置 eps 为无穷大,即只要数据集的样本数不少于 min_samples,那么任意一个样本点都是核心对象,即都有核心距离,且任意两个对象之间都存在可达距离。
OPTICS的原理并不复杂,只不过大多数介绍资料都喜欢列举一些广义的算法流程或者伪代码,虽然满足算法介绍的严谨性,但是阅读起来不免显得晦涩难懂,没有阅读的欲望。因此,和之前的文章一样,本文也是先介绍OPTICS的标准算法流程,然后再以案例的形式介绍流程的具体执行逻辑,如果算法流程不能一下子理解的话,可以先跳过直接看后面的案例,然后再回来看标准流程。
OPTICS算法流程:
已知样本数据集为:D = {[1, 2], [2, 5], [8, 7], [3, 6], [8, 8], [7, 3], [4,5]},为了更好地标识索引,我们以表格标识数据如下:
索引 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 核心对象 |
元素 | (1, 2) | (2, 5) | (8, 7) | (3, 6) | (8, 8) | (7, 3) | (4, 5) | |
核心距离 | 3.16 | 1.41 | 1.0 | 1.41 | 1.0 | 3.61 | 1.41 | |
第一次可达距离 | inf | 3.16 | 8.60 | 4.47 | 9.21 | 6.08 | 4.24 | 0 |
第二次可达距离 | -- | -- | 6.32 | 1.41 | 6.70 | 5.38 | 2.0 | 1 |
第三次可达距离 | -- | -- | 5.09 | -- | 5.39 | 5.0 | 1.41 | 3 |
第四次可达距离 | -- | -- | 4.47 | -- | 5.0 | 3.61 | -- | 6 |
第五次可达距离 | -- | -- | 4.12 | -- | 5.0 (5.10) |
-- | -- | 5 |
第六次可达距离 | -- | -- | -- | -- | 1.0 | -- | -- | 2 |
输出顺序 | 0 | 1 | 5 | 2 | 6 | 4 | 3 | |
可达距离 | inf | 3.16 | 4.12 | 1.41 | 1.0 | 3.61 | 1.41 |
假设eps = inf,min_samples=2,则数据集D在OPTICS算法上的执行步骤如下:
我们按照最终的输出顺序绘制可达距离图(注意,因为第一个元素没有可达距离,或者说可达距离是无穷大,故图中没有标出 0 号元素的可达距离):
可以发现,可达距离呈现两个波谷,也即表现为两个簇,波谷越深,表示簇越紧密,只需要在两个波谷之间取一个合适的 eps 分隔值(图中蓝色的直线,例如两个可达距离的平均值),使用 DBSCAN 算法就会聚类为两个簇。即第一个簇的元素为:0、1、3、6、5;第二个簇的元素为:2、4。下面我们通过sklearn库来验证我们的结果。
sklearn库同样为我们封装了 OPTICS 算法的API,供我们直接使用。
基于1.1的数据集,使用OPTICS验证算法结果如下:
from sklearn.cluster import OPTICS
import numpy as np
X = np.array([[1, 2], [2, 5], [8, 7],[3, 6], [8, 8], [7, 3], [4,5]])
clustering = OPTICS(min_samples=2).fit(X)
print(clustering.core_distances_)
'''
array([3.16227766, 1.41421356, 1. , 1.41421356, 1. ,3.60555128, 1.41421356])
'''
print(clustering.ordering_)
'''
array([0, 1, 3, 6, 5, 2, 4])
'''
print(clustering.reachability_)
'''
array([inf, 3.16227766, 4.12310563, 1.41421356, 1. ,3.60555128, 1.41421356])
'''
print(clustering.labels_)
'''
array([0, 0, 1, 0, 1, 0, 0])
'''
根据图3,选择 eps=3.8,使用DBSCAN算法验证如下:
import sklearn
db = sklearn.cluster.DBSCAN(eps=3.8,min_samples=2).fit(X)
db.labels_
## array([0, 0, 1, 0, 1, 0, 0])
[1] https://blog.csdn.net/PRINCE2327/article/details/110412944