您的位置:首页 > 其它

该来的还是要来,数据挖掘

2015-05-24 03:27 169 查看
k-means算法

n个对象聚簇成k个集合,选出k个质心

什么欧几里得距离,和余弦弧度相似度

大概先从n个中随机选k个作为质心,其实有点策略选会好点

然后求最近距离弄出k个集合,然后求方差,然后迭代到收敛

期间要不停换k个质心,通过求出的集合的均值作为新的质心,质心不一定要是原对象,坐标什么的可以随便取的

最后得到的k个集合和质心为所求,方差和均值和欧几里得距离这里只是一种方法,别的地方不一定是这些

但是最后要能收敛或在一定次数后终止循环迭代,另外注意空簇可能的bug

#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
const int k=3;
typedef vector<double> Tuple;
int dataNum;
int dimNum;
double getDistXY(const Tuple &t1,const Tupble &t2){
double sum=0;
for(int i=1;i<=dimNum;i++)
sum+=(t1[i]-t2[i])*(t1[i]-t2[i]);
return sqrt(sum);
}

int clusterOfTuple(Tuple means[],const Tuple &tuple){
double dist=getDistXY(means[0],tuple);
double tmp;
int lable=0;
for(int i=1;i<k;i++){
tmp=getDistXY(means[i],tuple);
if(tmp<dist){
dist=tmp;
label=i;
}
}
return label;
}
Tuple getMeans(const vector<Tuple> &cluster){
int num=cluster.size();
Tuple t(dimNu+1,0);
for(int i=0;i<num;i++){
for(int j=1;j<=dimNum;j++)
t[j]+=cluster[i][j];
}
for(int j=1;j<=dimNum;j++)
t[j]/=num;
return t;
}
double getVar(vector<Tuple> clusters[],Tuple means[]){
double var=0;
for(int i=0;i<k;i++){
vector<Tuple> t=clusters[i];
for(int j=0;j<t.size();j++)
var+=getDistXY(t[j],means[i]);
}
return var;
}
void KMeans(vector<Tuple> &tuples){
vector<Tuple> clusters[k];
Tuple means[k];
int i=0;
srand(time(nullptr));
for(i=0;i<k;i++){
int iToSelect=rand()%tuples.size();
if(means[i].size()==0){
for(int j=0;j<=dimNum;j++)
means[i].push_back(tuples[iToSelect][j]);
i++;
}
}
int label=0;
for(i=0;i!=tuples.size();i++){
label=clusterOfTuple(means,tuples[i]);
clusters[label].push_back(tuples[i]);
}
double oldVar=-1;
double newVar=getVar(clusters,means);
int t=0;
oldVar=newVar;
while(abs(newVar-oldVar)>=1){
for(int i=0;i<k;i++){
means[i]=getMeans(clusters[i]);
}
newVar=getVar(clusters,means);
for(int i=0;i<k;i++)
clusters[i].clear();
for(int i=0;i!=tuples.size();i++){
label=clusterOfTuple(means,tuples[i]);
clusters[label].push_back(tuples[i]);
}
oldVar=newVar;
}
}
int main() {
char fname[256];
cout<<"Please datafiles: ";
cin>>fname;
cout<<endl<<"Please input dim and number"<<endl;
cin>>dimNum>>dataNum;
ifstream infile(fname);
if(!infile){
cout<<"can't open input file!"<<endl;
return 0;
}
vector<Tuple>tuples;
for(int i=0;i<dataNum&&!infile.eof();++i){
string str;
getline(infile,str);
istringstream istr(str);
Tuple tuple(dimNum+1,0);
tuple[0]=i+1;
for(int j=1;j<=dimNum;j++){
istr>>tuple[j];
}
tuples.push_back(tuple);
}
cout<<endl<<"start k-means clustor"<<endl;
KMeans(tuples);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: