基于C++的最大最小聚类算法实现

一、          算法简介

1.   简介:

最大最小距离法是模式识别中一种基于试探的类聚算法,它以欧式距离为基础,取尽可能远的对象作为聚类中心。因此可以避免K-means法初值选取时可能出现的聚类种子过于临近的情况,它不仅能智能确定初试聚类种子的个数,而且提高了划分初试数据集的效率。

    该算法以欧氏距离为基础,首先初始一个样本对象作为第1个聚类中心,再选择一个与第1个聚类中心最远的样本作为第2个聚类中心,然后确定其他的聚类中心,直到无新的聚类中心产生。最后将样本按最小距离原则归入最近的类。

2.   算法流程

1)       从N个样本集中的任选取一个样本,作为第一个聚类中心z1;

2)       选取距离第一个聚类中心z1最远的样本作为第二个聚类中心z2;

3)       计算其余样本与z1、z2之间的距离,并求出它们中的最小值,即:

 

4)       若:(θ为选定的比例系数)

则相应的样本xl作为第三个聚类中心z3,转至下一步继续判断是否存在新的聚类中心,否则转至第六步;

5)       假设存在k个聚类中心,计算各样本到各个聚类中心的距离dij,并算出:

若成立,则zk+1=xl,并循环此步骤,继续判断是否有新的聚类中心存在,否则转至第六步;

6)       当判断不再有新的聚类中心存在时,将样本集按最小距离原则分到各类中去,即计算:

二、          算法实现

1.   实验数据—data.txt

文件内容

d=2 n=150

5.1  3.5

4.9  3

4.7  3.2

4.6  3.1

数据说明

第一行为特征维度数量和数据数量,此次试验是150个2维数据。数据来源于IRIS数据集的前两个特征。

 

还应该手动输入比例系数θ(0-1).

2.   输出数据—result.txt

输出数据输出实验数据聚类后的分类信息,与真实信息对比来分析程序聚类准确率。

文件内容:

0

2

0

1

0

              …

数据说明:

0,1,2依次对应表示Setosa,Versicolour,Virginica三类花。

3.   程序运行截图

Θ=0.5时:


数据被分为4类,并输出了聚类中心标号

Θ=0.6时:

                                            图2

       数据被分为3类,并输出了聚类中心标号

4.   结果分析:

将输出的result.txt文件导入EXCEL与真实信息对比计算。150个数据中有133个与真实数据的分类信息吻合,两次Θ取值,都只有83个样本正确,正确率只有55.33%

       我认为出现该结果的原因是因为样本特征选取不够,IRIS花瓣集前两个特征差异性不大。如图,为前两个特征的散点分布图有较多重合。在我的另一组测试数据中,当样本间距够大时能达到很好的分类效果(但样本数量太少没有采用来作为数据集)。

图3.IRIS数据集

图4.另一组数据集

              在这个数据集下表现良好,数据都能完美分开,但数量太少,不作过多讨论

5.   C++源码:

#include <iostream>  
#include <math.h>  
using namespace std;

const int N=150;//给定N个样本

