基于密度的聚类方法

摘要:我们生活在数据大爆炸时代,每时每刻都在产生海量的数据如视频,文本,图像和等。由于数据的类型和大小已经超出了人们传统手工处理的能力范围,聚类,作为一种最常见的无监督学习技术,可以帮助人们给数据自动打标签,已经获得了广泛应用。基于密度的聚类是根据样本的密度分布来进行聚类。通常情况下,密度聚类从样本密度的角度出来,来考查样本之间的可连接性,并基于可连接样本不断扩展聚类簇,以获得最终的聚类结果。其中最著名的算法就是 DBSCAN 算法。本文将对基于密度的聚类算法做简单的介绍。

关键词:聚类算法  基于密度  DBSCAN算法  OPTICS算法

1、关于聚类的总体介绍

1.1 聚类算法的来源

俗话说:“物以类聚,人以群分”,在自然科学和社会科学中,存在着大量的分类问题。所谓类,通俗地说,就是指相似元素的集合。

聚类分析起源于分类学,在古老的分类学中,人们主要依靠经验和专业知识来实现分类,很少利用数学工具进行定量的分类。随着人类科学技术的发展,对分类的要求越来越高,以致有时仅凭经验和专业知识难以确切地进行分类,于是人们逐渐地把数学工具引用到了分类学中,形成了数值分类学,之后又将多元分析的技术引入到数值分类学形成了聚类分析。聚类分析内容非常丰富,有系统聚类法、有序样品聚类法、动态聚类法、模糊聚类法、图论聚类法、聚类预报法等。

1.2 聚类算法的用途

聚类的用途是很广泛的。在文本分析处理上,聚类可以帮助新闻工作者把最新的微博,按照话题相似度进行分类,而快速得出热点新闻和关注对象。在生物医学上,可以根据对相似表达谱的基因进行聚类,从而知道未知基因的功能。在商业上,聚类可以帮助市场分析人员从消费者数据库中区分出不同的消费群体来,并且概括出每一类消费者的消费模式或者说习惯。它作为数据挖掘中的一个模块,可以作为一个单独的工具以发现数据库中分布的一些深层的信息,并且概括出每一类的特点,或者把注意力放在某一个特定的类上以作进一步的分析;并且,聚类分析也可以作为数据挖掘算法中其他分析算法的一个预处理步骤。

聚类的目的就是把不同的数据点,按照它们的相似与相异度分割成不同的簇(注意:簇,就是把数据划分后的子集),确保每个簇中的数据都是尽可能相似,使不同簇的数据尽可能的相异。从模式识别的角度来讲,聚类就是在发现数据中潜在的模式,帮助人们进行分组归类以达到更好理解数据的分布规律。由于聚类是无监督学习方法,不同的聚类方法基于不同的假设和数据类型,由于数据通常可以以不同的角度进行归类,因此没有万能的通用聚类算法,并且每一种聚类算法都有其局限性和偏见性。也就是说某种聚类算法可能在市场数据上效果很棒,但是在基因数据上就无能为力了。

1.3 聚类算法的分类

   聚类是机器学习中一种重要的无监督算法,它可以将数据点归结为一系列特定的组合。理论上归为一类的数据点具有相同的特性,而不同类别的数据点则具有各不相同的属性。在数据科学中聚类会从数据中发掘出很多分析和理解的视角,让我们更深入的把握数据资源的价值、并据此指导生产生活。以下是五种常用的聚类算法。

1.3.1 K均值聚类

这一最著名的聚类算法主要基于数据点之间的均值和与聚类中心的聚类迭代而成。它主要的优点是十分的高效,由于只需要计算数据点与剧类中心的距离,其计算复杂度只有O(n)。其工作原理主要分为以下四步:

1.首先我们需要预先给定聚类的数目同时随机初始化聚类中心。我们可以初略的观察数据并给出较为准确的聚类数目;

2.每一个数据点通过计算与聚类中心的距离了来分类到最邻近的一类中;

3.根据分类结果,利用分类后的数据点重新计算聚类中心;

4.重复步骤二三直到聚类中心不再变化。(可以随机初始化不同的聚类中心以选取最好的结果)

这种方法在理解和实现上都十分简单,但缺点却也十分明显,十分依赖于初始给定的聚类数目;同时随机初始化可能会生成不同的聚类效果,所以它缺乏重复性和连续性。和K均值类似的K中值算法,在计算过程中利用中值来计算聚类中心,使得局外点对它的影响大大减弱;但每一次循环计算中值矢量带来了计算速度的大大下降。

