DBSCAN与分层聚类
DBSCAN
一、应用举例
1、创建假数据
import numpy as np
from sklearn import datasets
from sklearn.cluster import KMeans,DBSCAN
import matplotlib.pyplot as plt
# y中是两类:0,1
X,y = datasets.make_circles(n_samples=1000,noise=0.05,factor = 0.5)
# centers = [(1.5,1.5)] 元组,代表着,中心点的坐标值
# y1一类:0 + 2
X1,y1 = datasets.make_blobs(n_samples=500,n_features=2,centers=[(1.5,1.5)],cluster_std=0.2)
# 将circle和散点进行了数据合并
X = np.concatenate([X,X1])
y = np.concatenate([y,y1 + 2])
plt.scatter(X[:,0],X[:,1],c = y)
2、Kmeans与DBSCAN对比
假设我们的数据分布是上面这种情况,如果用Kmeans来聚类:
kmeans = KMeans(3)
kmeans.fit(X)
y_ = kmeans.labels_
plt.scatter(X[:,0],X[:,1],c = y_)
此时,圆环这种分布的数据就分不开了,因为Kmeans是基于距离的聚类。距离近的点归为一类。
’圆环数据‘应用DBSCAN聚类:
dbscan = DBSCAN(eps = 0.2,min_samples=3)
dbscan.fit(X)
y_ = dbscan.labels_
plt.scatter(X[:,0],X[:,1],c = y_)
此时的分类效果就较为准确了,而且DBSCAN还可以应用于异常数据的检测,如上图离群点就没有被归为某一个大类
二、基本原理简介
DBSCAN(Density-Based Spatial Clustering of Applications with Noise,具有噪声的基于密度的聚类方法)是一种基于密度的空间聚类算法。 该算法将具有足够密度的区域划分为簇,并在具有噪声的空间数据库中发现任意形状的簇,它将簇定义为密度相连的点的最大集合。
基于密度这点有什么好处呢?,我们知道Kmeans聚类算法只能处理球形的簇,也就是一个聚成实心的团(这是因为算法本身计算平均距离的局限)。但往往现实中还会有各种形状,比如下面两张图,环形和不规则形,这个时候,那些传统的聚类算法显然就悲剧了。于是可以这样搞,把样本密度大的聚成一类呗。这就是DBSCAN聚类算法。
DBSCAN算法原理:
首先需要人为指定的主要参数:
1、eps---->半径
2、min_samples—>最小样本数
DBSCAN就是随机选择一个样本点,然后以此样本点画圆圈,圈中min_samples个样本归为一类,少于
min_samples的会被归为边界点或者离群值。
每一个点只访问一次,递归发展下线的感觉。大哥带几个小弟,小弟发展自己的势力,小弟的小弟继续发展势力。。。
示例:
假设min_samples=3时,
过程动画:
------------------>可视化网站
分层聚类/层次聚类
大概过程:先聚一个小类,再把距离近的小类聚为一个大类,如上图
分层聚类法(hierarchical cluster method)
算法原理:
层次聚类(Hierarchical Clustering)是聚类算法的一种,通过计算不同类别数据点间的相似度来创建一棵有层次的嵌套聚类树。在聚类树中,不同类别的原始数据点是树的最低层,树的顶层是一个聚类的根节点。创建聚类树有自下而上合并和自上而下分裂两种方法。
自底向上的合并算法:
两个组合数据点间的距离:
- Single Linkage
- 方法是将两个组合数据点中距离最近的两个数据点间的距离作为这两个组合数据点的距离。这种方法容易受到极端值的影响。两个很相似的组合数据点可能由于其中的某个极端的数据点距离较近而组合在一起。
- Complete Linkage
- complete Linkage的计算方法与Single Linkage相反,将两个组合数据点中距离最远的两个数据点间的距离作为这两个组合数据点的距离。Complete Linkage的问题也与Single Linkage相反,两个不相似的组合数据点可能由于其中的极端值距离较远而无法组合在一起。
- Average Linkage
- Average Linkage的计算方法是计算两个组合数据点中的每个数据点与其他所有数据点的距离。将所有距离的均值作为两个组合数据点间的距离。这种方法计算量比较大,但结果比前两种方法更合理。
- 我们使用Average Linkage计算组合数据点间的距离。下面是计算组合数据点(A,F)到(B,C)的距离,这里分别计算了(A,F)和(B,C)两两间距离的均值。
参数:
-
n_clusters
划分类别数目
-
linkage
度量两个子类的相似度时所依据的距离
- Single Linkage:将两个数据点集中距离最近的两个数据点间的距离作为这两个点集的距离。
- Complete Linkage:将两个点集中距离最远的两个数据点间的距离作为这两个点集的距离。
上述两种方法容易受到极端值的影响,计算大样本集效率较高。 - Average Linkage:计算两个点集中的每个数据点与其他所有数据点的距离。将所有距离的均值作为两个点集间的距离。这种方法计算量比较大,不过这种度量方法更合理
- Ward:最小化簇内方差。
-
connectivity
连接性约束,作用:只有相邻的簇才能合并在一起,进行聚类!
可视化案例:
导入数据:
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as p3
from sklearn.cluster import AgglomerativeClustering
from sklearn.datasets import make_swiss_roll
X,y = datasets.make_swiss_roll(n_samples=1500,noise = 0.05)
fig = plt.figure(figsize=(8,6))
a3 = fig.add_subplot(projection = '3d')
a3.scatter(X[:,0],X[:,1],X[:,2],c = y)
a3.view_init(10,-80)
用Kmeans效果:
kmeans = KMeans(n_clusters=6)
kmeans.fit(X)
y_ = kmeans.labels_
fig = plt.figure(figsize=(8,6))
a3 = plt.subplot(projection = '3d')
a3.scatter(X[:,0],X[:,1],X[:,2],c = y_)
a3.view_init(10,-80)
可以看到,基于距离的kmeans聚类出来的结果,会因为距离问题把不同层级的数据聚为一类
分层聚类
agg = AgglomerativeClustering(n_clusters=6,linkage='ward')# 最近的距离,作为标准,
agg.fit(X)
y_ = agg.labels_
fig = plt.figure(figsize=(12,9))
a3 = plt.subplot(projection = '3d')
a3.scatter(X[:,0],X[:,1],X[:,2],c = y_)
a3.view_init(10,-80)
效果也不是很好,为什么?
因为这种数据是非欧几何数据,没有设置连接性约束,会忽视了数据的结构特性
下面设置连接性约束,对局部的结构进行约束
from sklearn.neighbors import kneighbors_graph# graph图形的意思
# 邻居数量变少,认为,条件宽松
conn = kneighbors_graph(X,n_neighbors=10) #采用邻居,进行约束
agg = AgglomerativeClustering(n_clusters=6,connectivity=conn,linkage='ward')# 最近的距离,作为标准,
agg.fit(X)
y_ = agg.labels_
fig = plt.figure(figsize=(12,9))
a3 = fig.add_subplot(projection = '3d')
a3.scatter(X[:,0],X[:,1],X[:,2],c = y_)
a3.view_init(10,-80)
这下子就分开了!