K均值算法的改进Word格式文档下载.docx
- 文档编号:20017379
- 上传时间:2023-01-15
- 格式:DOCX
- 页数:13
- 大小:91.89KB
K均值算法的改进Word格式文档下载.docx
《K均值算法的改进Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《K均值算法的改进Word格式文档下载.docx(13页珍藏版)》请在冰豆网上搜索。
1)根据程序随机数表随机选取;
2)选择特殊的样本作为初始质心;
(通过对小样本树聚类获取)
3)将所有的样本之间的距离进行排列,然后选择将这些距离差不多等分的样本作为质心;
4)选择使得类间距离最大的样本作为质心;
5)选择任意k个样本作为质心,对于任意一个非质心样本,计算它与各质心的距离,找到与它最近的质心c,若它与c的距离大于质心对的最小距离,或者大于c与其它质心的最小距离,则它与c互换,即它为新的质心成员,而c则为一般对象;
对于K-均值算法,K值的确定也是很重要的,如果K值太大,则不能很好的计算聚类的数据点,使得计算精度减小;
但是如果K值太小,则不能很好的将所有数据点分类,而且计算过程相对也会复杂。
K值的确定一般通过下面方法:
(1)在较小的集合上通过树聚类得到;
(2)在经过多维比例尺变换降维后的低维空间里,进行树聚类得到。
3.1.3算法程序
我们将K-均值算法用c++程序写出来如下:
#include<
iostream>
#include<
cstdio>
cmath>
usingnamespacestd;
Intx[][];
X[10][3]={{2,1,5},{3,0,6},{1,8,2},{6,3,9},{2,5,0},{1,4,6},{3,1,5},{7,1,2},{3,6,8},{2,1,9}};
doublestartcenter[3][3];
//定义初始质心坐标数组
doublemidcenter[3][3];
//定义计算过程中得到的质点坐标数组
intclass[10];
//这10个点分别属于的类的存放数组
intcenter;
//记录与当前点最近的质心的编号
intmindist(doublex,doubley,doublez)
{
if(x<
=y&
&
x<
=z)return0;
if(y<
x&
y<
=z)return1;
if(z<
z<
y)return2;
}
doubledistA(inti,intj)//计算两个点的距离,返回当前点到质点的距离
doubledistx,disty,distz,dist;
distx=(double)x[i][0]-(double)midcenter[j][0];
disty=(double)x[i][1]-(double)midcenter[j][1];
distz=(double)x[i][2]-(double)midcenter[j][2];
dist=sqrt(distx*distx+disty*disty+distz*distz);
returndist;
}
intmain()
intcount[3];
//记录每种类的个数
inti,j;
doubledist[3];
//求坐标点距离3个质点距离时用到的变量
doublecenL,cenLx,cenLy,cenLz;
//求初始中间质点距离的时候用到的变量
cout<
<
“The10pointsare:
”<
“”;
//把所有点的坐标打印一遍
for(i=0;
i<
10;
i++)
cout<
x[i][0]<
“”<
x[i][1]<
x[i][2]<
for(i=0;
3;
i++)//给原始和中间的质点赋初值。
for(j=0;
j<
j++)
{
midcenter[i][j]=(double)x[i][j];
startcenter[i][j]=-999.0;
}
i++)//最前面的3个点作为初始的质点。
class[i]=i;
//假设第i个点属于第i类
while
(1)//退出条件是初始中间质点的距离小于0.001
i++)//给记录每一类的个数的数组赋初值
count[i]=0;
i++)//对10个点分别计算到质点的距离。
dist[j]=distA(i,j);
center=minDist(dist[0],dist[1],dist[2]);
//求距离最小值,返回距离最小的对应的质点坐标。
class[i]=center;
//将这个点归到距离最小的那一类。
count[center]++;
//这一类(编号为center)数目加1
i++)//中间质点的坐标复制到初始质点数组中
startcenter[i][j]=midcenter[i][j];
i++)//对新质点坐标赋初值,进行下面的计算。
j++)midcenter[i][j]=0.0;
i++)//对每一类的坐标点计算其坐标之和。
j++)midcenter[class[i]][j]+=x[i][j];
i++)//坐标之和除以count数组元素,即得质点坐标
midcenter[i][j]=midcenter[i][j]/count[i];
intflag=0;
//标志
i++)//求初始中间质点的距离
cenLx=midcenter[i][0]-startcenter[i][0];
cenLy=midcenter[i][1]-startcenter[i][1];
cenLz=midcenter[i][2]-startcenter[i][2];
cenL=sqrt(cenLx*cenLx+cenLy*cenLy+cenLz*cenLz);
if(cenL>
0.001)//只要有一个距离过大,重新开始循环
{flag=1;
}
if(flag!
=1)//只有当标志未被设置,退出while循环。
{break;
i++)//打印10个点各自所属的类。
{cout<
“point”<
“:
”<
“,”<
“,”<
“belongstoclass”<
class[i]<
endl;
getchar();
return0;
此程序的运行结果是将10个点划分到不同的类中,输出为点属于的类。
3.2算法分析
3.2.1优点
(1)时间复杂度与样本数量线性相关,所以,对于处理大数据集合,该算法非常高效,且伸缩性较好;
(2)当潜在的簇形状是凸面的,簇与簇之间区别较明显,且簇大小相近时,其聚类结果较理想。
(3)该方法确定的K个划分达到的平方误差最小。
3.2.2缺点
(1)K-均值算法试图找到使平方误差函数最小的簇,需要事先指定聚类数目;
(2)当潜在的簇形状不是凸面的时候,且簇大小相差明显时,其聚类结果很差;
(3)其对初始聚类中心敏感比较敏感,经常以局部最优结束,不合适的初始值不能得到满意的聚类结果;
(4)该方法对“噪声”和孤立点敏感。
如下图所示:
该算法对噪声很明显。
图3.2带离群点的聚类
图3.3离群点对聚类的影响
3.3改进后的算法
3.3.1改进说明
由于传统的K-均值聚类算法的质心是随机选择的,因此对于有的数据来说该算法容易达到局部收敛从而影响到整个过程的聚类,因此,我们这里提出的改进聚类算法旨在改变算法选取初始质心的方法,选择更理想的初始聚类质心。
下面是改进的算法步骤:
Step1:
从m个样本中选择k个质心,选择质心的过程依据cs算法的过程:
第t次迭代的第i个质心,通过Levy飞行,产生下一次迭代的初始质心
,有
(13)
其中
是点对点乘法,
就是一个步长大小服从Levy分布的随机游走,可以表示为
(14)
此处,具体的步长大小是利用Mantegna法则来实现的。
Step2:
将数据集当中每一个
代表的聚类中,得到每一种聚类的一个质心及属于这个质心的类,并且计算所有点到相应质心的距离的平方和
,保存所有的质心;
Step3:
循环过程Step1,利用Step1的过程继续产生不同的质心,接着进行Step2,将计算出的
与前面的
比较,选择最小的
保存在
中。
当
小于某个给定的值时停止循环,进入Step4;
Step4:
在分配完成后,重复执行上述过程,如果质心发生变化,则继续计算新质心以及E值;
Step5:
重复执行新计算的E值与上一次迭代得到的E值之间的差别小于一个给定的阈值;
Step6:
程序结束,得到数据点及所属质心。
3.3.2改进算法程序
此部分程序利用了opencv来做数据显示,编译语言为c++语言。
ctime>
usingnamespacestd;
voidKmeans(float*pSamples,int*pclusterResult,intclusterNum,intsampleNum,intfeatureNum,intAttempTimes=1,int*pInitCenter=NULL);
voidmyKmeans(float*pSamples,int*pClusterResult,intclusterNum,intsampleNum,intfeatureNum,intAttempTimes,int*pInitCenter)
inti,j,k,t;
intIterationTimes;
//当前迭代次数
doubleMinDistance;
//与聚类中心的最小距离
intcurrentCategory;
//当前点的类别
doubleVarSum;
//平方误差和
doubleLastVarSum;
//上一次的平方误差和
doubleminVarSum;
//最小平方误差和
intclusterEmpty;
//是否有空类
intbestCluster;
intMaxIterationTimes=200;
//最大迭代次数
doubleEpslion=0.001;
//聚类停止误差
float*pCenters=newfloat[clusterNum*featureNum];
//聚类中心
float*pBestCenters=newfloat[clusterNum*featureNum];
int*pEveryTimesResult=newint[sampleNum*AttempTimes];
double*pSum=newdouble[clusterNum*featureNum];
//用于计算聚类中心
int*pNum=newint[clusterNum];
//每类的数目
memset(pClusterResult,0,sampleNum*sizeof(int));
if(NULL==pInitCenter)
{srand((unsignedint)time(NULL));
intindex_temp=rand()%sampleNum;
for(i=0;
clusterNum;
{for(j=0;
featureNum;
{pCenters[i*featureNum+j]=pSamples[index_temp*featureNum+j];
index_temp+=(sampleNum/clusterNum);
if(index_temp>
=sampleNum)
{index_temp%=sampleNum;
}}}
else
{for(i=0;
{pCenters[i*featureNum+j]=pSamples[pInitCenter[i]*featureNum+j];
}}}
for(t=0;
t<
AttempTimes;
t++)
{if(0!
=t)//初始化聚类中心
IterationTimes=0;
VarSum=0;
LastVarSum=0;
clusterEmpty=0;
while
(1)
{boolhasEmpty=false;
IterationTimes++;
{pSum[i*featureNum+j]=0;
pNum[i]=0;
sampleNum;
{for(k=0;
k<
k++)//计算当前点属于哪一类
{doubledistance_temp=0;
j++){distance_temp+=(double)((double)(pCenters[k*featureNum+j]-pSamples[i*featureNum+j])*(pCenters[k*featureNum+j]-pSamples[i*featureNum+j]));
if(0==k||MinDistance>
distance_temp){
MinDistance=distance_temp;
currentCategory=k;
}}
pClusterResult[i]=currentCategory;
pEveryTimesResult[i*AttempTimes+t]=currentCategory;
VarSum+=sqrtl(MinDistance);
//开方防止超出存储长度
pNum[currentCategory]++;
//用于计算新的聚类中心
for(j=0;
{pSum[currentCategory*featureNum+j]+=pSamples[i*featureNum+j];
{for(j=0;
{if(pNum[i]!
=0){pCenters[i*featureNum+j]=pSum[i*featureNum+j]/(float)(pNum[i]);
else{hasEmpty=true;
if(true==hasEmpty)//如果有空类,就至少还要循环两次
{clusterEmpty=2;
else{clusterEmpty=clusterEmpty-1>
=0?
clusterEmpty-1:
0;
}if((IterationTimes>
=MaxIterationTimes||fabsl(VarSum-LastVarSum)<
=Epslion)&
(0==clusterEmpty))
{break;
}LastVarSum=VarSum;
if(0==t||minVarSum>
VarSum)
{minVarSum=VarSum;
bestCluster=t;
{for(j=0;
j++){pBestCenters[i*featureNum+j]=pCenters[i*featureNum+j];
}}}}
delete[]pCenters;
pCenters=NULL;
delete[]pSum;
pSum=NULL;
delete[]pNum;
pNum=NULL;
delete[]pBestCenters;
pBestCenters=NULL;
if(bestCluster!
=AttempTimes-1)
{for(i=0;
{pClusterResult[i]=pEveryTimesResult[i*AttempTimes+bestCluster];
delete[]pEveryTimesResult;
pEveryTimesResult=NULL;
算法的运行结果为:
图3.5改进算法的运行结果
3.3.3改进算法的优点
(1)由于cs算法有不会陷入局部最优的特点,因此选择的初始质心是分散的,在一定程度上减少了迭代次数;
(2)改进后的算法提高了聚类结果的准确性,改善了聚类效果;
(3)在一定程度上降低了算法的迭代次数。
3.4本章小结
本章先介绍了数据挖掘中的K-均值聚类算法,利用几个点对算法的程序进行了介绍,并且分析了此聚类算法的优缺点,针对它的缺点我们加入了cs算法的Levy行走模型,调整了算法初始质心的选择。
通过改进后的算法和原始算法进行比较发现改进算法的优势。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 均值 算法 改进
![提示](https://static.bdocx.com/images/bang_tan.gif)