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

描述

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

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

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

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

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

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

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

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

硬C划分和模糊C 划分

fde71c675a2fbdf7a201f210bbcaa34a.png

FCM算法原理

c0d85cf86907fc93600cbafac52ce621.png

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阅读更多精彩内容

点击阅读全文

你可能感兴趣的:(模糊聚类划分matlab代码)