int maxmindistance(float *sample[N],float theta)  
{ 
	int center[20];//保存聚类中心  
	float D[20][N];//保存D点与点之间的距离  

	float min[N];  //始终保存各点到各个聚类中心最小的距离
	int minindex[N];  

	int clas[N];  

	float theshold;  
	float D12=0.0;//第一个聚类和第二个聚类中的距离  
	float tmp=0;  
	int index=0;  
	center[0]=0;//first center第一个聚类选出来了  
	int i,k=0,j,m;  


	//计算其他样本到第一个聚类中心(0,0)的距离  
	//D[0][j]保存第j个点到到第1个聚类中心的距离
	for(j=0;j<N;j++)  
	{ 
		tmp=(sample[0][j]-sample[0][0])*(sample[0][j]-sample[0][0])+(sample[1][j]-sample[1][0])*(sample[1][j]-sample[1][0]);  
		D[0][j]=(float)sqrt(tmp);  
		if(D[0][j]>D12)
		{
			D12=D[0][j];
			index=j;
		}  //求出距离第一个聚类中心最远的点
	}  



	center[1]=index;//second center第二个聚类中心选出来了 并保存 
	k=1;  
	index=0;  
	theshold=D12;//两个聚类中心的距离 
	//最新的两聚类中心距离大于θ*D12则继续选取聚类中心
	while(theshold>theta*D12)  
	{  
		for(j=0;j<N;j++)
		{  
			tmp=(sample[0][j]-sample[0][center[k]])*(sample[0][j]-sample[0][center[k]])+  
				(sample[1][j]-sample[1][center[k]])*(sample[1][j]-sample[1][center[k]]);  
			D[k][j]=(float)sqrt(tmp);
		}  
		for(j=0;j<N;j++)
		{  
			float tmp=D12;      //8.944
			for(m=0;m<=k;m++)  
				if (D[m][j]<tmp) 
				{
					tmp=D[m][j];
					index=m;
				}  
				min[j]=tmp;           
				minindex[j]=index;    
				/*D[N][j]保存的是j点到第n-1个聚类中心的距离,
				从其中找出最小的并保存
				min[]始终保存各点到各个聚类中心最小的距离
				*/

		}//min-operate  
		float max=0;index=0;  
		for(j=0;j<N;j++)  
			if(min[j]>max) 
			{
				max=min[j];      //找到最大的
				index=j;         //并找到相应的点的下标
			}  
			if (max>theta*D12)
			{
				k++;
				center[k]=index;
			}// add a center  
			theshold=max;// prepare to loop next time  
	}  //求出所有中心,final array min[] is still useful  

	for(j=0;j<N;j++)  
		clas[j]=minindex[j];  

	//cout<<"原始数据信息:"<<endl;
	//for(i=0;i<2;i++)  //输出原来的坐标
	//{
	//	cout<<"维度"<<i+1<<"       ";
	//	for(j=0;j<N;j++)  
	//		cout<<sample[i][j]<<"  ";  
	//	cout<<"\n";  
	//}  

	cout<<"聚类中心数:"<<"k="<<k+1<<" ";  
	cout<<"聚类中心点依次是:";  
	for(m=0;m<k;m++) 
		cout<<center[m]+1<<"--";
	cout<<center[k]+1;
	cout<<"\n";  

	FILE *fp2;
	if((fp2=fopen("result.txt","w"))==NULL) {
		printf("File cannot be opened/n");
		exit(0);
	}
	cout<<"分类信息如下:"<<endl;
	for(j=0;j<N;j++)
	{	
		cout<<"("<<sample[0][j]<<","<<sample[1][j]<<")"<<"-------";
		cout<<clas[j]<<endl;
		fprintf(fp2,"%d \n",clas[j]);//写入文件
	}
	cout<<"\n";  
	return k;
}


//动态创建二维数组
float **array(int m,int n)
{
	int i;
	float **p;
	p=(float **)malloc(m*sizeof(float *));
	p[0]=(float *)malloc(m*n*sizeof(float));
	for(i=1;i<m;i++)    p[i]=p[i-1]+n;
	return p;
}
//d代表数据维度  n数据数目
float **loadData()//从文件中读取数据
{
	int i,j; 
	float **arraydata;
	float **arraydata2;
	FILE *fp;
	int d,n;
	if((fp=fopen("data.txt","r"))==NULL)    fprintf(stderr,"cannot open data.txt!\n");
	if(fscanf(fp,"d=%d n=%d\n",&d,&n)!=2)        fprintf(stderr,"load error!\n");
	arraydata=array(d,n);  //生成数据数组
	arraydata2=array(n,d);
	for(i=0;i<n;i++)
		for(j=0;j<d;j++)
		{
			fscanf(fp,"%f",&arraydata2[i][j]);  //读取数据点
			arraydata[j][i]=arraydata2[i][j];
		}
	return arraydata;
}

