模糊c-means算法的c++实现
首先输入点的个数,维度,分类数目
我的代码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++实现的更多相关文章
- Fuzzy C Means 算法及其 Python 实现——写得很清楚,见原文
Fuzzy C Means 算法及其 Python 实现 转自:http://note4code.com/2015/04/14/fuzzy-c-means-%E7%AE%97%E6%B3%95%E5% ...
- K-means算法
K-means算法很简单,它属于无监督学习算法中的聚类算法中的一种方法吧,利用欧式距离进行聚合啦. 解决的问题如图所示哈:有一堆没有标签的训练样本,并且它们可以潜在地分为K类,我们怎么把它们划分呢? ...
- paper 104: 彩色图像高速模糊的懒惰算法
工程及源代码:快速模糊.rar 图像模糊算法有很多种,我们最常见的就是均值模糊,即取一定半径内的像素值之平均值作为当前点的新的像素值,在一般的工业 ...
- 模糊C均值算法
Fuzzy C-Means读书笔记 一.算法简介 很显然,图中的数据集可分为两个簇.借鉴K-Means算法的思想,利用单个特殊的点(质心)表示一个簇.因此,我们用\(C_1\)和\(C_2\)分别表示 ...
- KNN 与 K - Means 算法比较
KNN K-Means 1.分类算法 聚类算法 2.监督学习 非监督学习 3.数据类型:喂给它的数据集是带label的数据,已经是完全正确的数据 喂给它的数据集是无label的数据,是杂乱无章的,经过 ...
- FCM聚类算法介绍
FCM算法是一种基于划分的聚类算法,它的思想就是使得被划分到同一簇的对象之间相似度最大,而不同簇之间的相似度最小.模糊C均值算法是普通C均值算法的改进,普通C均值算法对于数据的划分是硬性的,而FCM则 ...
- 《Single Image Haze Removal Using Dark Channel Prior》一文中图像去雾算法的原理、实现、效果(速度可实时)
最新的效果见 :http://video.sina.com.cn/v/b/124538950-1254492273.html 可处理视频的示例:视频去雾效果 在图像去雾这个领域,几乎没有人不知道< ...
- FCM算法
FCM算法是一种基于划分的聚类算法,它的思想就是使得被划分到同一簇的对象之间相似度最大,而不同簇之间的相似度最小.模糊C均值算法是普通C均值算法的改进,普通C均值算法对于数据的划分是硬性的,而FCM则 ...
- paper 105: 《Single Image Haze Removal Using Dark Channel Prior》一文中图像去雾算法的原理、实现、效果及其他
在图像去雾这个领域,几乎没有人不知道<Single Image Haze Removal Using Dark Channel Prior>这篇文章,该文是2009年CVPR最佳论文.作者 ...
- Matalab之模糊KMeans实现
这节继续上节的KMeans进行介绍,上节主要是对模糊KMeans方法的原理做了介绍,没有实践印象总是不深刻,前段时间有个师姐让我帮着写了个模糊KMeans的算法,今天就拿她给出的例子来对这个方法做个实 ...
随机推荐
- what the fuck!(二分查找 / 暴力模拟)
what the fuck! Description 现在有一家公司有nnn个员工(nnn为奇数),他们的工资发放是基本工资+提成,现在这家公司计划再招一批人.要写一篇招聘启事,但是对于这个招聘启事中 ...
- NLP(二十八)多标签文本分类
本文将会讲述如何实现多标签文本分类. 什么是多标签分类? 在分类问题中,我们已经接触过二分类和多分类问题了.所谓二(多)分类问题,指的是y值一共有两(多)个类别,每个样本的y值只能属于其中的一 ...
- 写给程序员的机器学习入门 (二) - pytorch 与矩阵计算入门
pytorch 简介 pytorch 是目前世界上最流行的两个机器学习框架的其中之一,与 tensoflow 并峙双雄.它提供了很多方便的功能,例如根据损失自动微分计算应该怎样调整参数,提供了一系列的 ...
- scarpy爬虫框架
目录 架构介绍 安装创建和启动 配置文件目录介绍 爬取数据,并解析 数据持久化 保存到文件 保存到redis 动作链,控制滑动的验证码 架构介绍 Scrapy一个开源和协作的框架,其最初是为了页面抓取 ...
- 【Linux】LAMP环境搭建(简易版)
一. 辅助软件包安装 准备工作:1.Linux系统准备 恢复快照(初始化安装) 设置IP 关闭SELINUX 配置yum源 2.yum -y install gcc gcc-c++ 3.关闭防火墙 4 ...
- SpringMVC(六):分层整合SSM
环境搭建 版本: MySQL 8 SpringMVC+Spring+Mybatis C3P0连接池 数据库建表 CREATE DATABASE `ssmbuild`; `ssmbuild` DROP ...
- ECSHOP数据表结构完整仔细说明教程 (http://www.ecshop119.com/ecshopjc-868.html)
s_account_log //用户账目日志表 字段 类型 Null 默认 注释 log_id mediumint(8) 否 自增ID号 user_id mediumint(8) 否 用户登录 ...
- linux系统管理,查看系统资源
free 查看内存使用情况 -b ===> 以byte为单位 -k ===> 以Kb为单位 -m ===> 以Mb为单位 -g ===> 以Gb为单位 -t ...
- Vue 核心最基本的功能
~~~<html><head> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"& ...
- wireshark没有找到接口
今天安装wireshark,打开发现显示没有找到接口,网上搜索发现出现这种问题的都是win10,但是我的是win7 看了一下win10这种问题的原因是自带的winpcap不支持win10,应到http ...