1.3.2均值漂移算法

这是一种基于滑动窗口的均值算法,用于寻找数据点中密度最大的区域。其目标是找出每一个类的中心点,并通过计算滑窗内点的均值更新滑窗的中心点。最终消除临近重复值的影响并形成中心点,找到其对应的类别。

1.首先以随机选取的点为圆心r为半径做一个圆形的滑窗。其目标是找出数据点中密度最高点并作为中心;

2.在每个迭代后滑动窗口的中心将为想着较高密度的方向移动;

3.连续移动,直到任何方向的移动都不能增加滑窗中点的数量,此时滑窗收敛;

4.将上述步骤在多个滑窗上进行以覆盖所有的点。当过个滑窗收敛重叠时,其经过的点将会通过其滑窗聚类为一个类;

与K均值相比最大的优点是我们无需指定聚类数目,聚类中心处于最高密度处也是符合直觉认知的结果。但其最大的缺点在于滑窗大小r的选取,对于结果有着很大的影响。

1.3.3基于密度的聚类算法(DBSCAN)

DBSCAN同样是基于密度的聚类算法,但其原理却与均值漂移大不相同:

1.首先从没有被遍历的任一点开始,利用邻域距离epsilon来获取周围点;

2.如果邻域内点的数量满足阈值则此点成为核心点并以此开始新一类的聚类。(如果不是则标记为噪声);

3.其邻域内的所有点也属于同一类,将所有的邻域内点以epsilon为半径进行步骤二的计算;

4.重复步骤二、三直到变量完所有核心点的邻域点;

5.此类聚类完成,同时又从任意未遍历点开始步骤一到四直到所有数据点都被处理;最终每个数据点都有自己的归属类别或者属于噪声。

这种方法最大的优点在于无需定义类的数量,其次可以识别出局外点和噪声点、并且可以对任意形状的数据进行聚类。

但也存在不可回避的缺点,当数据密度变化剧烈时,不同类别的密度阈值点和领域半径会产生很大的变化。同时在高维空间中准确估计领域半径也是不小的挑战。

1.3.4利用高斯混合模型进行最大期望估计

对于较为复杂的分布K均值将会产生如下图般较为离谱的聚类结果。而高斯混合模型却具有更高的灵活性。通过假设数据点符合均值和标准差描述的高斯混合模型来实现的。下图以二维情况下为例描述了如何利用最大期望优化算法来获取分布参数的过程:

1.首先确定聚类的数量,并随机初始化每一个聚类的高斯分布参数;

2.通过计算每一个点属于高斯分布的概率来进行聚类。与高斯中心越近的点越有可能属于这个类;

3.基于上一步数据点的概率权重,通过最大似然估计的方法计算出每一类数据点最有可能属于这一聚类的高斯参数;

4.基于新的高斯参数,重新估计每一点归属各类的概率,重复并充分2,3步骤直到参数不再变化收敛为止。

在使用高斯混合模型时有两个关键的地方,首先高斯混合模型十分灵活,可以拟合任意形状的椭圆;其次这是一种基于概率的算法,每个点可以拥有属于多类的概率,支持混合属性。

1.3.5凝聚层次聚类

层次聚类法主要有自顶向下和自底向上两种方式。其中自底向上的方式,最初将每个点看作是独立的类别,随后通过一步步的凝聚最后形成独立的一大类,并包含所有的数据点。这会形成一个树形结构,并在这一过程中形成聚类。

1.首先将每一个数据点看成一个类别,通过计算点与点之间的距离将距离近的点归为一个子类,作为下一次聚类的基础;

2.每一次迭代将两个元素聚类成一个,上述的子类中距离最近的两两又合并为新的子类。最相近的都被合并在一起;

3.重复步骤二直到所有的类别都合并为一个根节点。基于此我们可以选择我们需要聚类的数目,并根据树来进行选择。

层次聚类无需事先指定类的数目,并且对于距离的度量不敏感。这种方法最好的应用在于恢复出数据的层次化结构。但其计算复杂度比较高

每个聚类算法都有各自的优缺点,我们需要根据计算需求和应用需求选择合适的算法来进行处理。随着深度学习的出现,更多的神经网络、自编码器被用来提取数据中的高维特征用于分类,是值得注意的研究热点。

2、基于密度的聚类算法的具体介绍

基于密度的算法是聚类算法的一种,基于密度的方法与其它方法的一个根本区别是:它不是基于各种各样的距离的,而是基于密度的。这样就能克服基于距离的算法只能发现“类圆形”的聚类的缺点。这个方法的指导思想就是,只要一个区域中的点的密度大过某个阈值,就把它加到与之相近的聚类中去。代表算法有:DBSCAN算法、OPTICS算法、DENCLUE算法等;

2.1 DBSCAN算法

2.1.1 DBSCAN中的几个定义:

Ε邻域:给定对象半径为Ε内的区域称为该对象的Ε邻域;

核心对象:如果给定对象Ε领域内的样本点数大于等于MinPts,则称该对象为核心对象;

直接密度可达:对于样本集合D,如果样本点q在p的Ε领域内,并且p为核心对象,那么对象q从对象p直接密度可达。

密度可达:对于样本集合D,给定一串样本点p1, p2,…,pn,p=p1, q=pn,假如对象pi从pi-1直接密度可达,那么对象q从对象p密度可达。

密度相连:存在样本集合D中的一点o,如果对象o到对象p和对象q都是密度可达的,那么p和q密度相联。

可以发现,密度可达是直接密度可达的传递闭包,并且这种关系是非对称的。密度相连是对称关系。DBSCAN目的是找到密度相连对象的最大集合。

Eg: 假设半径Ε=3,MinPts=3,点p的E领域中有点{m,p,p1,p2,o}, 点m的E领域中有点{m,q,p,m1,m2},点q的E领域中有点{q,m},点o的E领域中有点{o,p,s},点s的E领域中有点{o,s,s1}。那么核心对象有p,m,o,s(q不是核心对象,因为它对应的E领域中点数量等于2,小于MinPts=3);点m从点p直接密度可达,因为m在p的E领域内,并且p为核心对象;点q从点p密度可达,因为点q从点m直接密度可达,并且点m从点p直接密度可达;点q到点s密度相连,因为点q从点p密度可达,并且s从点p密度可达。

2.1.2算法步骤

1、以每一个数据点xi为圆心,以 eps 为半径画一个圆圈。这个圆圈被称为 xi的 eps 邻域

2、对这个圆圈内包含的点进行计数。如果一个圆圈里面的点的数目超过了密度阈值 MinPts,那么将该圆圈的圆心记为核心点,又称核心对象。如果某个点的 eps 邻域内点的个数小于密度阈值但是落在核心点的邻域内,则称该点为边界点。既不是核心点也不是边界点的点,就是噪声点。

3、核心点 xi的 eps 邻域内的所有的点,都是 xi 的直接密度直达。如果 xj由 xi密度直达,xk 由 xj 密度直达,xn 由 xk密度直达,那么,xn 由 xi密度可达。这个性质说明了由密度直达的传递性,可以推导出密度可达。

4、如果对于xk,使 xi 和xj都可以由 xk 密度可达,那么,就称 xi 和 xj密度相连。将密度相连的点连接在一起,就形成了我们的聚类簇。【1】

2.1.3算法优点:

1. 与K-means方法相比,DBSCAN不需要事先知道要形成的簇类的数量。

2. 与K-means方法相比,DBSCAN可以发现任意形状的簇类。

3. 同时,DBSCAN能够识别出噪声点。对离群点有较好的鲁棒性,甚至可以检测离群点。

4.DBSCAN对于数据库中样本的顺序不敏感,即Pattern的输入顺序对结果的影响不大。但是,对于处理簇类之间边界样本,可能会根据哪个簇类优先被探测到而其归属有所摆动。

5.DBSCAN被设计与数据库一同使用,可以加速区域的查询。

2.1.4算法缺点:

1. DBSCAN不能很好反映高维数据。

2. DBSCAN不能很好反映数据集以变化的密度。

3.由于DBSCAN算法直接对整个数据集进行操作,并且在聚类之前需要建立相应的R*树,并绘制k-dist图,因此算法所需的内存空间和I/O消耗都相当可观。在计算资源有限而数据量又非常庞大的情况下,DBSCAN算法的效率将受到很大影响。(DBSCAN算法将区域查询得到的所有未被处理过的点都作为种子点,留待下一步扩展处理。对于大规模数据集中的较大类而言,这种策略会使种子点的数目不断膨胀,算法所需的内存空间也会快速增加。)

