简易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 等 ...
随机推荐
- 使用logstash的input file filter收集日志文件
使用logstash的input file filter收集日志文件 一.需求 二.实现步骤 1.前置知识 2.编写pipeline文件 3.Input 中 file 插件的部分参数解释: 4.启动l ...
- 将manjaro作为主力开发系统,我遇到了哪些坑。
首先遇到的问题就是企业微信. 最开始几天,我直接去安装企业微信和微信,安装全都报错了. 无奈之下,只好安装了virtual box,装了一个win7,可以正常使用微信,企业微信,最开始蛋疼的地方是,企 ...
- CSS学习(二)选择符
元素选择符:以元素名作为选择符(span{ color: red; }) 群组选择符:将两个选择符用逗号隔开构成群组(span, div{ color: red; }) 通用选择符:通用选择符(*)将 ...
- Mac sourceTree每次都输入密码
打开终端 依次输入以下三条命令 curl http://github-media-downloads.s3.amazonaws.com/osx/git-credential-osxkeychain - ...
- kubernetes创建用户
创建k8s User Account 使用openssl方法创建普通用户 准备工作 1 2 3 4 mkdir /root/pki/ 将k8s ca.pem ca-key.pem 证书拷贝到此目录 ...
- 《手把手教你》系列技巧篇(三十九)-java+ selenium自动化测试-JavaScript的调用执行-上篇(详解教程)
1.简介 在做web自动化时,有些情况selenium的api无法完成,需要通过第三方手段比如js来完成实现,比如去改变某些元素对象的属性或者进行一些特殊的操作,本文将来讲解怎样来调用JavaScri ...
- 第二课 Dubbo设计的架构设计
总体架构 Dubbo的总体架构,如图所示: Dubbo框架设计一共划分了10个层,而最上面的Service层是留给实际想要使用Dubbo开发分布式服务的开发者实现业务逻辑的接口层.图中左边淡蓝背景的为 ...
- Spring Boot程序中@JsonIgnoreProperties与@JsonIgnore基本使用
问题由来: springboot项目中定义了很多类,我们在rest返回中直接返回或者在返回对象中使用这些类,spring已经使用jackson自动帮我们完成这些的to json.但是有时候自动转的js ...
- 旧电脑做服务器--第一篇 sql server 服务器搭建
背景:旧电脑为2015年的老电脑,联系G50系列,目前键盘鼠标操作都有问题,键盘按键和鼠标左键莫名奇妙变成右击,屏幕显示也是大颗粒.但是配置还可以,16GB内存+256GB三星固态硬盘.所以想搭建作为 ...
- 详解电子表格中的json数据:序列化与反序列化
从XML到JSON 当下应用开发常见的B/S架构之下,我们会遇到很多需要进行前后端数据传输的场景.而在这个传输的过程中,数据通过何种格式传输.方式是否迅速便捷.书写方式是否简单易学,都成为了程序员在开 ...