简易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 ...
- elasticsearch的索引操作
1.创建索引(test_index) curl -XPUT "http://192.168.99.1:9200/test_index" 2.创建索引,指定分片和副本的数量 curl ...
- Linux修改bashrc
.bashrc是一个隐藏的文件,要打开并修改该文件需要: (1) 查看:ll -a 找到文件 .bashrc: (2) 打开:vi .bashrc (或者 vim .bashrc) 打开文件: (3) ...
- python的分支结构
python分支结构 if结构 python的 if 选择分支结构的基础语法如下,需要注意的是判断条件后面是半角的分号,它的作用相当于Java中的小括号 if 判断条件 : 代码块 elif 判断条件 ...
- Mysql教程:(二)分组与函数查询group by
分组与函数查询 温馨提示:分组之后查询其他函数结果是不正确的: 分组函数:group by 按班级分组,查询出每班数学最高分:select class,max(maths) from score gr ...
- Java踩坑之List的removeAll方法
最近在公司写东西,发现List的removeAll方法报错 Demo代码如下: List<Long> ids1 = Arrays.asList(1L, 3L, 2L); List<L ...
- Flink 实践教程:入门(6):读取 PG 数据写入 ClickHouse
作者:腾讯云流计算 Oceanus 团队 流计算 Oceanus 简介 流计算 Oceanus 是大数据产品生态体系的实时化分析利器,是基于 Apache Flink 构建的具备一站开发.无缝连接.亚 ...
- Mac下Shell脚本使用学习笔记(一)
参考文献 Shell 教程 MAC常用终端命令行 Mac下Shell脚本使用 1.使用终端创建test.sh: (1)进入指定文件夹路径(命令示例:cd Desktop/面向对象程序设计): (2)创 ...
- [loj2245]魔法森林
枚举携带的"A型守护精灵"数$A_{0}$,那么即只能经过$A_{i}\le A_{0}$的边,并最小化1到$n$路径上最大的$B_{i}$ 将所有边按照$A_{i}$从小到大排序 ...
- [loj2135]幻想乡战略游戏
以1为根建树,令$D_{i}$为$i$子树内所有节点$d_{i}$之和 令$ans_{i}$为节点$i$的答案,令$fa$为$i$的父亲,则$ans_{i}=ans_{fa}+dis(i,fa)(D_ ...