4.由于DBSCAN算法使用了全局性表征密度的参数,因此当各个类的密度不均匀,或类间的距离相差很大时,聚类的质量较差。(当各个类的密度不均匀、或类间的距离相差很大时,如果根据密度较高的类选取较小的Eps值,那么密度相对较低的类中的对象Eps 邻域中的点数将小Minpts,则这些点将会被错当成边界点,从而不被用于所在类的进一步扩展,因此导致密度较低的类被划分成多个性质相似的类。与此相反,如果根据密度较低的类来选取较大的Eps值,则会导致离得较近而密度较大的类被合并,而它们之间的差异被忽略。所以在上述情况下,很难选取一个合适的全局Eps值来获得比较准确的聚类结果。)

5.DBSCAN不是完全确定的,边界点从不同的簇中获得,可以使不同簇的一部分,取决于数据处理。

6.DBSCAN的质量取决于regionQuery(P,Eps)函数中距离的测量。最常用的距离度量是欧式距离,尤其是在高维数据中,由于所谓的维数灾难,这种度量基本上是无用的,很难为E找到一个恰当的值。虽然目前有一些基于欧式距离的算法,但是如果不能对数据和规模有很好的了解,也很难找一个有意义的距离阈值E。

7.当密度差异大时,由于选取的MinPts-Eps组合不能同时适合所有的簇,DBSACN不能很好的进行数据聚类。

8.输入参数敏感,确定参数Eps , MinPts困难 ,若选取不当 ,将造成聚类质量下降。

9.由于经典的DBSCAN算法中参数Eps和MinPts在聚类过程中是不变的,使得该算法难以适应密度不均匀的数据集.

2.1.5算法改进

1. 对缺点3的改进:通过选用核心点邻域中的部分点作为种子点来扩展类,从而大大减少区域查询的次数,降低I/O开销,实现快速聚类。

2.对缺点4的改进:为了解决上述问题,周水庚等人提出了PDBSCAN ( Partitioning-based DBSCAN)算法。该算法基于数据分区技术来扩展DBSCAN算法,它根据数据的分布特性,将整个数据空间划分为多个较小的分区,然后分别对这些局部分区进行聚类,最后将各个局部的聚类结果进行合并。 PDBSCAN 的算法思想是:首先,根据数据集在某一维或多个维上的分布特性,将整个数据空间划分为若干个局部区域,使得各局部区域内的数据尽可能分布均匀;然后依次绘制各个局部区域的k-dist图,并依次得到各个区域的Eps值,接着用 DBSCAN 算法对各个局部区域进行局部聚类;最后,将各个局部聚类的结果进行合并,从而完成整个数据集的聚类分析。由于每个局部区域都使用各自的局部Eps值来进行聚类,因此有效缓解了因使用全局Eps值而导致的聚类质量恶化的问题。

3.缺点8改进:

DBSCAN 算法的改进,输入参数的处理:针对 DBSCAN算法对输入参数(聚类半径Eps , 聚类点数 MinPts) 敏感问题 ,作如下处理。由于参数的设置通常是依赖经验 , 当数据密度相差较大和类间距离分布不均匀时 ,很难选取一个合适的 Eps 值来进行聚类且得到比较准确的结果 . 因此 , 事先确定算法的参数值大小是不可取的 ,应在聚类过程中根据聚类结果的好坏对参数进行适当的调整。比如选择适当的评价函数作为评价聚类结果的尺度。反复调整算法的参数 ,重新聚类 ,直到聚类结果满足要求。尽管DBSCAN算法提供了利用绘制降序k-距离图的可视化方法来选择Eps ,选定的Eps值已经比较接近“理想”值 ; 但常有微小差距 , 最终造成聚类结果的相差很大。可以考虑采用如下方法来加以改善 :

(1)可以对所有聚类对象按照从一个簇到另一个簇 ,按簇边缘→簇核心→簇边缘的顺序排序。这样,该对象序列就可以反映出数据空间基于密度的簇结构信息。基于这些信息可以容易地确定合适的Eps值 ,并随之发现各个簇。

