首先输入点的个数,维度,分类数目

我的代码FCM中主要过程如下:

1:(init_c函数)随机初始化聚类中心

2:(comp_dis函数)计算每个点到每个聚类距离 dis[i][j] 表示i点到j聚类中心的距离

3:(while(1))进入循环

4:(comp_u函数)计算隶属度矩阵u[i][j]表示i点对应j聚类中心的隶属度

5:(update_c函数)根据隶属度和每个点的位置更新聚类中心

6:(compdis函数)因为聚类中心更新了嘛,再重新计算下每个点到每个聚类中心的距离

7:(comp_obj_func函数)计算函数值差值如果小于设定值eps则进行第8步,否则进行第9步

8:(break)退出循环

9:根据每个点的隶属度情况,给每个点分类(距离哪个聚类中心近,就给谁)

注意事项:

1.如果点很少的话,可能在我的初始化聚类中心函数中会有相同的点,造成分类错误,但实际应用中,点数足够多的情况则这个概率可以忽略

2.在计算隶属度的函数中,如果一个点距离一个聚类中心足够的近,那么直接将它的隶属度设置成1,其他的为0

其他:

如果有错误和疑问欢迎探讨,望多多指教!

代码:

 #include<iostream>
#include<cstdio>
#include<vector>
#include<fstream>
#include<cmath>
#include<ctime>
#include<cstdlib>
using namespace std;
struct Mode
{
int x,y;
int di;
vector<double> datas;
};
typedef vector<vector<Mode> > ModeVec;
const int N=;
const double eps=1e-;
const double eps_dis=1e-; double getDistance(Mode &m1,Mode &m2);
void FCM(Mode *p,int n,int di,int clusternum,vector<vector<Mode> > &ans);
void init_c(Mode *p,int n,int clusternum,Mode *c);
void comp_dis(Mode *p,Mode *c,int n,int clusternum,double dis[][]);
void comp_u(double dis[][],int n,int clusternum,double u[][]);
void update_c(Mode *p,double u[][],int n,int clusternum,Mode *c);
double comp_obj_func(double u[][],double dis[][],int n,int clusternum,int di);
int main()
{
int n,dimension,clusternum;
Mode p[N];
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
ifstream fin("in.txt");
ofstream fout("out.txt");
fin>>n>>dimension>>clusternum; //输入点的个数,维度,聚类数目
for(int i=; i<n; i++)
{
p[i].di=dimension;
for(int j=; j<dimension; j++)
{
double temp;
fin>>temp;
p[i].datas.push_back(temp);
}
}
vector<vector<Mode> > ans;
FCM(p,n,dimension,clusternum,ans); //传入数组p,有n个点,维度为dimension,结果保存在ans
for(int i=;i<clusternum;i++)
{
printf("第%d类:\n",i+);
for(int j=;j<ans[i].size();j++)
{
printf("(");
for(int k=;k<dimension;k++)
{
if(k==) printf("%f",ans[i][j].datas[k]);
else printf(",%f",ans[i][j].datas[k]);
}
printf(") ");
}
printf("\n");
}
return ;
}
double getDistance(Mode &m1,Mode &m2)
{
int di=m1.di;
double ans=;
for(int i=; i<di; i++)
ans+=(m1.datas[i]-m2.datas[i])*(m1.datas[i]-m2.datas[i]);
return ans;
}
void init_c(Mode *p,int n,int clusternum,Mode *c) //初始化聚类中心
{
int di=p[].di;
srand(time(NULL));
for(int i=;i<clusternum;i++)
{
c[i].di=di;
c[i].datas.clear();
for(int j=;j<di;j++)
c[i].datas.push_back();
}
for(int i=;i<n;i++)
for(int j=;j<di;j++)
for(int k=;k<clusternum;k++)
c[k].datas[j]+=p[i].datas[j];
for(int i=;i<clusternum;i++)
{
for(int j=;j<di;j++)
{
int tp=rand()%n+;
c[i].datas[j]/=tp;
}
}
}
void comp_dis(Mode *p,Mode *c,int n,int clusternum,double dis[][]) //初始化每个点和每个簇的距离
{
for(int i=; i<n; i++)
for(int j=; j<clusternum; j++)
dis[i][j]=getDistance(p[i],c[j]);
}
void comp_u(double dis[][],int n,int clusternum,double u[][]) //计算隶属度矩阵
{
for(int i=; i<n; i++)
{
double tp=;
for(int j=;j<clusternum;j++)
{
if(dis[i][j]<eps_dis) //如果这个点很接近一个簇类中心,那么这个隶属度设为1,其他为0
{
for(int k=;k<clusternum;k++)
u[i][k]=;
u[i][j]=;
return;
}
tp+=/dis[i][j];
}
tp=/tp;
for(int j=; j<clusternum; j++)
u[i][j]=tp*(/dis[i][j]);
}
}
void update_c(Mode *p,double u[][],int n,int clusternum,Mode *c)
{
int di=p[].di;
for(int j=;j<clusternum;j++)
{
c[j].di=di;
c[j].datas.clear();
for(int i=;i<di;i++)
c[j].datas.push_back();
double tp=;
for(int i=;i<n;i++)
{
for(int k=;k<di;k++)
c[j].datas[k]+=u[i][j]*u[i][j]*p[i].datas[k];
tp+=u[i][j]*u[i][j];
}
for(int k=;k<di;k++)
c[j].datas[k]/=tp;
}
}
double comp_obj_func(double u[][],double dis[][],int n,int clusternum,int di)
{
double sum=;
for(int i=;i<n;i++)
for(int j=;j<clusternum;j++)
sum+=u[i][j]*u[i][j]*dis[i][j];
return sum;
}
void FCM(Mode *p,int n,int di,int clusternum,vector<vector<Mode> > &ans) //in: n,d,c time:O(c*n*d) 时间复杂度=聚类数*点数*维数
{
int index=;
double sum=,psum;
Mode c[]; //聚类中心
double dis[N][]; //距离
double u[N][]; //隶属度矩阵
init_c(p,n,clusternum,c); // 初始化聚类中心 time: O(c)
comp_dis(p,c,n,clusternum,dis); //更新距离矩阵dis
while()
{
index++;
printf("第%d次循环----------------------------------------\n",index);
comp_u(dis,n,clusternum,u); //计算隶属度矩阵u time:O(n*c);
for(int i=;i<n;i++)
{
printf("第%d个点的隶属值\n",i+);
for(int j=;j<clusternum;j++)
{
printf("%f ",u[i][j]);
}
printf("\n");
}
update_c(p,u,n,clusternum,c); //更新聚类中心 time:O(c*(2*d+(n*d))) = O(c*n*d)
comp_dis(p,c,n,clusternum,dis); //重新计算距离矩阵
psum=sum;
sum=comp_obj_func(u,dis,n,clusternum,di);
printf("函数值=%f\n",sum);
if(fabs(psum-sum)<eps)
break;
}
for(int i=;i<clusternum;i++)
{
vector<Mode> m;
ans.push_back(m);
}
for(int i=;i<n;i++)
{
double tp=-;
int index=;
for(int j=;j<clusternum;j++)
{
if(u[i][j]>tp)
{
tp=u[i][j];
index=j;
}
}
ans[index].push_back(p[i]);
}
}

