赞
踩
之前介绍过基于划分的聚类算法,如k-means和k-medoids,也介绍过基于层次聚类的方法。这两种方法本质上都是基于距离的算法,只能发现类圆形的聚类。
基于密度的方法(Density-based Methods)是基于密度的,可以克服基于距离的算法只能发现“类圆形”聚类的缺点。
主要思想:只要在给定半径邻近区域的密度超过某个阈值,就把它添加到与之相近的簇类中去。
这样的方法可以用来过滤噪声数据,并且可以发现任意形状的聚类。
基于密度的方法中,代表算法有:
DBSCAN是基于密度聚类中的经典算法,突出特色在于:
DBSCAN聚类中有两个重要参数:
基于这两个参数,DBSCAN聚类将样本观测点分成以下4类:
设置邻域半径
ε
\varepsilon
ε和邻域半径
ε
\varepsilon
ε范围内包含的最少观测点个数
m
i
n
P
t
s
minPts
minPts。
在参数设定的条件下,DBSCAN聚类过程大致包括形成小类和合并小类两个阶段:
在scikit-learn中,包含sklearn.cluster.DBSCAN的算法。DBSCAN()常用形式为:
DBSCAN(eps=0.5,min_samples=5,metric=’euclidean’, algorithm=’auto’)
参数说明:
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
x1,y1=datasets.make_circles(n_samples=5000, factor=0.6,noise=0.05)
x2,y2 = datasets.make_blobs(n_samples=1000, n_features=2, centers=[[1.2,1.2]], cluster_std=[[.1]],random_state=9)
x = np.concatenate((x1, x2))
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
plt.figure(figsize=(10,8))
plt.subplot(2,2,1)
# 观察总体样本分布
plt.title("整体样本分布")
plt.scatter(x[:,0],x[:,1], marker='o')
plt.subplot(2,2,2)
# 观察认参数聚类效果
plt.title("默认参数聚类效果")
x = np.concatenate((x1, x2))
y_pred = DBSCAN().fit_predict(x)
plt.scatter(x[:,0],x[:, 1], c=y_pred)
plt.subplot(2,2,3)
# 观察邻域为0.1时聚类效果
plt.title("邻域为0.1时聚类效果")
y_pred2 = DBSCAN(eps = 0.1).fit_predict(x)
plt.scatter(x[:,0],x[:,1],c=y_pred2)
plt.subplot(2,2,4)
# 观察minPts为10时聚类效果
plt.title("minPts为0.1时聚类效果")
y_pred3 = DBSCAN(eps = 0.1,min_samples =10).fit_predict(x)
plt.scatter(x[:,0],x[:,1],c=y_pred3)
plt.show()
DBSCAN聚类的最大特点是能够发现任意形状的类。
DBSCAN算法对参数
ε
\varepsilon
ε(邻域半径)和
m
i
n
P
t
s
minPts
minPts极为敏感。以下进行相关参数设置试验以说明特性:
试验代码如下:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from itertools import cycle
import warnings
warnings.filterwarnings(action = 'ignore')
%matplotlib inline
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
from scipy.stats import norm
from sklearn.datasets import make_moons
from sklearn.cluster import DBSCAN,Birch,KMeans,estimate_bandwidth,MeanShift
X=pd.read_csv('异形聚类数据.txt',header=0)
fig=plt.figure(figsize=(15,10))
plt.subplot(231)
plt.scatter(X['x1'],X['x2'])
plt.title("异形样本观测的分布(样本量=%d)"%len(X))
plt.xlabel("X1")
plt.ylabel("X2")
colors = 'bgrcmyk'
EPS=[0.2,0.5,0.2,0.5,0.2]
MinS=[200,80,100,300,30]
Gid=1
for eps,mins in zip(EPS,MinS):
DBS=DBSCAN(min_samples=mins,eps=eps)
DBS.fit(X)
labels=np.unique(DBS.labels_)
Gid+=1
plt.subplot(2,3,Gid)
for i,k in enumerate(labels):
if k==-1: #噪声点
c='darkorange'
m='*'
else:
c=colors[i]
m='o'
plt.scatter(X.iloc[DBS.labels_==k,0],X.iloc[DBS.labels_==k,1],c=c,s=30,alpha=0.8,marker=m)
plt.title("DBSCAN聚类解\n(最少观测点=%d,近邻半径=%.2f)\n (%d个核心点,%d个噪声点,%d个其他点)"%(mins,eps,len(DBS.components_),
sum(DBS.labels_==-1),len(X)-len(DBS.components_)-sum(DBS.labels_==-1)))
plt.xlabel("X1")
plt.ylabel("X2")
fig.subplots_adjust(hspace=0.3)
fig.subplots_adjust(wspace=0.2)
在DBSCAN算法中,有两个初始参数 ε \varepsilon ε(邻域半径)和 m i n P t s minPts minPts( ε \varepsilon ε邻域最小样本数)需要用户手动设置输入,并且聚类的类簇结果对这两个参数的取值非常敏感,不同的取值将产生不同的聚类结果,其实这也是大多数需要初始化参数聚类算法的弊端。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。