(2)不对原始数据集进行聚类 ,而是通过从数据集合中抽取高密度点生成新的数据集合,并修改密度参数 ,反复进行这一过程 , 直到生成的数据集合可以很容易地被聚类为止,然后以此结果为基础,再将其它点逐层地吸附到各个类中。这样,就避免了DBSCAN算法中输入参数对聚类结果的影响。

(3)采用核聚类的思想对样本集进行非线性变换,使样本集的分布尽可能地均匀,经过核函数的映射使原来没有显现的特征突现出来,然后再用全局参量Eps ,从而能够更好地聚类 , 得到较好的结果 .

(4)在绝大多数聚类结果不理想的情况下,是Eps值选择过小,导致本应为一个簇的对象集合被分析成了多个子簇。被分开的子簇共享一些对象 ,可以认为子簇通过这些共享的对象相互连接。而DBSCAN算法将子簇的连接信息简单地丢掉 。因此,可以通过记录下所有的簇连接信息,由用户根据实际的聚类结果和连接信息,将被错误分开的子簇合并。这样可以提高聚类的效果,而输入参数Eps的变化对聚类结果的影响,就被最后的合并过程屏蔽掉。可以考虑以下两种方式进行改进 :

 1)并行化.

从DBSCAN算法可以看出,全局变量Eps值影响了聚类质量,尤其是数据分布不均匀时.因此,考虑对数据进行划分,每一个划分中的数据分布相对较均匀 ,根据每个划分中数据的分布密集程度来选取Eps值.这样一方面降低了全局变量Eps值的影响,另一方面由于具有多个划分 ,因此考虑并行处理 ,从而提高聚类效率 ,也降低了DBSCAN算法对内存的较高要求

2)增量式处理。

 当数据增加或者删除时,只考虑其增加或删除的数据所影响到的那些类 。 这种方法在处理大数据集时非常有效,不需要重新对数据库中的数据进行聚类,只需要对类进行渐进性地更新,修正和加强已发现的类。另外,由于高维数据的复杂性,使聚类分析的效率和实用性都很差。通过确定聚类空间中和聚类主题相关性较强的数据维,来降低聚类空间的维度。利用数据降维可以降低数据结构上的复杂性。目前,有多种降维技术均可用于特征空间的削减。在方法的选择上应根据降维后,信息丢失率在可接收范围内 ,来选择一种合适的降维方法。

4.对缺点9改进:

(1)自适应选择 Eps 参数

对于不均匀数据分布,各个数据与周围数据的相似程度不同,因此,针对每个点,将距离该点最近的多个点的距离平均值作为该点处的稠密程度的评判标准,即对任意一点P,根据距离矩阵,选取与P点最近的k个点,计算距离的平均值.此时,每个点都能够得出一个k最近点平均距离.然后对所有点的一维k最近点平均距离数据进行DBSCAN聚类。再对聚类结果中每类 i找到其最大平均距离的点.最后将该点与它的第k点的距离作为该类的邻域阈值Epsi ,并将其保存以备聚类.这种发现Eps的方法主要考虑到对于不同密度的数据集,应根据各个数据的稠密程度,分别选取合适的阈值进行聚类.由于聚类中所采用的参数Eps只能够确定聚类结果中同一类数据中的密度差别,所以,参数选取所引起的误差不会对聚类结果产生很大影响.

(2)基于变参数的 DBSCAN 聚类

1)将(1)中得出的邻域阈值Epsi按照由小到大的顺序排列,准备聚类;

2)选取最小的邻域阈值,MinPts可以不变,对数据进行DBSCAN聚类;

3)然后使用下一个邻域阈值和MinPts作为参数,对标注为噪声的数据再次进行 DBSCAN聚类;

4)不断循环,直到所有邻域阈值均使用完毕,聚类结束.

在多次聚类过程中,邻域阈值要由小到大进行聚类.使用较小阈值进行聚类时,距离较大的类中的数据由于不满足该阈值而不被处理到,所以较小的距离阈值只能处理密度较大的点,不会对小密度数据产生影响。

2.1.6实验仿真

以下为了更好的说明,进行数据仿真实验,为了更方便的得到数据且能够说明问题,采用鼠标取点的方式生成数据集,取点时注意尽量集中取点,能够更好的说明问题。实验中取点结果如下。

密度聚类 特征向量 python 密度聚类算法例题_密度聚类 特征向量 python

可以观察到取点大概分为4个数据集,下面我们通过DBSCAN算法实现数据点的聚类,得到结果如下。