模糊c-means算法的c++实现的更多相关文章

  1. Fuzzy C Means 算法及其 Python 实现——写得很清楚,见原文

    Fuzzy C Means 算法及其 Python 实现 转自:http://note4code.com/2015/04/14/fuzzy-c-means-%E7%AE%97%E6%B3%95%E5% ...

  2. K-means算法

    K-means算法很简单,它属于无监督学习算法中的聚类算法中的一种方法吧,利用欧式距离进行聚合啦. 解决的问题如图所示哈:有一堆没有标签的训练样本,并且它们可以潜在地分为K类,我们怎么把它们划分呢?  ...

  3. paper 104: 彩色图像高速模糊的懒惰算法

    工程及源代码:快速模糊.rar                            图像模糊算法有很多种,我们最常见的就是均值模糊,即取一定半径内的像素值之平均值作为当前点的新的像素值,在一般的工业 ...

  4. 模糊C均值算法

    Fuzzy C-Means读书笔记 一.算法简介 很显然,图中的数据集可分为两个簇.借鉴K-Means算法的思想,利用单个特殊的点(质心)表示一个簇.因此,我们用\(C_1\)和\(C_2\)分别表示 ...

  5. KNN 与 K - Means 算法比较

    KNN K-Means 1.分类算法 聚类算法 2.监督学习 非监督学习 3.数据类型:喂给它的数据集是带label的数据,已经是完全正确的数据 喂给它的数据集是无label的数据,是杂乱无章的,经过 ...

  6. FCM聚类算法介绍

    FCM算法是一种基于划分的聚类算法,它的思想就是使得被划分到同一簇的对象之间相似度最大,而不同簇之间的相似度最小.模糊C均值算法是普通C均值算法的改进,普通C均值算法对于数据的划分是硬性的,而FCM则 ...

  7. 《Single Image Haze Removal Using Dark Channel Prior》一文中图像去雾算法的原理、实现、效果(速度可实时)

    最新的效果见 :http://video.sina.com.cn/v/b/124538950-1254492273.html 可处理视频的示例:视频去雾效果 在图像去雾这个领域,几乎没有人不知道< ...

  8. FCM算法

    FCM算法是一种基于划分的聚类算法,它的思想就是使得被划分到同一簇的对象之间相似度最大,而不同簇之间的相似度最小.模糊C均值算法是普通C均值算法的改进,普通C均值算法对于数据的划分是硬性的,而FCM则 ...

  9. paper 105: 《Single Image Haze Removal Using Dark Channel Prior》一文中图像去雾算法的原理、实现、效果及其他

    在图像去雾这个领域,几乎没有人不知道<Single Image Haze Removal Using Dark Channel Prior>这篇文章,该文是2009年CVPR最佳论文.作者 ...

  10. Matalab之模糊KMeans实现

    这节继续上节的KMeans进行介绍,上节主要是对模糊KMeans方法的原理做了介绍,没有实践印象总是不深刻,前段时间有个师姐让我帮着写了个模糊KMeans的算法,今天就拿她给出的例子来对这个方法做个实 ...

