机器学习——聚类分析

聚类分析研究的是未标记的样本自动划分成多个类簇。在日常生活中,常常需要将信息进行归类,构建知识体系。在人类的认知过程中,会遇到许多没有见过的新对象,将这些对象划分未不同类别的过程,需要根据对象本身的特征进行划分。但聚类算法不会提供每个类簇的语义解释。

聚基于划分的聚类

基于划分的方法是简单,常用的一种聚类方法,通过将对象划分为互斥的簇进行聚类,每个对象属于且仅属于一个簇。划分结果旨在使簇之间的样本相似性低,簇内部的样本相似度高。基于划分的聚类的常用算法有k均值,K-中心点划分,K-原型等。

我们就重点介绍以下k均值算法

K-均值算法

K均值聚类是聚类算法中比较简单的一种基础算法,它是工人的十大数据挖掘算法之一,其优点是计算速度快,易于理解.K均值聚类是基于划分的聚类算法,计算样本点与类簇质心的距离,与类簇质心相近的样本点划分为同一类簇。

K均值中样本间的相似度是由它们之间的距离决定的,距离越近,说明相似度越高;反之,则说明相似度越低通常用距离的倒数表示相似度的值,其中常见的距离计算方法有欧式距离和曼哈度距离。

的k-means算法聚类步骤如下:

  1. 首先选取ķ个类簇(K需要用户指定)的质心,通常是随机抽取
  2. 对剩余的每个样本点,计算它们到各个质心的欧式距离,并将其归入到相互间距离最小的质心所在的簇。计算各个新簇的质心。
  3. 在所有样本点都划分完毕后,根据划分情况重新计算各个簇的质心所在位置,然后迭代计算各个样本点到各簇质心的距离,对所有样本点重新进行划分。
  4. 重复第2步和第3步,直到迭代计算后,所有样本点的划分情况保持不变,此时说明的k-means算法已经得到了最优解,将运行结果返回。

算法最主要的问题是如何让算法保证收敛,即如何确定所有样本点的划分情况保存不变。

在实际应用过程中,存在数据集过大而导致算法收敛速度过慢无法得到有效结果的情况。在这样的情况下,可以为K均值均值算法指定最大收敛次数或指定簇中心变化阈值,当算法运算达到最大收敛次数或簇中心变化率小于某个阈值时,算法停止运行。

与其他聚类算法相比,k均值算法原理简单,容易实现,且运行效率比较高,算法的时间复杂度是O(NKT),其中Ñ是所有对象数目,T是迭代次数,通常K,吨都远小于ñ。且对于大数据集,算法是相对可伸缩的,可以指定最大迭代次数,在牺牲一定准确度的情况下提升算法的运行效率。由于k均值均值算法原理简单,因此算法的聚类结果容易解释,适用于高维数据的聚类。

k-means算法的缺点也比较明显,由于算法采用了贪心策略对样本点进行聚类,导致了算法容易局部收敛,在大规模的数据集上解析较慢.k-means算法对离群点和噪声点非常敏感,少量的离群点和噪声点可能对算法求平均值产生极大影响,从而影响算法的聚类效果。

的K-means算法中,K值(即期望得到的类簇个数)的选取会对聚类结果的影响非常大,如果事先能够知道所有样本点中有多少各簇,或者对簇的个数有明确要求,那么在指定ķ值的时候没有太大问题。但是在实际应用中,很多情况下并不知道样本点的分布情况,此时往往是通过多次运行的k-means算法选取聚类质量好的结果,在大数据集下这样的做法非常耗费资源。因此对于k-means算法中k的选取有下面两种方法:

  • 与层次聚类算法结合,先通过层次聚类算法得出大致的聚类数目,并且获得一个初始聚类结果,然后再通过k均值算法改进这个聚类结果。
  • 基于系统演化方法,通过模拟伪热力学系统中的分裂和合并,不断演化直到达到稳定平衡状态,从而确定ķ值。

代码如下所示:
 

import numpy as np
import  matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sklearn.cluster import  KMeans
from sklearn import  datasets
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
np.random.seed(5)
iris=datasets.load_iris()
X=iris.data
Y=iris.target
est=KMeans(n_clusters=2)
est.fit(X)
labels=est.labels_
#可视化
fig=plt.figure(1,figsize=(4,3))
ax=Axes3D(fig,rect=[0,0,.95,1],elev=48,azim=134)
ax.scatter(X[:,3],X[:,0],X[:,2],c=labels.astype(np.float),edgecolor='k')
ax.w_xaxis.set_ticklabels([])
ax.w_yaxis.set_ticklabels([])
ax.w_zaxis.set_ticklabels([])
ax.set_xlabel('花瓣宽度')
ax.set_ylabel('萼片长度')
ax.set_zlabel('花瓣长度')
ax.set_title('3类')
ax.dist=12
plt.show()