密度聚类 特征向量 python 密度聚类算法例题_基于密度的聚类算法_02

在上面的结果中,红色的点代表的是噪音点,点代表的是边界点,十字代表的是核心点。不同的颜色代表着不同的类。

2.2 OPTICS算法【2】

2.2.1算法简介

在前面介绍的DBSCAN算法中,有两个初始参数Eps(邻域半径)和MinPts (E邻域最小点数)需要用户手动设置输入,并且聚类的类簇结果对这两个参数的取值非常敏感,不同的取值将产生不同的聚类结果,其实这也是大多数其他需要初始化参数聚类算法的弊端。为了克服DBSCAN算法这一缺点,提出了OPTICS算法。OPTICS并 不显示的产生结果类簇,而是为聚类分析生成一个增广的簇排序(比如,以可达距离为纵轴,样本点输出次序为横轴的坐标图),这个排序代表了各样本点基于密度的聚类结构。它包含的信息等价于从一个广泛的参数设置所获得的基于密度的聚类,换句话说,从这个排序中可以得到基于任何参数Eps和MinPts的DBSCAN算法的聚类结果。

2.2.2 OPTICS两个概念

核心距离:

对象p的核心距离是指是p成为核心对象的最小E’。如果p不是核心对象,那么p的核心距离没有任何意义。

可达距离:

对象q到对象p的可达距离是指p的核心距离和p与q之间欧几里得距离之间的较大值。如果p不是核心对象,p和q之间的可达距离没有意义。

例如:假设邻域半径Eps=2, MinPts=3,存在点A(2,3),B(2,4),C(1,4),D(1,3),E(2,2),F(3,2)

点A为核心对象,在A的E领域中有点{A,B,C,D,E,F},其中A的核心距离为E,=1,因为在点A的E,邻域中有点{A,B,D,E}>3;

点F到核心对象点A的可达距离为2^(1/2),因为A到F的欧几里得距离2^(1/2),大于点A的核心距离1。

2.2.3算法描述

输入:样本集D, 邻域半径Eps, 给定点在Eps领域内成为核心对象的最小领域点数MinPts

输出:具有可达距离信息的样本点输出排序

方法:

1、创建两个队列,有序队列和结果队列。(有序队列用来存储核心对象及其该核心对象的直接可达对象,并按可达距离升序排列;结果队列用来存储样本点的输出次序。你可以把有序队列里面放的理解为待处理的数据,而结果队列里放的是已经处理完的数据);

2、如果所有样本集D中所有点都处理完毕,则算法结束。否则,选择一个未处理(即不在结果队列中)且为核心对象的样本点,找到其所有直接密度可达样本点,如过该样本点不存在于结果队列中,则将其放入有序队列中,并按可达距离排序;

3、如果有序队列为空,则跳至步骤2(重新选取处理数据)。否则,从有序队列中取出第一个样本点(即可达距离最小的样本点)进行拓展,并将取出的样本点保存至结果队列中(如果它不存在结果队列当中的话)。然后进行下面的处理。

3.1.判断该拓展点是否是核心对象,如果不是,回到步骤3(因为它不是核心对象,所以无法进行扩展了。那么就回到步骤3里面,取最小的。这里要注意,第二次取不是取第二小的,因为第一小的已经放到了结果队列中了,所以第二小的就变成第一小的了。)。如果该点是核心对象,则找到该拓展点所有的直接密度可达点;

3.2.判断该直接密度可达样本点是否已经存在结果队列,是则不处理,否则下一步;

3.3.如果有序队列中已经存在该直接密度可达点,如果此时新的可达距离小于旧的可达距离,则用新可达距离取代旧可达距离,有序队列重新排序(因为一个对象可能直接由多个核心对象可达,因此,可达距离近的肯定是更好的选择);

3.4.如果有序队列中不存在该直接密度可达样本点,则插入该点,并对有序队列重新排序;

4、迭代2,3。

5、算法结束,输出结果队列中的有序样本点。

3、小结

本文对聚类算法中基于密度的聚类算法进行了总结学习。首先是对聚类算法作了大概的研究与阐述,给出聚类算法的来源、用途、分类等,然后重点写了基于密度的聚类算法中的DBSCAN算法和OPTICS算法,包括其相关定义、主要思想、算法过程等。通过对相关知识的学习以及对这篇论文的撰写,我对基于密度的聚类算法有了更加深刻的认识。

