zoukankan      html  css  js  c++  java
  • 该来的还是要来,数据挖掘

    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;
    }
    
  • 相关阅读:
    thinkphp 3.2 服务器 session 设置时间周期失效问题 服务器是linux windows 上暂时没有发现此类问题
    php 不常见的开发模式
    js 里面的 call 方法 和 apply 方法
    PHP读取文件目录, 并显示需要的目录
    PHP 时间格式
    Python之旅.第三章.函数
    Python之旅.第三章.函数
    Python之旅.第三章.函数
    Python之旅.第三章.函数
    Python之旅.第三章.函数
  • 原文地址:https://www.cnblogs.com/HaibaraAi/p/4525315.html
Copyright © 2011-2022 走看看