K-means 聚类,介绍了 K-means
算法以及一些优化改进的算法,通过此了解聚类分析,接下来我们进一步的介绍聚类分析的其他方法。
本篇代码可见:Github
\quad\quad 层次聚类技术是第二类重要的聚类方法。层次聚类方法对给定的数据集进行层次的分解,直到满足某种条件为止,传统的层次聚类算法主要分为两大类算法:
AGNES算法
(AGglomerative NESting) → \rightarrow → 采用 自底向上 的策略。最初将每个对象作为一个簇,然后这些簇根据某些准则被一步一步合并,两个簇间的距离可以由这两个不同簇中距离最近的数据点的相似度来确定;聚类的合并过程反复进行直到所有的对象满足簇数目。
DIANA算法
(DIvisive ANALysis) → \rightarrow → 采用 自顶向下 的策略。首先将所有对象置于一个簇中,然后按照某种既定的规则逐渐细分为越来越小的簇(比如最大的欧式距离),直到达到某个终结条件(簇数目或者簇距离达到阈值)。
到目前为止,凝聚层次聚类技术最常见,本篇主要介绍这类聚类方法
层次聚类常常使用称作 树状图 的类似于树的图显示,该图显示簇-子簇联系和簇合并(凝聚)或分类的次序。对于二维点的集合,层次聚类也可以使用嵌套簇图表示。如下图:
上面算法的关键操作是计算两个簇之间的邻近性,主要有以下几种:
最小距离(MIN):两个聚簇中最近的两个样本之间的距离(single/word-linkage聚类法),最终得到模型容易形成链式结构
最大距离(MAX):两个聚簇中最远的两个样本的距离(complete-linkage聚类法),如果存在异常值,那么构建可能不太稳定
组平均:两个聚簇中样本间两两距离的平均值(average-linkage聚类法),两个聚簇中样本间两两距离的中值(median-linkage聚类法)
上图是基于图的定义,什么是基于图,可参考前篇;
- 如果取基于原型的观点,簇用质心代表,则不同的簇邻近度定义就更容易,使用质心时,簇的邻近度一般定义为簇质心之间的邻近度。
- 另一种技术,
Ward
方法,也假定簇用其质心代表,但它使用两个簇导致的SSE增加来度量两个簇之间的邻近性,类似于K均值
,Ward
方法也试图最小化点到其簇质心的距离的平方和。
样本数据如下:
(1)MIN
d i s t ( { 3 , 6 } , { 2 , 5 } ) = m i n ( d i s t ( 3 , 2 ) , d i s t ( 6 , 2 ) , d i s t ( 3 , 5 ) , d i s t ( 6 , 5 ) ) dist(\{3,6\},\{2,5\}) = min(dist(3,2),dist(6,2),dist(3,5),dist(6,5)) dist({3,6},{2,5})=min(dist(3,2),dist(6,2),dist(3,5),dist(6,5))
= m i n ( 0.15 , 0.25 , 0.28 , 0.39 ) = min(0.15,0.25,0.28,0.39) =min(0.15,0.25,0.28,0.39)
= 0.15 =0.15 =0.15
- 左图中圆圈数字代表聚类的次;
- 右图中纵轴代表两个簇的距离;
(2)MAX
d i s t ( { 3 , 6 } , { 4 } ) = m a x ( d i s t ( 3 , 4 ) , d i s t ( 6 , 4 ) ) = m a x ( 0.15 , 0.22 ) = 0.22 dist(\{3,6\},\{4\}) = max(dist(3,4),dist(6,4))= max(0.15,0.22) = 0.22 dist({3,6},{4})=max(dist(3,4),dist(6,4))=max(0.15,0.22)=0.22
d i s t ( { 3 , 6 } , { 2 , 5 } ) = m a x ( d i s t ( 3 , 2 ) , d i s t ( 6 , 2 ) , d i s t ( 3 , 5 ) , d i s t ( 6 , 5 ) ) = m a x ( 0.15 , 0.25 , 0.28 , 0.39 ) = 0.39 dist(\{3,6\},\{2,5\}) = max(dist(3,2),dist(6,2),dist(3,5),dist(6,5))\\ = max(0.15,0.25,0.28,0.39) = 0.39 dist({3,6},{2,5})=max(dist(3,2),dist(6,2),dist(3,5),dist(6,5))=max(0.15,0.25,0.28,0.39)=0.39
d i s t ( { 3 , 6 } , { 1 } ) = m a x ( d i s t ( 3 , 1 ) , d i s t ( 6 , 1 ) ) = m a x ( 0.22 , 0.23 ) = 0.23 dist(\{3,6\},\{1\}) = max(dist(3,1),dist(6,1))= max(0.22,0.23) = 0.23 dist({3,6},{1})=max(dist(3,1),dist(6,1))=max(0.22,0.23)=0.23
(3)组平均
对于组平均,簇 C I C_I CI 和 C j C_j Cj 的邻近度 p r o x i m i t y ( C i , C j ) proximity(C_i, C_j) proximity(Ci,Cj) 由下式定义:
p r o x i m i t y ( C i , C j ) = ∑ x ∈ C i , y ∈ C j p r o x i m i t y ( x , y ) m i ∗ m j proximity(C_i, C_j) = \frac{\sum_{x \in C_i,y \in C_j}proximity(x,y)}{m_i * m_j} proximity(Ci,Cj)=mi∗mj∑x∈Ci,y∈Cjproximity(x,y)
其中, m i , m j m_i,m_j mi,mj 分别表示簇 C i , C j C_i,C_j Ci,Cj的大小
d i s t ( { 3 , 6 , 4 } , { 1 } ) = ( 0.22 + 0.37 + 0.23 ) / ( 3 ∗ 1 ) = 0.28 dist(\{3,6,4\},\{1\}) = (0.22+0.37+0.23)/(3*1)=0.28 dist({3,6,4},{1})=(0.22+0.37+0.23)/(3∗1)=0.28
d i s t ( { 2 , 5 } , { 1 } ) = ( 0.2357 + 3421 ) / ( 2 ∗ 1 ) = 0.2889 dist(\{2,5\},\{1\}) = (0.2357+3421)/(2*1)=0.2889 dist({2,5},{1})=(0.2357+3421)/(2∗1)=0.2889
d i s t ( { 3 , 6 , 4 } , { 2 , 5 } ) = ( 0.15 + 0.28 + 0.25 + 0.39 + 0.20 + 0.29 ) / ( 3 ∗ 2 ) = 0.26 dist(\{3,6,4\},\{2,5\}) = (0.15+0.28+0.25+0.39+0.20+0.29)/(3*2)=0.26 dist({3,6,4},{2,5})=(0.15+0.28+0.25+0.39+0.20+0.29)/(3∗2)=0.26
因为 d i s t ( { 3 , 6 , 4 } , { 1 } ) dist(\{3,6,4\},\{1\}) dist({3,6,4},{1}) 比 d i s t ( { 3 , 6 , 4 } , { 2 , 5 } ) dist(\{3,6,4\},\{2,5\}) dist({3,6,4},{2,5}) 和 d i s t ( { 2 , 5 } , { 1 } ) dist(\{2,5\},\{1\}) dist({2,5},{1}) 小,簇 { 3 , 6 , 4 } \{3,6,4\} {3,6,4}和 { 2 , 5 } \{2,5\} {2,5}在第4阶段合并。
(4)Ward
对于 Ward
方法,两个簇的邻近度定义为两个簇合并时导致的平方误差的增量。该方法使用的目标函数与K均值
相同。当两个点之间的邻近度取它们之间距离的平方时,Ward
方法与 组平均
非常相似
使用 sklearn
库中AgglomerativeClustering
类,API如下:
sklearn.cluster.AgglomerativeClustering(n_clusters = 2, affinity ='euclidean',
memory = None, connectivity = None, compute_full_tree ='auto',
linkage ='ward', pooling_func ='deprecated')
常用参数说明:
参数 | 描述 |
---|---|
n_clusters : int, default=2 | 要查找的簇数 |
affinity : string or callable, default: “euclidean” | 用于计算链接的度量标准。可以是“euclidean”,“l1”,“l2”,“manhattan”,“cosine”或“precomputed” |
linkage : {“ward”, “complete”, “average”, “single”}, optional (default=”ward”) | 使用哪种链接标准。连接标准确定观察组之间使用的距离。该算法将合并最小化该标准的簇对。“ward”最小化被合并的集群的方差;“average”使用两组中每次观察的距离的平均值;“complete”完整或最大连接使用两组的所有观察之间的最大距离;“single”使用两组所有观测值之间的最小距离。 |
connectivity : array-like or callable, optional | 连通矩阵。为每个样本定义遵循给定数据结构的相邻样本。这可以是连接矩阵本身,也可以是将数据转换为连接矩阵的可调用,例如从kneighbors_graph派生的。默认值为None,即层次聚类算法是非结构化的。 |
本案例使用球形数据和月牙形数据以及加入噪声点的数据,使用不同的邻近性方法构建凝聚层次聚类带来的效果:
由上图可知
- 对于
Ward
方法,使用的是方差,对球形数据的效果不错,但是对月牙形数据就不好了;- 对于
complete
方法,使用的是最大值,对于球形数据基本不行,对于月牙形效果很好,但是假如噪声后,效果就不行,可见此方法受噪声的影响;- 对于
average
方法,使用的是平均值,效果和最大值方法一样。
代码可见:07_层次聚类(AGNES)算法采用不同距离计算策略.py
BIRCH
算法(平衡迭代削减聚类法):是一种非常有效的聚类技术,用于欧几里得向量空间数据,即平均值有意义的数据。BIRCH
能够用一遍扫描有效地对这种数据进行聚类,并可以使用附加的扫描改进聚类。BIRCH
还能有效地处理离群点。BIRCH
基于聚类特征和聚类特征树的概念。基本思想是:数据点的簇可以用三元组 ( N , L S , S S ) (N,LS,SS) (N,LS,SS)表示:
BIRCH
算法通过构建满足 分枝因子和簇直径限制 的聚类特征树来求聚类,聚类特征树其实是一个具有两个参数分枝因子和类直径的高度平衡树;分枝因子规定了树的每个节点的子女的最多个数,而类直径体现了对这一类点的距离范围;非叶子节点为它子女的最大特征值;聚类特征树的构建可以是动态过程的,可以随时根据数据对模型进行更新操作。
优缺点:
- 适合大规模数据集,线性效率;
- 只适合分布呈凸形或者球形的数据集、需要给定聚类个数和簇之间的相关参数;
案例:
本案例使用BIRCH
中不同的参数,比较模型效果以及消耗时间
运行结果:
Birch算法,参数信息为:直径=1.7;n_lusters=None;模型构建消耗时间为:2.432秒;聚类中心数目:171
Birch算法,参数信息为:直径=0.5;n_clusters=None;模型构建消耗时间为:6.250秒;聚类中心数目:3205
Birch算法,参数信息为:直径=1.7;n_lusters=100;模型构建消耗时间为:2.529秒;聚类中心数目:100
结果表示,设置合理的参数,可以很好的聚类数据
代码可见:08_层次聚类(BIRCH)算法参数比较.py
CURE
算法(使用代表点的聚类法):该算法先把每个数据点看成一类,然后合并距离最近的类直至类个数为所要求的个数为止,但是和 AGNES
算法的区别是:取消了使用所有点或用中心点+距离来表示一个类,而是从每个类中抽取固定数量、分布较好的点作为此类的代表点,并将这些代表点乘以一个适当的收缩因子,使它们更加靠近类中心点。CURE
使用簇中的多个代表点来表示一个簇:
代表点的收缩特性可以调整模型可以匹配那些非球形的场景,而且收缩因子的使用可以减少噪音对聚类的影响。
优缺点:
- 能够处理非球形分布的应用场景
- 采用随机抽样和分区的方式可以提高算法的执行效率
\quad\quad 基于密度的聚类寻找被低密度区域分离的高密度区域。这里我们只介绍 DBSCAN
算法,它是一种简单、有效的基于密度的聚类算法。
DBSCAN
相比于基于划分的聚类方法和层次聚类方法,DBSCAN
算法将簇定义为密度相连的点的最大集合,能够将足够高密度的区域划分为簇,并且在具有噪声的空间数据商能够发现任意形状的簇。
DBSCAN
算法的核心思想是:用一个点的 ε ε ε 邻域内的邻居点数衡量该点所在空间的密度,该算法可以找出形状不规则的 c l u s t e r cluster cluster,而且聚类的时候事先不需要给定 c l u s t e r cluster cluster 的数量。
直接密度可达:该点在核心点的领域类,那么就说该点从核心点出发直接密度可达,如下图, x 2 x_2 x2 由 x 1 x_1 x1直接密度可达;
密度可达:如果存在一个对象链 p 1 , p 2 , . . . , p m p_1,p_2,...,p_m p1,p2,...,pm 如果满足 p i + 1 p_{i+1} pi+1是从 p i p_i pi 直接密度可达的,那么称 p m p_m pm 是从 p 1 p_1 p1 密度可达的,如下图, x 3 x_3 x3 由 x 1 x_1 x1密度可达;
密度相连:在集合 X X X中,如果存在一个对象 o o o,使得对象 x x x 和 y y y 是从 o o o 关于 ε ε ε 和 m m m 密度可达的,那么对象 x x x 和 y y y 是关于 ε ε ε 和 m m m 密度相连的,如下图, x 3 x_3 x3 与 x 4 x_4 x4密度相连。
簇(cluster):一个基于密度的簇是最大的密度相连对象的集合C;满足以下两个条件:
- Maximality:若x属于C,而且y是从x密度可达的,那么y也属于C
- Connectivity:若x属于C,y也属于C,则x和y是密度相连的
DBSCAN
算法DBSCAN
算法可以描述如下:任意两个足够靠近的点(相互之间的距离在 E p s Eps Eps之内)的核心点将放在同一个簇中;同样,任何与核心点足够靠近的边界点也放到与核心点相同的簇中,噪声点被丢弃。(如果一个边界点靠近不同簇的核心,则可能需要解决平局问题)
算法如下:
DBSCAN
算法优缺点优点:
缺点:
DBSCAN
算法聚类效果依赖距离公式的选取,最常用的距离公式为欧几里得距离。但是对于高维数据,由于维数太多,距离的度量已变得不是那么重要,密度定义更加困难DBSCAN
算法不适合数据集中密度差异很小的情况DBSCAN
算法案例使用 sklearn
库中 DBSCAN
类,API如下:
sklearn.cluster.DBSCAN(eps=0.5, min_samples=5, metric=’euclidean’,
metric_params=None, algorithm=’auto’, leaf_size=30, p=None, n_jobs=None)
常用参数说明:
参数 | 描述 |
---|---|
eps : float, optional | 前面提到的 Eps |
min_samples : int, optional | 前面提到的 MinPts |
本案例使用球形数据和环形数据,通过设定不同的 ε 和 m 参数,比较效果
有图1可看出,密度聚类对于密度变化不大,且有重叠的数据的效果不好,两个簇有重叠很容易被聚类为同一个簇
由图2可看出,设置合适的参数,可以很好的聚类环形嵌套的数据
代码可见:09_密度聚类(DBSCAN)算法案例.py
\quad\quad 谱聚类
是基于谱图理论基础上的一种聚类方法,与传统的聚类方法相比:具有在任意形状的样本空间上聚类并且收敛于全局最优解的优点。
通过对样本数据的 拉普拉斯矩阵的特征向量 进行聚类,从而达到对样本数据进行聚类的目的;其本质是 将聚类问题转换为图的最优划分问题 ,是一种点对聚类算法。
谱聚类算法将数据集中的每个对象看做图的顶点V,将顶点间的相似度量化为相应顶点连接边E的权值w,这样就构成了一个基于相似度的无向加权图G(V,E),于是聚类问题就转换为图的划分问题。基于图的最优划分规则就是子图内的相似度最大,子图间的相似度最小。
使用 sklearn
库中spectral_clustering
类,API如下:
spectral_clustering(affinity, n_clusters=8, n_components=None, eigen_solver=None,
random_state=None, n_init=10, eigen_tol=0.0, assign_labels=’kmeans’)
常用参数说明:
参数 | 描述 |
---|---|
affinity | 亲和度矩阵描述样本与嵌入的关系。必须是对称的。 |
n_clusters | 簇的数目 |
assign_labels : {‘kmeans’,‘discretize’},默认:‘kmeans’ | 用于在嵌入空间中分配标签的策略 |
本案例使用球形数据和环形数据,通过设定不同的 σ 参数,比较效果
图1可见,通过设定适当的参数,谱聚类可以将球形数据很好的聚类
图2可见,当σ为0.06,0.16和0.40时,效果很好,因此谱聚类也可以对环形数据很好地聚类
代码可见:10_谱聚类(SC)算法案例.py
由上图可以看出
- 对于环形数据,密度聚类与谱聚类可以聚类成功,但是谱聚类的执行效率比较低;
- 对于月牙形数据,除了
K-Means
、Mini Batch K-Means
和Brich
效果不行,其他都可以,谱聚类执行效率最低,密度聚类最好;- 对于球形数据,
AC-average
和密度聚类不行,其他都可以,求Mini Batch K-Means
执行效率最高,谱聚类执行效率低;- 对于随机数据,有些算法也会强行将其划分为两个簇。
从上面我们可以看出,虽然谱聚类算法效果比较好,但是执行效率比较低,所以一般不使用。在实际工作中使用最多的还是 K-means
,对于有些数据我们可以先对数据进行一些预处理,使其满足 K-means
对数据的要求,比如,可以将数据映射到高维空间使其成为明显分离的数据。
代码可见:11_不同聚类算法比较.py
代码可见:12_基于K-means算法进行图片压缩.py