当前位置: 首页 > 科技观察

用Python进行系统的聚类分析_0

时间:2023-03-17 20:54:19 科技观察

在进行机器学习的时候,我们经常需要对数据进行聚类分析。聚类,说白了就是对相似的样本点/数据点进行分类,将相似度高的样本点放在一起,从而将一个样本分成几类。聚类分析的方法也有很多,如分解法、加法、有序样本聚类、模糊聚类法和系统聚类法等。本文要介绍的是系统聚类方法以及如何使用python进行系统聚类分析。首先,让我们看一下系统聚类方法的定义。层次聚类法又称层次聚类法,是目前最常用的聚类分析方法。基本步骤如下:假设样本中有n个样本,那么首先将这n个样本视为n个类,即一个样本为一类,然后将属性最接近的两个类合并为一个newclass,这样得到n-1个类,然后找到最接近的两个类,让它们合并,这样就变成了n-2个类,让这个过程继续下去,最后所有的样本都归为一类,画出上图处理成一个图,这个图称为聚类图,然后从图中决定分成多少类。大致流程如图1所示。图1系统聚类分析示意图这里我们需要先判断每个样本的相似度,然后才能对它们进行分类,那么如何判断它们的相似度呢?通常我们采用的方法是计算每个样本点之间的距离,然后根据距离进行分类。这里我们按照距离来分类,还有最短距离法、最长距离法、重心法、类平均法、沃德法等几种方法。下面我们对这些方法进行简要介绍。1.最短距离法最短距离法是从两个类中找出距离最短的两个样本点,如图2所示。点3和点7分别是类G1和类G2中距离最短的两个点。计算公式如图4所示。图2.最短距离法示意图2.最长距离法最长距离法是从两个类中找出距离最长的两个样本点,如图3所示。1和点6是G1类和G2类中距离最长的两个点。计算公式如图4所示。图3.最长距离法示意图3.重心法从物理的角度来看,一个类使用它的重心是比较合理的,即均值类样本的值,作为代表,类与类之间的距离也就是重心之间的距离。如果样本之间使用欧几里德距离,则假设某个步骤将类G1和G2组合成G3,每个类有n1、n2和n3个样本,其中n3=n1+n2,它们的重心分别用X1、X2、X3表示,则X3=1/n3(n1X1+n2X2)。重心法的计算公式见图4。4.类平均法,顾名思义,就是对两个类之间所有点的距离取平均值。计算公式如图4所示。图4常用的距离计算方法5.偏差平方和法偏差平方和法也称为Ward法。类之间的平方差之和应该很大。计算公式如图4所示。在了解了系统聚类方法的基本知识后,我们将通过python代码来展示系统聚类方法的具体使用。首先,导入各种库。importnumpyasnpfrommatplotlibimportpyplotaspltfromscipy.cluster.hierarchyimportdendrogram,linkage下一步是生成数据集。我们这次使用的数据集是随机生成的,数量并不多。总共有15个数据点,分为两个数据簇,一个有7个数据点,另一个有8个数据点。之所以数据点数设置的这么少,是为了方便看数据的分布,后面画图的时候也方便看图片的分类。代码如下所示。state=np.random.RandomState(99)#设置随机状态a=state.multivariate_normal([10,10],[[1,3],[3,11]],size=7)#生成多个正态变量b=state.multivariate_normal([-10,-10],[[1,3],[3,11]],size=8)data=np.concatenate((a,b))#在这里拼接数据我们设置一个随机状态,以方便重复实验。然后用这个随机状态生成两个变量a和b,这两个变量就是上面说的数据簇,a有7个数据点,b有8个,a和b是多元正态变量,其中a的均值向量为[10,10],b的均值向量为[-10,-10],两者的协方差矩阵为[[1,3],[3,11]]。这里要注意协方差矩阵应该是正定矩阵或者半正定矩阵。然后将a和b拼接得到可变数据。下一步是绘制数据点的分布。代码如下所示。fig,ax=plt.subplots(figsize=(8,8))#设置图片大小ax.set_aspect('equal')#设置两个坐标轴的比例相等plt.scatter(data[:,0],data[:,1])plt.ylim([-30,30])#设置Y轴取值范围plt.xlim([-30,30])plt.show()这里的代码比较简单,就不细说了,主要看一下ax.set_aspect('equal')这行代码,因为matplotlib中x轴和y轴的比例默认是不一样的,即单位长度相同的线段在显示时的长度是不同的,所以两者的比例设置为前者相同,这样画面看起来更协调,更准确。绘制的图片如图5所示,从图中可以清楚的看到两个数据簇。上面的数据簇很可能集中在坐标点[10,10]附近,而下面的数据簇很可能集中在[-10,-10]附近,这和我们的设置是一样的。从图中可以清楚的看出,这个数据集大致可以分为两类,即上层的数据簇分为一类,下层的数据簇又分为另一类,但是我们还需要计算它通过算法。图5.使用到的数据分布图及之后的数据处理,代码如下。z=linkage(data,"average")#使用average算法,即类average方法的数据处理只有这行代码,很简单,但这就是难点所在。首先我们看一下z的结果,如图6所示。图6.聚类计算结果很多人第一次看到这个结果的时候都会一头雾水,甚至是n面的,其实背后的道理很简单。Scipy官方对此有一些设置。例如,结果第一行有4个数字,分别是11、13、0.14740505、2。前两个数字指的是“类”。一开始每个点都是一个类,所以11和13这两个点是两个类,第三个数0.14740505是这两点之间的距离,这两个点合并为一个类,所以这个新的类包含两个点(11和13),这是第四个点的值2,这个新的类算作第15类。注意这里是第15类,不是第15类,因为我们原来的数据集中有15个点,分别是class0,class1,class2...class14依次为,因为python是从0开始的,所以这里的class15指的是第16类。在z的第二行数据中,前两个数字是2和5,分别是原来的2类和5类,距离为0.3131184,包括2个点。这行数据与第一行类似。然后看第三行数据。前两个数字是10和15,分别是10班和15班。15班是前面第一行合并后形成的新班级。它包含11和13这两个点。Class15和class15class10的距离是0.39165998,也就是classes11和13和class10的平均距离,因为我们这里用的算法是average,classes10,11和13合并成一个新的类,这个类包含3个点,所以前四位是3。z中其他行的数据都可以按照这个规则推导出来。在最后一行数据中,第26类和第27类合并为一个新类,包含所有15个点,即这15个点最终被归为一类,算法终止。接下来就是画图了,代码如下,结果如图7所示fig,ax=plt.subplots(figsize=(8,8))dendrogram(z,leaf_font_size=14)#drawingplt.title("HierachialClusteringDendrogram")plt.xlabel("Clusterlabel")plt.ylabel("Distance")plt.axhline(y=10)#绘制分类线plt.show()图7.聚类结果图如可以从图中可以看出,这15个点可以分为两类,前面绿线连接的点代表一类,即0点到6点的7个点,红线连接的点后面的线代表第二类,即第7点到第14点的8个点。可以看到这个划分的结果是非常正确的,和我们当时的设置是一样的。系统聚类方法算法比较简单,具有较高的实用性。它是目前使用最广泛的聚类方法,但是这种方法在处理大量数据时会力不从心,所以最好结合其他算法使用。用户在使用时应根据自身情况选择合适的距离计算方式。本文主要使用类平均法进行聚类操作,因为这个数据集很简单,所以用其他距离计算方法得到的结果和这个是一样的。如果数据量比较大,不同的距离计算方式得到的最终结果可能不同,所以用户要根据自己的情况做出选择。