聚类分析,即聚类(Clustering),是指在一大推数据中采用某种方式或准则来将一些具有相同或相似性质和特征的数据划分为一类。聚类是无监督学习的典型算法,相较于有监督学习,由于聚类针对的大多是无标签数据,因此对于最终构建的模型而言,在进行模型评估时会比较麻烦。同时,在对算法进行调参时也会因为这种不确定性而稍带困难。
聚类算法的分类有:
划分法
划分法(Partitioning Methods),给定一个有N个元组或者纪录的数据集,分裂法将构造K个分组,每一个分组就代表一个聚类,K小于N。而且这K个分组满足下列条件:
(1)每一个分组至少包含一个数据纪录;
(2)每一个数据纪录属于且仅属于一个分组(注意:这个要求在某些模糊聚类算法中可以放宽);
层次法
层次法(Hierarchical Methods),这种方法对给定的数据集进行层次似的分解,直到某种条件满足为止。具体又可分为“自底向上”和“自顶向下”两种方案。例如,在“自底向上”方案中,初始时每一个数据纪录都组成一个单独的组,在接下来的迭代中,它把那些相互邻近的组合并成一个组,直到所有的记录组成一个分组或者某个条件满足为止。
密度算法
基于密度的方法(Density-Based Methods),基于密度的方法与其它方法的一个根本区别是:它不是基于各种各样的距离的,而是基于密度的。这样就能克服基于距离的算法只能发现“类圆形”的聚类的缺点。
图论聚类法
图论聚类方法解决的第一步是建立与问题相适应的图,图的节点对应于被分析数据的最小单元,图的边(或弧)对应于最小处理单元数据之间的相似性度量。因此,每一个最小处理单元数据之间都会有一个度量表达,这就确保了数据的局部特性比较易于处理。图论聚类法是以样本数据的局域连接特征作为聚类的主要信息源,因而其主要优点是易于处理局部数据的特性。
网格算法
基于网格的方法(Grid-Based Methods),这种方法首先将数据空间划分成为有限个单元(cell)的网格结构,所有的处理都是以单个的单元为对象的。这么处理的一个突出的优点就是处理速度很快,通常这是与目标数据库中记录的个数无关的,它只与把数据空间分为多少个单元有关。
代表算法有:STING算法、CLIQUE算法、WAVE-CLUSTER算法;
模型算法
基于模型的方法(Model-Based Methods),基于模型的方法给每一个聚类假定一个模型,然后去寻找能够很好的满足这个模型的数据集。这样一个模型可能是数据点在空间中的密度分布函数或者其它。它的一个潜在的假定就是:目标数据集是由一系列的概率分布所决定的。
通常有两种尝试方向:基于统计、基于神经网络。
世间万物,皆为混沌。为此,人类世界经历了原始社会、奴隶社会、封建社会、资本主义社会到共产主义社会,这是人类社会从低级到高级的发展过程。但从哲学的角度看来,这实际上是一种从无序到有序的过程。人类社会如此,数学亦是如此。
数字的无穷尽给它的使用带来了极大不便,为此,在一维空间建立了“数轴”,以将这些数字按序列在一条直线上,既便于比较也便于查找与定位,如:。一维空间最经典的用例,莫过于尺子:用以测量长度。但是地图的出现让人们陷入苦恼,要如何精准地定位一个人的位置呢?“坐标轴”似乎是一个可行的方案:通过在二维平面中,额外增加一条与一维空间中的数轴所垂直的纵向数轴,便能建立一个能海纳百川的空间,此时可用 (, ) 定位任意位置。二维空间最典型的用例,莫过于用于进行全球定位的经纬度。在建筑、设计类软件中,处理目标更多的是立体图形,此时,二维空间便显得余力不足。很自然地想到,可采取从一维到二维的相同提升方式,即添加一条与二维平面相垂直的数轴,这样一来就能构建一个涵盖三维空间全部位置的坐标轴,以达到从二维空间到三维空间的提升,此时可用 (, , ) 定位任意位置。
现在让我们回忆下不同空间中与距离相关的一些定义:
有关(内)积的定义:
在二维及以上空间,基于两点 (1, 2, … , ) , (1, 2, … , ) 可定义一个具有方向的指标,称其为向量,则可得到:
ξ ⃗ = { a 1 , a 2 , … , a n } = { x 1 , x 2 , … , x n } − { y 1 , y 2 , … , y n } = { x 1 − y 1 , x 2 − y 2 , … , x n − y n } \vec{\xi} = \{ a_1, a_2, … ,a_n \} = \{ x_1, x_2, …, x_n \} - \{ y_1, y_2, …, y_n \} = \{ x_1 - y_1, x_2 - y_2, …, x_n - y_n \} ξ={a1,a2,…,an}={x1,x2,…,xn}−{y1,y2,…,yn}={x1−y1,x2−y2,…,xn−yn}
对于高维空间,定义两向量的内积为: ξ ⃗ ⋅ η ⃗ = ∑ i = 1 n a i b i = a 1 b 1 + a 2 b 2 + … + a n b n \vec{\xi}·\vec{\eta}=\sum_{i=1}^na_ib_i=a_1b_1+a_2b_2+…+a_nb_n ξ⋅η=∑i=1naibi=a1b1+a2b2+…+anbn 这个内积和两点之间的内积算法是一致的。
有时候,我们需要通过两个向量之间的夹角来判断与其相关的一些性质,为此定义了方向余弦,其定义为:
c o s θ = ξ ⃗ ⋅ η ⃗ ∣ ξ ⃗ ∣ ⋅ ∣ η ⃗ ∣ cos \theta=\frac{\vec{\xi}·\vec{\eta}}{|\vec{\xi}|·|\vec{\eta}|} cosθ=∣ξ∣⋅∣η∣ξ⋅η
以上就是在低维空间(一维、二维、三维)构建的一系列“秩序”,以帮助我们理解与使用,而高维空间却因它的抽象性显得较有难度。但是,依然可采取与前面的相同的思路来进行拓展。此时,若将在低纬空间总结的有关距离、(内)积、角相关的定理推广至有限的更高维空间,那这些符合定义的空间则被统称为欧几里得空间(亦即欧式空间,Euclidean Space)。
K-Means 算法是一种典型的基于划分的聚类算法,它的核心思想是:若将指定数据集的特征投影至 n 维欧氏空间,则数据之间的相似性应当与这些数据的欧氏距离成反比。说简单点就是:越相似的数据,彼此之间离得越近。
其算法流程如下:首先从数据集中随机选取 个初始聚类中心 (1 ≤ ≤ ) ,接下来对每个其余数据对象,均计算出该数据对象与 个聚类中心的的欧式距离,并将离目标数据对象最近的聚类中心 作为该数据对象所属的类别。经过这样一次迭代,就完成了一次 K-Means 聚类。接着计算每个簇中数据对象的平均值作为新的聚类中心,进行下一次迭代,直到聚类中心不再变化或达到最大的迭代次数时停止。
上图给出了 K-Means 算法的执行流程(通过观察,显然可将该数据集划分为 2 类,因此取 k = 2):
(a) 算法开始,将指定数据集的特征投影至 n 维欧氏空间;
(b) 随机选取 k = 2 个初始聚类中心;
(c) 对任意数据 x() ,算出其与 k 个聚类中心的欧式距离,取其中距离最近的那个类簇作为数据 x() 的所属类别(第一次 k-means);
(d) 基于新的类簇分布,算出每个簇中数据对象的平均值作为新的聚类中心;
(e) 对任意数据 x() ,算出其与 k 个聚类中心的欧式距离,取其中距离最近的那个类簇作为数据 x() 的所属类别(第二次 k-means);
(f) 基于新的类簇分布,算出每个簇中数据对象的平均值作为新的聚类中心;
(f) 之后,算法将执行第三次 k-means,接着当再次计算新的类簇中心时,会发现类簇中心不再发生变化(或变化
范围很小),此时算法停止并返回最终的分类结果。
总的来看,K-Means 算法需要预先指定初始类簇个数和聚类中心,然后再按照样本与类簇中心的距离进行归类与迭代更新。在迭代过程中, K-Means 算法会不断降低各类簇的误差平方和SSE(Sum of Squared Error,SSE),当SSE不再变化或目标函数收敛时,聚类结束,得到最终结果。下面给出 K-Means 算法计算某个数据对象 () 与某类簇中心 的欧氏距离公式:
d i s t a n c e ( x ( i ) , C j ) = ∑ t − 1 m ( x t ( i ) − C j t ) 2 distance \left( x^{(i)},C_j \right)=\sqrt{\sum_{t-1}^m{\left( x_t^{(i)}-C_{jt} \right)^2}} distance(x(i),Cj)=t−1∑m(xt(i)−Cjt)2
其中, x t ( i ) x_t^{(i)} xt(i) 为第 个数据对象在第 个特征上的取值, 为第 个数据对象在第 个特征上的取值。
整个数据集的误差平方和 SSE 计算公式为(SSE的大小衡量了聚类结果的好坏):
S S E = ∑ j = 1 k ∑ x ( i ) ∈ C j ( d i s t a n c e ( x ( i ) , C j ) ) 2 SSE=\sum_{j=1}^k\sum_{x^{(i)}∈C_j} \left( distance( x^{(i)},C_j) \right)^2 SSE=j=1∑kx(i)∈Cj∑(distance(x(i),Cj))2
自此,可总结出 K-Means 算法的步骤:
① 随机选择 k 个样本作为初始簇类的均值向量
② 将每个样本数据划分给离它距离最近的簇;
③ 根据每个样本所属的簇,更新簇类的均值向量;
④ 重复 ②③ 步,当达到设置的迭代次数或类簇的均值向量不再改变时,模型构建完成,输出聚类算法结果。
K-Means 算法非常简单且使用广泛,但是主要存在以下四个缺陷:
从上图不难看出,K-Means算法对于环形簇的分类效果非常糟糕!
DBSCAN(Density-Based Spatial Clustering of Applications with Noise),翻译是“基于密度的带噪声聚类算法”,DBSCAN 将簇定义为“密度相连的点的最大集合”,它把具有足够高密度的区域划分为簇,能在带噪声的数据中发现任意形状的类簇。为理解 DBSCAN 的算法原理,下面先介绍一些相关概念(假设样本集为 = {(1), (2), … , ()}):
基于下图可以很容易理解上述定义,图中 = 4,红色的点都是核心对象,因为其 − 邻域至少有 4 个样本。黑色的样本是非核心对象。所有核心对象密度直达的样本都在以红色核心对象为中心的圆内,如果不在圆内,则不能密度直达。图中用蓝色箭头连起来的核心对象组成了密度可达的样本序列,此序列是一个簇集。在这些密度可达的样本序列的 − 邻域内所有的样本相互都是密度相连的 (注意,此图中有两个簇集)。
DBSCAN 的聚类定义很简单:由密度可达关系导出最大密度相连的样本集合,即为我们最终聚类的一个簇。簇里面可以有一个或者多个核心对象。如果只有一个核心对象,则簇里其他的非核心对象样本都在这个核心对象的 − 邻域里;如果有多个核心对象,则簇里的任意一个核心对象的 − 邻域中一定至少有一个其他核心对象,否则这两个核心对象无法密度可达。这些核心对象的 − 邻域里的所有样本集合就组成了一个DBSCAN 聚类簇。
现在我们讨论下如何根据 DBSCAN 的聚类定义来对数据集进行聚类。首先,在样本集中选出所有的核心对象并构成一个集合 ;然后,在 中任意选择一个数据点作为根,并标记该数据点作为一个新类簇;接下来,寻找所有这个核心对象能够密度可达的样本集合,并将这个集合中的所有点都归类到根所在类簇中,这便找到了一个类(这样得到的所有数据点肯定都是密度相连的)。之后,不断按这样的方式寻找新类簇,直到集合 中的所有核心对象都有类别为止。最终,剩余未被归类的数据点即被称为“噪声点”或“离群点”。因此,DBSCAN 算法也可用于识
别噪声点。
基于以上讨论,下面给出 DBSCAN 算法的具体流程:
① 初始化核心对象集合 = ∅ ,待查子集合 = ∅ ,初始化类簇个数 = 0;
② 遍历样本集 的元素,如果是核心对象,则将其加入到核心对象集合 中;
③ 接下来遍历核心对象集 ;
④ 若核心对象集 中所有元素都已被访问,则算法结束,否则转入步骤 ⑤;
⑤ 在核心对象集 中,随机选择一个未被访问的核心对象 。首先将其标记为已访问,然后将 所属类别标记为 ,最后再将 的 − 邻域中的所有未被访问数据存放到待查子集合 中;
⑥ 如果待查子集合 = ∅,则当前类簇 生成完毕,令 = + 1,并跳转到 ③。否则,从待查子集合 中选出一个数据点 。首先将其标记为已访问,并标记所属类别为 ,然后判断 是否为核心对象,如果是,则将 包含的未被访问的数据点加入到待查子集合 中,并跳转到 ⑥。
上图展示了 DBSCAN 算法的执行流程(图中 =4):
输出所有类簇:0、1。
DBSCAN 算法不是一个完全稳定的算法。例如某些样本可能到两个核心对象的距离都小于 ,但是,由于这两个核心对象不是密度直达,且又不属于同一个类簇,那么如果界定这些样本的类别呢?此时,DBSCAN 通常会采用先来后到的准则,即在算法执行过程中,这些样本先被归到哪一类则最终就隶属于那一类。所以,同一数据集在 DBSCAN 的执行过程中,某些样本最终的归类并不一定严格一致。
DBSCAN 的主要优点:
DBSCAN 的主要缺点: