本篇文章主要学习:
机器学习(八):DBSCAN算法(基础篇)
DBSCAN聚类算法原理及其实现
密度聚类也被称作“基于密度的聚类”(density-based clustering),此算法假设聚类结构能通过样本分布的紧密程度确定,通常情况下,密度聚类算法从样本密度的角度来考察样本之间的可连接性,并基于可连接样本不断扩展聚类以获取最终的聚类结果。
DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一个比较有代表性的基于密度的聚类算法。它基于一组**“邻域”**(neighborhood)参数来刻画样本分布的紧密程度,可以发现任何形状的聚类。
了解DBSCAN算法的原理,需要了解几个基本概念:
核心对象:如果给定对象e邻域内的样本点数大于等于MinPoints,则称该对象为核心对象;如图:设置MinPoints的点为2,那么在对象p的e领域内有4个点,大于MinPoints,那么p对象就是核心对象。
密度可达:给定一个对象集合D,给定一串样本点p1,p2….pn, xi= p1并且xi为核心对象,xj= pn,xj不为核心对象,(即pn不为核心对象)。那么假如对象pi(可能为核心对象,也可能不为核心对象)从pi-1(核心对象)直接密度可达,那么对象xj从对象xi密度可达。
密度相连:存在样本集合D中的一点o,如果对象o(是核心对象)到对象p(不是核心对象)和对象q(不是核心对象)都是密度可达的,那么p和q密度相联。
DBSCAN聚类使用到一个k-距离的概念,k-距离是指:给定数据集P={p(i); i=0,1,…n},对于任意点P(i),计算点P(i)到集合D的子集S={p(1), p(2), …, p(i-1), p(i+1), …, p(n)}中所有点之间的距离,距离按照从小到大的顺序排序,假设排序后的距离集合为D={d(1), d(2), …, d(k-1), d(k), d(k+1), …,d(n)},则d(k)就被称为k-距离。也就是说,k-距离是点p(i)到所有点(除了p(i)点)之间距离第k近的距离。对待聚类集合中每个点p(i)都计算k-距离,最后得到所有点的k-距离集合E={e(1), e(2), …, e(n)}。
K距离:给定数据集P{p(1),p(2)…p(i)},计算p(i)到集合D的子集S中所有点的距离,按照从小到大的顺序排序,d(k)就被称为k距离。
半径e根据距离来设定:找突变点。即根据得到的所有点的k-距离集合E,对集合E进行升序排序后得到k-距离集合E’,需要拟合一条排序后的E’集合中k-距离的变化曲线图,然后绘出曲线,通过观察,将急剧发生变化的位置所对应的k-距离的值,确定为半径Eps的值。
MinPoints:称为点的密度,一般取值较小而多次尝试。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN # DBSCAN API
data = pd.read_csv("data.csv").values
plt.scatter(data[:,0],data[:,1])
plt.show()
model = DBSCAN(eps=1.5,min_samples=4) # 设半径为1.5 Minpoint为4
model.fit(data)
result = model.fit_predict(data)
result
# 可视化 不同颜色表示同簇的点
# 构建点的样式列表
mark = ['or','ob','og','oy','ok','om']
# 输出数据的 索引 以及 数据
for i,d in enumerate(data):
# print(i,d)
# 可视化
plt.plot(d[0],d[1],mark[result[i]])
plt.show()
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
x1,y1 = datasets.make_circles(n_samples=2000,factor=0.5,noise=0.05) # 构建数据集1
x2,y2 = datasets.make_blobs(n_samples=1000,centers=[[1.2,1.2]],cluster_std=[[0.1]]) # 构建数据集2
x = np.concatenate((x1,x2)) # 数据集1和2叠加
plt.scatter(x[:,0],x[:,1],marker='o')
plt.show()
"""
kmeans聚类:效果不好
"""
from sklearn.cluster import KMeans
y_pred = KMeans(n_clusters=3).fit_predict(x)
plt.scatter(x[:,0],x[:,1],c=y_pred)
plt.show()
"""
DBSCAN聚类:效果不错
"""
from sklearn.cluster import DBSCAN
y_pred = DBSCAN(eps=0.2,min_samples=50).fit_predict(x)
plt.scatter(x[:,0],x[:,1],c=y_pred)
plt.show()