参考文献

【1】周志华,《机器学习》。

【2】Ankerst, M., Breunig, M. M., Kriegel, H.P., & Sander, J. (1999, June). OPTICS: ordering points to identify theclustering structure. In ACM Sigmod record (Vol. 28, No. 2, pp. 49-60). ACM.

附录

function [ dis ] = calDistance( x )%% 计算矩阵中点与点之间的距离
    [m,n] = size(x);
    dis = zeros(m,m);
   
    for i = 1:m
        for j = i:m
            %计算点i和点j之间的欧式距离
            tmp =0;
            for k = 1:n
                tmp = tmp+(x(i,k)-x(j,k)).^2;
            end
            dis(i,j) = sqrt(tmp);
            dis(j,i) = dis(i,j);
        end
    end
end
 
 
function [Eps]=epsilon(x,k)
 [m,n]=size(x);
 
Eps=((prod(max(x)-min(x))*k*gamma(.5*n+1))/(m*sqrt(pi.^n))).^(1/n);


主体程序
clear all;
clc;
close all%为了更方便的采集数据,采用鼠标取点,采点尽量集中
fp = fopen('data.txt','w');
[x,y] = ginput();
data=[x y];
fclose(fp);
figure
scatter(x,y);
% 定义参数Eps和MinPts
MinPts = 5;
Eps = epsilon(data, MinPts);
[m,n] = size(data);%得到数据的大小
x = [(1:m)' data];
[m,n] = size(x);%重新计算数据集的大小
types = zeros(1,m);%用于区分核心点1,边界点0和噪音点-1
dealed = zeros(m,1);%用于判断该点是否处理过,0表示未处理过
dis = calDistance(x(:,2:n));
number = 1;%用于标记类
 
% 对每一个点进行处理
for i = 1:m
    %找到未处理的点
    if dealed(i) == 0
        xTemp = x(i,:);
        D = dis(i,:);%取得第i个点到其他所有点的距离
        ind = find(D<=Eps);%找到半径Eps内的所有点
        % 区分点的类型
        if length(ind) > 1 && length(ind) < MinPts+1 %边界点
            types(i) = 0;
            class(i) = 0;
        end
        if length(ind) == 1%噪音点
            types(i) = -1;
            class(i) = -1;
            dealed(i) = 1;
        end
        if length(ind) >= MinPts+1 %核心点(此处是关键步骤)
            types(xTemp(1,1)) = 1;
            class(ind) = number;
           
            % 判断核心点是否密度可达
            while ~isempty(ind)
                yTemp = x(ind(1),:);
                dealed(ind(1)) = 1;
                ind(1) = [];
                D = dis(yTemp(1,1),:);%找到与ind(1)之间的距离
                ind_1 = find(D<=Eps);
                if length(ind_1)>1%处理非噪音点
                    class(ind_1) = number;
                    if length(ind_1) >= MinPts+1
                        types(yTemp(1,1)) = 1;
                    else
                        types(yTemp(1,1)) = 0;
                    end 
                    for j=1:length(ind_1)
                       if dealed(ind_1(j)) == 0
                          dealed(ind_1(j)) = 1;
                          ind=[ind ind_1(j)];  
                          class(ind_1(j))=number;
                       end                   
                   end
                end
            end
            number = number + 1;
        end
    end
end
% 最后处理所有未分类的点为噪音点
ind_2 = find(class==0);
class(ind_2) = -1;
types(ind_2) = -1;
 
figure% 画出最终的聚类图
hold on
for i = 1:m
    if class(i) == -1
        plot(data(i,1),data(i,2),'.r');
    elseif class(i) == 1
        if types(i) == 1
            plot(data(i,1),data(i,2),'+b');
        else
            plot(data(i,1),data(i,2),'.b');
        end
    elseif class(i) == 2
        if types(i) == 1
            plot(data(i,1),data(i,2),'+g');
        else
            plot(data(i,1),data(i,2),'.g');
        end
    elseif class(i) == 3
        if types(i) == 1
            plot(data(i,1),data(i,2),'+c');
        else
            plot(data(i,1),data(i,2),'.c');
        end
    else
        if types(i) == 1
            plot(data(i,1),data(i,2),'+k');
        else
            plot(data(i,1),data(i,2),'.k');
        end
    end
end
hold off