模糊C均值聚类算法(原理+Matlab代码)

电子常识

2587人已加入

描述

  聚类分析是多元统计分析的一种,也是无监督模式识别的一个重要分支,在模式分类 图像处理和模糊规则处理等众多领域中获得最广泛的应用。它把一个没有类别标记的样本按照某种准则划分为若干子集,使相似的样本尽可能归于一类,而把不相似的样本划分到不同的类中。硬聚类把每个待识别的对象严格的划分某类中,具有非此即彼的性质,而模糊聚类建立了样本对类别的不确定描述,更能客观的反应客观世界,从而成为聚类分析的主流。

  模糊聚类算法是一种基于函数最优方法的聚类算法,使用微积分计算技术求最优代价函数,在基于概率算法的聚类方法中将使用概率密度函数,为此要假定合适的模型,模糊聚类算法的向量可以同时属于多个聚类,从而摆脱上述问题。

  模糊聚类分析算法大致可分为三类

  1)分类数不定,根据不同要求对事物进行动态聚类,此类方法是基于模糊等价矩阵聚类的,称为模糊等价矩阵动态聚类分析法。

  2)分类数给定,寻找出对事物的最佳分析方案,此类方法是基于目标函数聚类的,称为模糊C均值聚类。

  3)在摄动有意义的情况下,根据模糊相似矩阵聚类,此类方法称为基于摄动的模糊聚类分析法

  模糊的c均值聚类算法:-------- 一种模糊聚类算法,是k均值聚类算法的推广形式,隶属度取值为[0 1]区间内的任何一个数,提出的基本根据是“类内加权误差平方和最小化”准则;

  模糊C 均值聚类算法(FCM,Fuzzy c-means) 是从硬C 均值聚类算法发展而来(HCM,Hardc-means )。

  硬C划分和模糊C 划分

 模糊C均值聚类

  FCM算法原理

  模糊C均值聚类

  FCM 算法步骤

  给定聚类类别数C,设定迭代收敛条件,初始化各个聚类中心;

  (1)重复下面的运算,直到各个样本的隶属度值稳定:

  (2)用当前的聚类中心根据公式(6) 计算隶属度函数;

  A.用当前的隶属度函数根据公式(5) 重新计算各个聚类的中心。

  B.当算法收敛时,就得到了各类的聚类中心和各个样本对于各类的隶属度值,从而完成了模糊聚类划分。

  算法实现

  ·采用VC++进行编写

  文档的读取

  #include “data.h”

  //函数定义

  double **DataRead(char*name,int row,intcol)

  {

  double**p=new double* [row];

  ifstreaminfile;

  infile.open(name,ios::in);

  for(inti=0;i《row;i++)

  {

  p[i]=newdouble[col];

  for(intj=0;j《col;j++)

  {

  infile》》p[i][j];

  }

  }

  infile.close();

  cout《《“成功读取数据文件:”《《name《《“!\n”;

  returnp;

  //释放内存

  for(i=0;i《row;i++)

  {

  delete[]p[i];

  }

  delete[]p;

  }

  文档的保存

  #include “data.h”

  void DataSave(double**data,int row,intcol,char*name)

  {

  inti,j;

  ofstreamoutfile;

  //打开文件,输出数据

  outfile.open(name,ios::out);

  outfile.setf(ios::fixed);

  outfile.precision(4);

  for(i=0;i《row;i++)

  {

  for(j=0;j《col;j++)

  {

  outfile《《data[i][j]《《“”;

  }

  outfile《《endl;

  }

  outfile《《endl《《endl;

  outfile.close();

  }

  数据标准化处理

  #include “data.h”

  double **Standardize(double **data,introw,int col)

  {

  inti,j;

  double*a=new double[col]; //矩阵每列的最大值

  double*b=new double[col]; //矩阵每列的最小值

  double*c=new double[row]; //矩阵列元素

  for(i=0;i《col;i++)

  {

  //取出数据矩阵的各列元素

  for(j=0;j《row;j++)

  {

  c[j]=Data[j][i];

  }

  a[i]=c[0],b[i]=c[0];

  for(j=0;j《row;j++)

  {

  //取出该列的最大值

  if(c[j]》a[i])

  {

  a[i]=c[j];

  }

  //取出该列的最小值

  if(c[j]《b[i])

  {

  b[i]=c[j];

  }

  }

  }

  //数据标准化

  for(i=0;i《row;i++)

  {

  for(j=0;j《col;j++)

  {

  data[i][j]=(data[i][j]-b[j])/(a[j]-b[j]);

  }

  }

  cout《《“完成数据极差标准化处理!\n”;

  delete[]a;

  delete[]b;

  delete[]c;

  returndata;

  }

  生成样本虑属矩阵

  #include “data.h”

  void Initialize(double **u, int k, introw)

  {

  inti,j;

  //初始化样本隶属度矩阵

  srand(time(0));

  for(i=0;i《k;i++)

  {

  for(j=0;j《row;j++)

  {

  u[i][j]=(double)rand()/RAND_MAX;//得到一个小于1的小数隶属度

  }//rand()函数返回0和RAND_MAX之间的一个伪随机数

  }

  }

  数据归一化处理

  #include “data.h”

  void Normalize(double **u,int k,intcol)

  {

  inti,j;

  double*sum=new double[col];

  //矩阵U的各列元素之和

  for(j=0;j《col;j++)

  {

  doubledj=0;

  for(i=0;i《k;i++)

  {

  dj=dj+U[i][j];

  sum[j]=dj;//隶属度各列之和

  }

  }

  for(i=0;i《k;i++)

  {

  for(j=0;j《col;j++)

  {

  u[i][j]=U[i][j]/sum[j];

  }//规一化处理(每列隶属度之和为1)

  }

  }

  迭代过程

  #include “data.h”

  #include “func.h”//对模糊C均值进行迭代运算,并返回有效性评价函数的值

  doubleUpdate(double**u,double**data,double**center,int row,int col, int k)

  {

  inti,j,t;

  double**p=NULL;

  for(i=0;i《k;i++)

  {

  for(j=0;j《row;j++)

  {

  //模糊指数取2

  u[i][j]=pow(u[i][j],2);

  }

  }

  //根据隶属度矩阵计算聚类中心

  p=MatrixMul(u,k,row,data,row,col);

  for(i=0;i《k;i++)

  {

  //计算隶属度矩阵每行之和

  doublesi=0;

  for(j=0;j《row;j++)

  {

  si+=u[i][j];

  }

  for(t=0;t《col;t++)

  {

  center[i][t]=p[i][t]/si; //类中心

  }

  }

  //计算各个聚类中心i分别到所有点j的距离矩阵dis(i,j)

  double*a=new double[col]; //第一个样本点

  double*b=new double[col]; //第二个样本点

  double**dis=newdouble*[k]; //中心与样本之间距离矩阵

  for(i=0;i《k;i++)

  {

  dis[i]=newdouble[row];

  }

  for(i=0;i《k; i++)

  {

  //聚类中心

  for(t=0;t《col; t++)

  {

  a[t]=center[i][t]; //暂存类中心

  }

  //数据样本

  for(j=0;j《row; j++)

  {

  for(t=0;t《col; t++)

  {

  b[t]=data[j][t];//暂存一样本

  }

  doubled=0;

  //中心与样本之间距离的计算

  for(t=0;t《col; t++)

  {

  d+=(a[t]-b[t])*(a[t]-b[t]); //d为一中心与所有样本的距离的平方和

  }

  dis[i][j]=sqrt(d); //距离

  }

  }

  //根据距离矩阵计算隶属度矩阵

  for(i=0;i《k;i++)

  {

  for(j=0;j《row;j++)

  {

  doubletemp=0;

  for(t=0;t《k;t++)

  {

  //dis[i][j]依次除以所在列的各元素,加和;

  //模糊指数为2.0

  temp+=pow(dis[i][j]/dis[t][j],2/(2.0-1));//一个类中心和一个元素的距离平方与

  }

  u[i][j]=1/temp;//所有类与该元素距离平方的和的商

  }

  }

  //计算聚类有效性评价函数

  doublefunc1=0;

  for(i=0;i《k;i++)

  {

  doublefunc2=0;

  for(j=0;j《row;j++)

  {

  func2+=pow(u[i][j],2.0)*pow(dis[i][j],2);

  }

  func1+=func2;

  }

  doubleobj_fcn=1/(1+func1);

  returnobj_fcn;

  //内存释放

  delete[]a;

  delete[]b;

  for(i=0;i《k;i++)

  {

  delete[]dis[i];

  }

  delete[]dis;

  }

  详细过程

  #include “data.h”

  #include “func.h”

  #include “max.h”

  //全局变量定义

  double **Data; //数据矩阵

  double **Center; //聚类中心矩阵

  double **U; //样本隶属度矩阵

  int m; //样本总数

  int n; //样本属性数

  int k; //设定的划分类别数

  int main()

  {

  intLab; //数据文件标号

  intnum; //算法运行次数

  ///////////////////////////////////////////////////////////////

  cout《《“模糊C均值聚类算法:”《《endl;

  cout《《“1-iris.txt; 2-wine.txt; 3-ASD_12_2.txt; 4-ASD_14_2.txt”《《endl;

  cout《《“请选择数据集: Lab=”;

  cin》》Lab;

  cout《《“设定运行次数: mum=”;

  cin》》num;

  //各次运行结束后的目标函数

  double*Index=new double[num];

  //各次运行结束后的聚类正确率

  double*R=new double [num];

  //num次运行的平均目标函数及平均正确率

  doubleM_Index=0;

  doubleM_R=0;

  //FCM聚类算法运行num次,并保存记录与结果

  for(inti=0;i《num;i++)

  {

  intj;

  doubleepsilon=1e-4;

  inte=0;

  intnx=0;

  //记录连续无改进次数

  intE[200]={0};

  if(i》0)

  {

  cout《《endl《《endl;

  cout《《setfill(‘#’)《《setw(10)《《endl;

  }

  cout《《“第”《《i+1《《“次运行记录:”《《endl;

  //读取数据文件

  if(Lab==1)

  {

  m=150;

  n=4;

  k=3;

  Data=DataRead(“dataset\\iris.txt”,m,n);

  }

  elseif(Lab==2)

  {

  m=178;

  n=13;

  k=3;

  Data=DataRead(“dataset\\wine.txt”,m,n);

  }

  elseif(Lab==3)

  {

  m=535;

  n=2;

  k=12;

  Data=DataRead(“dataset\\ASD_12_2.txt”,m,n);

  }

  elseif(Lab==4)

  {

  m=685;

  n=2;

  k=14;

  Data=DataRead(“dataset\\ASD_14_2.txt”,m,n);

  }

  //数据极差标准化处理

  Data=Standardize(Data,m,n);

  //聚类中心及隶属度矩阵,内存分配

  Center=newdouble*[k];

  U=newdouble *[k];

  for(j=0;j《k;j++)

  {

  Center[j]=newdouble[n];

  U[j]=newdouble[m];

  }

  //隶属度矩阵的初始化

  Initialize(U,k, m);

  //对隶属度矩阵进行归一化

  Normalize(U,k,m);

  //历次迭代过程中的目标函数

  doubleObjfcn[100]={0};

  cout《《“第”《《i+1《《“次运行记录:”《《endl;

  cout《《“开始迭代过程!”《《endl;

  cout《《“*******************************”《《endl;

  //输出精度为小数点后5位

  cout.precision(5);

  //固定格式

  cout.setf(ios::fixed);

  //目标函数连续20代无改进,停止该次聚类迭代过程

  while(e《20)

  {

  nx++;

  //聚类迭代过程

  Objfcn[nx]=Update(U,Data,Center,m,n,k);

  //统计目标函数连续无改进次数e

  if(nx》0&& Objfcn[nx]-Objfcn[nx-1]《epsilon )

  {

  e++;

  }

  else

  {

  e=0;

  }

  E[nx]=e;

  }

  //输出结果到文件,保存

  ofstreamoutfile(“运行记录.txt”,ios::app);

  outfile《《“第”《《i+1《《“次运行记录:”《《endl;

  outfile《《“开始迭代过程!”《《endl;

  outfile《《“*******************************”《《endl;

  outfile.precision(5);

  outfile.setf(ios::fixed);

  for(intn1=1;n1《=nx;n1++)

  {

  cout《《“e[”《《setw(2)《《n1《《“]=”《《setw(2)《《E[n1]《《“ Objfcn[”

  《《setw(2)《《n1《《“]=”《《Objfcn[n1]《《“\n”;

  //保存数据文件

  outfile《《“e[”《《setw(2)《《n1《《“]=”《《setw(2)《《E[n1]《《“ Objfcn[”

  《《setw(2)《《n1《《“]=”《《Objfcn[n1]《《“\n”;

  }

  cout《《endl;

  outfile《《endl;

  outfile.close();

  //本次运行的最大目标函数

  Index[i]=Objfcn[nx];

  //保存聚类正确率,输出聚类结果:

  R[i]=Result(Lab,U, k, m, i);

  //内存释放

  for(j=0;j《k;j++)

  {

  delete[]Center[j];

  delete[]U[j];

  }

  delete[]Center;

  delete[]U;

  }

  //////////////////////////统计平均///////////////////////////////////

  doubletemp1=0, temp2=0;

  for(i=0;i《num;i++)

  {

  temp1+=Index[i];

  temp2+=R[i];

  }

  //计算各次结果的统计平均

  M_Index=(double)temp1/num;

  M_R=(double)temp2/num;

  cout《《“//////////////////////////////////////////////////////////////”《《endl;

  cout《《num《《“次运行,平均聚类正确率: ”《《100*M_R《《“%”《《endl;

  //输出精度为小数点后6位

  cout.precision(6);

  //固定格式

  cout.setf(ios::fixed);

  cout《《“平均目标函数:”《《M_Index《《endl;

  //统计结果文件保存

  ofstreamresultfile(“聚类结果.txt”,ios::app);

  resultfile《《“//////////////////////////////////////////////////////////////”《《endl;

  resultfile《《num《《“次运行,平均聚类正确率: ”《《100*M_R《《“%”《《endl;

  //输出精度为小数点后6位

  resultfile.precision(6);

  //固定格式

  resultfile.setf(ios::fixed);

  resultfile《《“平均目标函数:”《《M_Index《《endl;

  return0;

  }

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分