简易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 等 ...
随机推荐
- elasticsearch使用ik中文分词器
elasticsearch使用ik中文分词器 一.背景 二.安装 ik 分词器 1.从 github 上找到和本次 es 版本匹配上的 分词器 2.使用 es 自带的插件管理 elasticsearc ...
- 零基础玩转C语言单链表
下图为最一简单链表的示意图: 第 0 个结点称为头结点,它存放有第一个结点的首地址,它没有数据,只是一个指针变量.以下的每个结点都分为两个域,一个是数据域,存放各种实际的数据,如学号 num,姓名 n ...
- SQLServer聚集索引导致的插入性能低
1,新表默认会在主键上建立聚集索引.对于非专业DBA, 默认配置在大多数情况下够用. 2,当初为了优化查询速度. 把聚集索引建立在非自增主键的唯一索引列. 数据量上千万后,插入性能开始显现不足. 随着 ...
- .NET 生态系统的蜕变之 .NET 6
.NET 6 是自.NET 4 框架以来生态系统看到的最大版本更新,虽然.NET Core 是2014年开始非常大的一项重大战略举措,但是.NET 6是真正的具有强大动力的非常重要的版本. 2021年 ...
- vcs(UST)Undefined System Task Call
转载:VCS求助啊 - 微波EDA网 (mweda.com) Error-[UST] Undefined System Task Call../../path/bench/path.v, 51Unde ...
- wpa_supplicant启动出错rfkill: Cannot open RFKILL control device
在板子是调试网络,千辛万苦把wpa_supplicant及其依赖都移植编译进来了,在板子上调试启动的时候启动报错了 D/wpa_supplicant( 1152): wpa_supplicant v2 ...
- linux下创建文件的文件权限问题
今天发现创建文件的权限和自己规定的权限不一致,了解到了权限掩码的问题,这里总结一下. 首先权限掩码umask是chmod配套的,总共为4位(gid/uid,属主,组权,其它用户的权限),不过通常我们都 ...
- Luogu P2149 [SDOI2009]Elaxia的路线 | 图论
题目链接 题解: 题面中给了最简洁清晰的题目描述:"求无向图中,两对点间最短路的最长公共路径". 对于这个问题我们可以先考虑图中的哪些边对这两对点的最短路产生了贡献. 比如说下面这 ...
- Python 模块 itertools
python 2.6 引入了itertools模块,使得排列组合的实现非常简单: import itertools 有序排列:e.g., 4个数内选2个排列: >>> print l ...
- 【java+selenium3】模态框处理(五)
一.模态框的定义: 模态对话框(Modal Dialogue Box , 又叫做模式对话框),是指在用户想要对话框以外的应用程序进行操作时候,必须先对该对话框进行响应.如单击[确定]或者[返回]按钮等 ...