随机推荐

  1. MiniUi遇到的一个Bug或者说坑,以div里面的内容自适应高度

    页面源码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <tit ...

  2. 在ES5实现ES6中的Object.is方法

    ES6中对象的扩展里面添加了一个Object.is方法,用于比较两个值是否严格相等.内部计算与 === 行为基本一致.那么我们怎么在不支持这个方法的ES5中实现呢? 首先我们需要搞清楚两点,1:Obj ...

  3. C++11中的四种类型转换

    static_cast 基础数据类型转换(基本类型) 同一继承体系中类型的转换(父子类型) 任意类型与空指针(void *)之间的转换(指针类型) dynamic_cast 执行派生类指针或引用与基类 ...

  4. 【python实现卷积神经网络】激活函数的实现(sigmoid、softmax、tanh、relu、leakyrelu、elu、selu、softplus)

    代码来源:https://github.com/eriklindernoren/ML-From-Scratch 卷积神经网络中卷积层Conv2D(带stride.padding)的具体实现:https ...

  5. pgsql中的事务隔离

    pgsql中的事务隔离级别 前言 事物隔离级别 在各个级别上被禁止出现的现象是 脏读 不可重复读 幻读 序列化异常 读已提交隔离级别 可重复读隔离级别 可序列化隔离级别 摘录 pgsql中的事务隔离级 ...

  6. win10+ubuntu双系统修复ubuntu启动引导

    因为windows是不能引导linux的,而每次win10升级或恢复都会将linux的启动引导覆盖掉,导致无法进入linux, 所以一直就禁止了win10更新.这几天win10出了点小毛病,所以就狠下 ...

  7. Redis分布式锁的实现以及工具类

    一.应用场景: 本文应用的场景为在查询数据时,发现数据不存在此时就需要去查询数据库并且更新缓存,此时可能存在高并发的请求同时打在数据库上,而针对这种情况必须要给这些请求加锁,故而采用了分布式锁的方式. ...

  8. Docker-Bridge Network 02 容器与外部通信

    本小节介绍bridge network模式下,容器与外部的通信. 1.前言2.容器访问外部2.1 访问外网2.2 原理2.3 一张图总结2.4 抓包3.外部访问容器3.1 创建nginx容器并从外部访 ...

  9. pickle\json,configparser,hashlib模块

    python常用模块 目录 python常用模块 json模块\pickle模块 configparser模块 hashlib模块 subprocess模块 json模块\pickle模块 首先说一下 ...

  10. Windows DC域控由server08r2升级至server2016测试

    测试环境 原DC: csctest.com CSCDC01 192.168.100.1 server08r2 CSCDC02 192.168.100.2 server08r2 要求: 原两台旧主机均更 ...