简易kmeans-c++版本
typedef double dtype;
主要接口:
void Kmeans(const vector<vector<dtype> > &d,int k,string distype,vector<vector<int> > &kset,map<int,int> &category,vector<vector<dtype> > &kcenter)
参数:
vector<vector<dtype> > &d: 数据矩阵mxn
int k:聚类类别数目
string distype:距离类别,"sqeuclidean"表示欧式距离,"cosine"表示余弦距离,"hamming"表示海明距
vector<vector<int> > &kset:初始化K个中心
map<int,int> &category:返回的类别号
vector<vector<dtype> > &kcenter:返回的类别中心
double SSE(const vector<vector<dtype> > &matrix,const vector<vector<dtype> > &kcenter,map<int,int> &category,string distype,map<int,double> &EverySSE)
返回总的误差平方和,map<int,double> &EverySSE返回每个类的误差平方和
#include<iostream>
#include<vector>
#include<map>
#include<algorithm>
#include<cmath>
#include<fstream>
#include<string>
#include<assert.h>
#include<stdlib.h>
#include<time.h>
int const N = 1000;
int const eps = 1e-3;
using namespace std;
typedef double dtype;
typedef vector<int>::size_type vt;
double disfun(const vector<dtype> &a,const vector<dtype> &b,string distype)
{
double dis_sum=0;
if(distype=="sqeuclidean")
{
for(vt i=0;i<a.size();++i)
dis_sum+=pow(a[i]-b[i],2);
}
if(distype=="cosine")
{
double len_a=0,len_b=0,in_product=0;
for(vt i=0;i<a.size();++i)
{
len_a+=pow(a[i],2);
len_b+=pow(b[i],2);
in_product+=a[i]*b[i];
}
dis_sum = 1-in_product*1.0/(sqrt(len_a)*sqrt(len_b));
}
if(distype=="hamming")
{
int count=0;
for(vt i=0;i<a.size();++i)
{
if(a[i]!=b[i])count++;
}
dis_sum = count*1.0/a.size();
}
return dis_sum;
}
vector<int> random_chooseK(const int n,int k)
{
map<int,int> mvis;
vector<int> vec;
int i=0;
cout<<"n:"<<n<<"k:"<<k<<endl;
cout<<"random choose K ok"<<endl;
srand((unsigned)time(NULL));
while(i<k)
{
int tmp=rand()%(n);
if(!mvis.count(tmp)){
mvis[tmp]=1;
vec.push_back(tmp);
i++;
}
}
for(int &i:vec)cout<<i<<"->";
cout<<"random choose K over"<<endl;
return vec;
}
bool nochange(const vector<vector<dtype> > &kcenter,const vector<vector<dtype> > &prekcenter)
{
for(int i=0;i<kcenter.size();++i)
{
string st("sqeuclidean");
if(disfun(kcenter[i],prekcenter[i],st)>eps)return false;
}
return true;
}
vector<dtype> sum_vector(const vector<dtype> &a,const vector<dtype> &b)
{
vector<dtype> avec;
assert(a.size()==b.size());
for(int i=0;i<a.size();++i)
{
avec.push_back(a[i]+b[i]);
}
return avec;
}
void setZero(vector<dtype> &vec)
{
for(int i=0;i<vec.size();++i)
{
vec[i]=0;
}
}
void AlterKcenter(const vector<vector<dtype> > &d,vector<vector<dtype> > &kcenter,const vector<vector<int> > &kset,string distype)
{
for(int i=0;i<kcenter.size();++i)
{
setZero(kcenter[i]);
cout<<i<<":"<<kset[i].size()<<endl;
for(int j=0;j<kset[i].size();++j)
{
kcenter[i] = sum_vector(d[kset[i][j]],kcenter[i]);
}
for(int p=0;p<kcenter[i].size();++p)
{
if(distype=="hamming")
kcenter[i][p]=int(kcenter[i][p]*1.0/kset[i].size()+0.5);
else kcenter[i][p]=kcenter[i][p]*1.0/kset[i].size();
}
}
}
void Kmeans(const vector<vector<dtype> > &d,int k,string distype,vector<vector<int> > &kset,map<int,int> &category,vector<vector<dtype> > &kcenter)
{
vector<int> kgram=random_chooseK(d.size(),k);
vector<vector<dtype> > prekcenter;
//vector<vector<int> > kset;
for(int i=0;i<k;++i){
vector<int> vitmp;
kset.push_back(vitmp);
}
cout<<"kset"<<endl;
for(vt i=0;i<kgram.size();++i)kcenter.push_back(d[kgram[i]]);
cout<<"kset over"<<endl;
bool flag =false;
int count=0;
while(!flag)
{
for(int x=0;x<k;++x)kset[x].clear();
for(int j=0;j<d.size();++j)
{
double min_dis= 1e308;
int index = -1;
for(int m =0;m <k;++m)
{
double dis=disfun(d[j],kcenter[m],distype);
if(dis<min_dis)
{
min_dis=dis;
index = m;
}
}
kset[index].push_back(j);
category[j]=index;
}
prekcenter = kcenter;
count++;
cout<<"alterkcenter begin"<<endl;
AlterKcenter(d,kcenter,kset,distype);
cout<<"alterkcenter finished"<<endl;
flag = nochange(kcenter,prekcenter);
cout<<"µÚ"<<count<<"´Îµü´ú"<<endl;
}
}
void printmatrix(const vector<vector<dtype> > &matrix)
{
for(int i=0;i<matrix.size();++i)
{
for(int j=0;j<matrix[i].size();++j)
cout<<matrix[i][j]<<" ";
cout<<endl;
}
}
double SSE(const vector<vector<dtype> > &matrix,const vector<vector<dtype> > &kcenter,map<int,int> &category,string distype,map<int,double> &EverySSE)
{
double TotalSSE=0;
//map<int,double> EverySSE;
for(int i=0;i<matrix.size();++i)
{
double tmpsse=0;
tmpsse=disfun(matrix[i],kcenter[category[i]],distype);
if(EverySSE.count(category[i]))
EverySSE[category[i]]+=tmpsse;
else EverySSE[category[i]]=tmpsse;
TotalSSE+=tmpsse;
}
return TotalSSE;
}
void saveresult(const vector<vector<dtype> > &matrix,vector<vector<int> > &kset)
{
fstream f("result.txt",ios::out);
map<int,int> category;
cout<<"kset size:"<<kset.size()<<endl;
f<<"total:"<<endl;
for(int i=0;i<kset.size();++i){
f<<"µÚ"<<i<<"Àà:"<<kset[i].size()<<endl;
}
for(int i=0;i<kset.size();++i)
{
cout<<kset[i].size()<<endl;
for(int j=0;j<kset[i].size();++j)
category[kset[i][j]]=i;
}
for(int i=0;i<matrix.size();++i)
{
f<<i<<": "<<category[i]<<endl;
}
for(int i=0;i<matrix.size();++i)
{
f<<"----------------------------------"<<category[i]<<"---------------------------------"<<endl;
for(int j=0;j<matrix[i].size();++j)
f<<matrix[i][j]<<" ";
f<<endl;
}
f.close();
}
int main()
{
vector<vector<dtype> > matrix;
int all=0;
srand((unsigned)time(0));
while(all<600)
{
vector<dtype> row;
for(int n=1;n<=600;++n)
{
int tmp=rand()%(2);
if(rand()/double(RAND_MAX)>0.6)tmp=0;
//cout<<tmp<<endl;
row.push_back(tmp);
}
matrix.push_back(row);
all++;
}
//printmatrix(matrix);
vector<vector<int> > kset;
vector<vector<dtype> > kcenter;
map<int,int> category;
string st("hamming");
Kmeans(matrix,30,st,kset,category,kcenter);
saveresult(matrix,kset);
map<int,double> EverySSE;
cout<<SSE(matrix,kcenter,category,st,EverySSE)<<endl;
map<int,double>:: const_iterator it=EverySSE.begin();
while(it!=EverySSE.end()){
cout<<it->first<<":"<<it->second<<endl;
it++;
}
system("pause");
return 0;
}
简易kmeans-c++版本的更多相关文章
- 简易 (I/O)版本通讯录
#include <stdio.h> #include<assert.h> //#include<malloc.h> #include<string.h> ...
- 简易付XP版本无法获取server.xml配置文件处理方案
博客地址:https://blog.csdn.net/zdw_wym/article/details/40892535 把它添加到C:/WINDOWS/Microsoft.NET/Framework/ ...
- WebSocket实现简易的FTP客户端
WebScoket的简单应用,实现一个简易的FTP,即文件上传下载,可以查看上传人,下载次数,打开多个Web可以多人上传. 说在前面的话 文件传输协议(File Transfer Protocol,F ...
- C#代码
http://www.cnblogs.com/zjfree/category/269738.html 超简易静态Web服务器 C# 生成不重复随机字符串 (1秒内生成1000000个) C# 读写IN ...
- Oracle 数据库 Database Express Edition 11g Release 2 (11.2) 错误解决集锦(安装方面)
前言:第一次接触数据库,想下载个oracle试玩下(虽然听说一般大企业才用),到 官网下载 了个简易版 XE 版本,安装时要注意记住自己输入的数据库密码(口令) 还有安装路径不能含有空格(Do no ...
- 从零开始学C++之STL(七):剩下5种算法代码分析与使用示例(remove 、rotate 、sort、lower_bound、accumulate)
一.移除性算法 (remove) C++ Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 ...
- ES6数组扩展
前面的话 数组是一种基础的JS对象,随着时间推进,JS中的其他部分一直在演进,而直到ES5标准才为数组对象引入一些新方法来简化使用.ES6标准继续改进数组,添加了很多新功能.本文将详细介绍ES6数组扩 ...
- 利用ADO让普通人用excel读取oracle数据库表的通用办法
Ref:http://blog.csdn.net/iamlaosong/article/details/8465177 Excel通过ADO方式连接到Oracle并操作Oracle给那些编程能力不强的 ...
- ES6 数组的扩展
1. Array.from() Array.from()将类数组(array-like)对象与可遍历的对象转化为数组并返回. 下面是一个类数组 let arr = { '0':'a', '1':'b' ...
- 使用git进行版本控制
一.git基本介绍 Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目.Git是目前世界上最先进的分布式版本控制系统. 与常用的版本控制工具 CVS, Subversion 等 ...
随机推荐
- spring social理解
现在互联网飞速发展,人们每天在互联网上冲浪,获取各种信息.各大网站为了方便用户的登录,提供了各式各样的社交登录,比如:QQ.微信和微博登录等.这些主流的社交登录大多是基于oauth协议进行实现,spr ...
- Noip模拟15 2021.7.14
T1 夜莺与玫瑰 题目越发的变态起来... 这题刚开始看超级像仪仗队,好不容易码完欧拉函数后尝试×2后输出但不对!! 于是选择了跳过.... 正解居然是莫比乌斯函数....我也是醉了 预处理完就剩下$ ...
- WPF PropertyChanged实现子属性通知
今天用WPF的View绑定了ViewModel的一个属性类,结果在属性类的子属性修改时,没有通知到UI. 如有要显示一个学生信息,采用WPF MVVM的模式,则前端代码 <StackPanel& ...
- 洛谷 P3147 [USACO16OPEN]262144 P
链接: P3147 P3146双倍经验 前言: 今天发现的一道很有意思的DP题 分析: 第一眼以为是区间DP,于是设f[i][j]为从第i个数到第j个数可以合出的最大值,但思考后发现并不能简单合并,并 ...
- fd定时器--timerfd学习
定时器 可以用系统定时器信号SIGALARM 最近工作需要于是又发现了一个新玩意timerfd配合epoll使用. man 手册看一下 TIMERFD_CREATE(2) Linux Programm ...
- Luogu P2024 [NOI2001]食物链 | 并查集
题目链接 思路:并查集,因为一开始我们并不知道每一只动物是哪一个种类的,所以我们干脆建立三倍于n的空间,1~n这三分之一用来存第i只动物是A的情况,n+1~2n这三分之一用来存第(i-n)只动物是B的 ...
- Nginx多种安装方式
不指定参数配置的Nginx编译安装 ./configuremake make install wget下载或浏览器下载上传.解压进入目录[root@mcw1 nginx-1.10.2]# ls #查看 ...
- 如何系统学习C 语言(中)之 指针篇
谈到指针,我们可能会想到钟表上的指针,但这里的指针不是现实生活中看得见摸得着的钟表上的指针,c 语言中的指针只存在于逻辑思维中,物理上并不存在. 同时,指针也是C 语言中最精华的部分,通过灵活地运用指 ...
- no space left on device 磁盘空间不足
新挂载的目录,创建文件提示:no space left on device 1.执行命令:df -h ,查看盘是否挂载成功 2.用history命令查看历史命令,尴尬的发现挂载前忘记格式化了 3.取消 ...
- 【java+selenium3】Actions模拟鼠标 (十一)
一.鼠标操作 WebElement的click()方法可实现元素的点击操作,但是没有提供鼠标的右击/双击/悬停/鼠标拖动等操作.这些操作需要通过Action类提供的方法来实现! Action常用的ap ...