密度聚类假设聚类结构能通过样本分布的紧密程度确定。
DBSCAN(Density-Based Spacial Clustering of Application with Noise)就是一种著名的密度聚类算法,它用一组参数(,MinPts)来刻画样本分布的紧密程度。先定义下面的一些概念:
-邻域:对,其-邻域包含样本集D中与的距离不大于的样本,即;
核心对象:若的-邻域至少包含MinPts个样本,即,则是一个核心对象;
密度直达:若位于的-邻域中,且是核心对象,则称由密度直达;
密度可达:对和,若存在样本序列,其中且由密度直达,则称由密度可达;
密度相连:对和,若存在使得与均由密度可达,则称与密度相连。
上述概念的直观显示:
DBSCAN将“簇”定义为:由密度可达关系导出的最大的密度相连样本集合,给定参数(,MinPts),簇CD是满足以下性质的非空样本子集:
- 连接性:密度相连
- 最大性:,由密度可达
另外,D中可能存在不属于任何簇的样本,这样的样本被认为是噪声或异常样本。
如何从数据集D中找到满足以上性质的聚类簇呢?不难证明,若x为核心对象,由x密度可达的所有样本组成的集合X = {x'D|x'由x密度可达}就是满足连接性和最大性的簇。
算法描述如下:
python代码实现:
import numpy as np
epsilon = 0.11
minpts = 5
x = np.load("watermalon4.0.npy")
#epsilon邻域统计表
t = [set() for i in range(30)]
#聚类簇
clusters = []
#核心对象集
coreset = set()
for i in range(len(x)):
t[i].add(i)
for j in range(i+1,len(x)):
#欧式距离
dist = np.linalg.norm(x[i] - x[j])
if dist <= epsilon:
#记录epsilon邻域信息
t[i].add(j)
t[j].add(i)
for i in range(len(t)):
if len(t[i]) >= minpts:
#核心对象集
coreset.add(i)
allset = {i for i in range(len(x))}
while len(coreset) > 0:
#浅拷贝(拷贝第一层,这里没影响)
oldset = allset.copy();
corepoint = coreset.pop()
q = [corepoint]
allset -= {corepoint}
while len(q) > 0:
item = q.pop(0)
if len(t[item]) >= minpts:
#交集
delta = t[item] & allset
q += [i for i in delta]
allset -= delta
#新的聚类簇
newcluster = oldset - allset
clusters.append(newcluster)
coreset -= newcluster
print(clusters)
参考资料:周志华《机器学习》