首先,从虹膜数据集中加载鸢尾花样本信息到X和ý两个变量中,其中,X存放花瓣长宽等特征,Y存放花的类别标签。构造并初始化k均值模型,设置类簇数量为3类,调用适合方法执行聚类

接下来,对聚类的结果可视化显示,使用Axes3D将其显示在三维空间中,其中花瓣宽度,萼片长度,花瓣长度分别作为X,Y,Z三个维度最后效果如下所示:

基于密度的聚类 

基于划分聚类的方法在聚类过程中根据距离来划分类簇,因此只能够用于挖掘球状簇。为了解决这一缺陷,基于密度聚类算法利用密度思想,将样本中高密度区域(即样本点分布稠密的区域)划分为簇,将簇看作是样本空间中被稀疏区域(噪声)分隔开的稠密区域。这一算法的主要目的是过滤样本空间中的稀疏区域,获取稠密区域作为簇。

基于密度的聚类算法是根据密度而不是距离来计算样本相似度,所以基于密度的聚类算法能够用于挖掘任意形状的簇,并且能够有效过滤掉噪声样本对于聚类结果的影响。常见的基于密度的聚类算法有DBSCAN,OPTICS和DENCLUE等。

下面我们就重点介绍一下DBSCAN算法

DBSCAN算法

DBSCAN采用基于中心的密度定义,的样本密度通过核心对象在\ varepsilon半径内的样本点个数(包括自身)来估计.DBSCAN算法基于领域来描述样本的密度,输入样本集S = {X1,X2,。 ... xn}和参数(\ varepsilon,MinPts)刻画领域中样本个数的阈值。下面给出DBSCAN中的几个重要概念。

  1. \ varepsilon-领域:给定对象十一,半径在\ varepsilon内的区域称为喜的\ varepsilon-领域在该区域中,S的子样本集N \ varepsilon(xi)= {xj \ in S | distance(xi,xj \ leqslant \ varepsilon)}
  2. 核心对象:如果对象xi \ in S.,其\ varepsilon-对应领域的子样本集N \ varepsilon(xi)至少所有游戏MinPts个样本,| N \ varepsilon(xi)| \ GEQMinPts,那么喜为核心对象
  3. 直接密度可达:对于对象喜和XJ,如果喜是一个核心对象,且XJ在十一的\ varepsilon-领域内,那么对象XJ是从十一直接密度可达的。
  4. 密度可达:对于对象xi和xj,若存在一个对象链p1,p2,... pn,使用p1 = x,pn = xj,并且对于pi \ in S(1 \ leq i \ leq n),Pi + 1从Pi关于(\ varepsilon,MinPts)直接密度可达,那么XJ是从十一密度可达的。
  5. 密度相连:对于对象xi和xj,若存在Xk使Xi和Xj是从Xk关于(\ varepsilon,MinPts)密度可达,那么Xi和Xj是密度相连的。

DBSCAN算法根据密度可达关系求出所有密度相连样本的最大集合,将这些样本点作为同一个簇.DBSCAN算法任意选取一个核心对象作为“种子”,然后从“种子”出发寻找所有密度可达的其他核心对象,并且包含每个核心对象的\ varepsilon-领域的非核心对象,将这些核心对象和非核心对象作为一个簇当寻找完成一个簇之后,选择还没有簇标记的其他核心对象,得到一个新的簇,反复执行这个过程,直到所有的核心对象都属于某一个簇为止

DBSCAN利用密度思想进行聚类,因此DBSCAN可以用于对任意形状的稠密数据集进行聚类.K均值算法对数据输入顺序比较敏感,数据输入顺序可能会对聚类结果产生影响,DBSCAN算法对输入顺序不敏感.DBSCAN能够在聚类的过程中发现数据集中的噪声点,且算法本身对噪声点不敏感。

DBSCAN算法要对数据集中的每个对象进行领域检查,当数据集较大时,聚类收敛时间较长,算法的空间复杂度较高。此时可以采用KD树或球树对算法进行改进,快速搜索最近邻,帮助算法快速收敛。此外,聚类质量受样本密度的影响,当空间聚类的密度不均匀,聚类的质量较差。

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
X1, y1=datasets.make_circles(n_samples=5000, factor=.6,
                                      noise=.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.scatter(X[:, 0], X[:, 1], marker='o')
plt.show()

运行结果如下所示:

猜你喜欢

转载自blog.csdn.net/qq_41338249/article/details/84974508