int main()
{
	/*float s[2][N]={{0,3,2,1,5,4,6,5,6,7},  //特征1
				  {0,8,2,1,3,8,3,4,4,5}};  //特征2*/

	float **data;
	data=loadData();
	float theta;
	cin>>theta;
	maxmindistance(data,theta);
}




  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 点云欧式聚类算法(Euclidean Clustering)是一种对点云数据进行聚类的方法。该算法基于欧式距离的度量,将空间中距离较近的点划分为同一个聚类簇。 具体实现过程如下: 1. 首先,将点云中的每个点初始化为一个单独的聚类簇。 2. 对于每个点p,计算其与其它点之间的欧式距离,并将距离小于给定阈值的点归为同一聚类簇。 3. 对于每个已经归类的点集合,再次计算其内部点的欧式距离,并将距离小于阈值的点归为同一聚类簇。 4. 重复上述步骤,直到所有的点都被归类为止。 该算法的优点是简单易懂,适用于处理大规模点云数据。其缺点是对于非球形的聚类结构效果不佳,对于噪声点和密度变化较大的区域也较为敏感。 在实际应用中,可以根据点云数据的特点和实际需求进行算法的优化。例如,可以通过调整欧式距离的阈值,改变聚类的粒度;还可以结合其他的特征(如法向量、颜色等)来进行综合聚类分析,提高算法的准确性。 总之,点云欧式聚类算法是一种简洁有效的点云数据处理方法,可以用于点云分析、三维重建、目标检测等领域,有着广泛的应用前景。 ### 回答2: 点云欧式聚类算法c是一种用于处理点云数据的聚类算法。点云是一种由大量离散点组成的三维数据,常用于地图建模、机器人导航等领域。点云欧式聚类算法c的目标是将点云数据进行聚类,将相似的点分组在一起。 该算法的具体步骤如下: 1. 输入:点云数据集 2. 随机选择一个点作为初始种子点 3. 计算该种子点到其他所有点的欧式距离,并将距离小于预设阈值的点归为同一聚类 4. 对于新添加到聚类中的点,重复第3步,直到没有新的点加入 5. 从未聚类的点中随机选取一个作为新的种子点,重复第3步至第4步,直到所有的点都被聚类 点云欧式聚类算法c的关键在于欧式距离的计算。欧式距离是两个点之间的直线距离,可以通过计算两点在三维空间中的坐标差值并求平方和再开方得到。该聚类算法通过比较点与点之间的距离,将距离小于阈值的点进行聚类。 该算法的优点是简单且易于实现,能够较好地处理点云数据中的离群点。但是该算法需要预先设置阈值,对于不同的点云数据集,阈值的选择会有一定难度。另外,该算法对初始种子点的选择也较为敏感,对于不同的初始种子点,可能会得到不同的聚类结果。 综上所述,点云欧式聚类算法c是一种用于点云数据聚类的简单算法,通过计算点与点之间的欧式距离,将距离小于阈值的点进行聚类。但是在实际应用中,需要注意阈值和初始种子点的选择。 ### 回答3: 点云欧式聚类算法 C 是一种用于点云数据的聚类算法。点云数据是由大量的点构成的三维数据,常用于三维重建、虚拟现实等领域的数据处理。 该算法的基本思想是利用欧式距离来度量点之间的相似度,并将相似度高的点划分为同一个类别。首先,选择一个初始点作为聚类的种子点,然后计算其他点与该种子点的欧式距离,将距离小于设定阈值的点加入到该类别中。接着,从该聚类中选择一个未被标记的点作为新的种子点,重复上述过程,直到所有的点都被聚类。 具体实现中,可以通过遍历所有点并计算其与其他点的欧式距离,将距离小于阈值的点加入到同一个类别中。为了提高计算效率,可以使用空间索引结构(如kd-tree)来加速搜索过程。聚类过程中,可以使用标记数组来记录每个点的类别,避免重复聚类。 点云欧式聚类算法 C 的优点是简单易用,对于具有凸性质的数据集聚类效果良好。然而,在处理具有噪声、密度差异较大的数据集时,该算法容易受到参数选择和初始点选择的影响,可能出现聚类错误的情况。 总而言之,点云欧式聚类算法 C 是一种基于欧式距离的简单聚类方法,适用于处理具有凸性质的点云数据。在实际应用中,需要根据具体数据集的特点选择合适的参数和初始点,以获得良好的聚类效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值