该算法的并行化中使用了zoo数据集,数据集地址:(http://archive.ics.uci.edu/ml/datasets/Zoo)
详细算法设计
采用主从方式,由一个进程充当主节点负责数据的划分与分发,其他进程完成本地数据的计算,并将结果返回给主节点做聚合。
1、选定进程0为主节点,首先调用loadDate函数从数据集文件zoo.data中读取数据集,每次读取一行数据,并把数据按animal结构体指定的结构保存到内存中,结构体如下所示:
struct animal{
int name;
int type;
int characters[D];
};
zoo.data每一行是个18维的数据。其中第一维表示动物的名字,是个字符串,为了方便MPI中数据的传递,将动物名映射成一个int型索引保存到属性name中,而索引到字符串名称的映射通过另一个变量idx2name,它是一个哈希表。中间的16维代表了该动物的特征,全为整数,因此保存到一个长度维D=16的数组characters中。最后一维代表了该动物所属的类型,也为整数,保存到属性type中。
2、完成了数据的读取后,主节点0向其他从节点分发数据,首先告知各个节点需要处理的数据量,假设进程数为size,数据总量为N,那么除主节点不处理数据外,其他从节点处理的数据量为dataNum = N/(size-1),节点i处理数据的范围为(i-1)*dataNum~i*dataNum。确定好每个从节点处理的数据量和数据范围后,进程0将对应的数据分发给这个节点。
3、进程0随机选择每个聚类的中心点,并发送给其他进程。
4、其他从节点进程根据自己分配得到的数据,计算数据块中每个点到各个聚类中心点的距离,取距离最小的那个类为该点所属的聚类,并计算每个聚类包含的数据量local_cnt,同时将每个数据的属性值叠加到对应聚类i的属性和local_cluster_center[i]上,最后将这些结果返回给进程0方便计算新的聚类中心。这些结果的传递采用MPI_Reduce函数进行规约,规约操作op为求和MPI_SUM。该步骤要调用两个函数cluster和distance,其中cluster计算每个数据点所属的新的类型,它会调用distance计算数据点到聚类中心点的距离。
5、进程0根据local_cnt和local_cluster_center计算新的聚类中心,新的聚类中心i为sum(local_cluster_center[i])/sum(local_cnt[i]),然后发送给其他进程。
6、返回步骤进行新的一轮迭代,直到达到指定的迭代轮数epoch。
7、将聚类结果保存到文件中,将属于同一类的动物保存在一个cluster中。
算法流程

主要函数及其功能说明
1、int loadData(string filename,animal* &data):从文件filename中读取数据保存到data中
2、double distance(int charc[],double center_charc[]):求数据点charc和聚类中心center_charc之间的欧式距离 d i s = ∑ i = 1 D ( c h a r c [ i ] − c e n t e r _ c h a r c [ i ] ) 2 dis=\sqrt{\sum_{i=1}^{D}(charc[i]-center\_charc[i])^2} dis=∑i=1D(charc[i]−center_charc[i])2
double distance(int charc[],double center_charc[]){
double dis=0.0;
for(int i=0;i<D;i++){
dis+=(charc[i]*1.0-center_charc[i])*(charc[i]*1.0-center_charc[i]);
}
return sqrt(dis);
}
3、void cluster(animal* &data,int dataSize,double data_center[][D],double new_data_center[][D],int cnt[]):判断data中每个数据点所属的类型,data_center为当前的聚类中心,new_data_center为每个聚类包含的所有数据点的属性之和,cnt每个聚类包含的数据个数
void cluster(animal* &data,int dataSize,double data_center[][D],double new_data_center[][D],int cnt[]){
for(int i=0;i<dataSize;i++){
double min_dis=10000.0;
int clusterId=-1;
for(int j=0;j<K;j++){
double cur_dis=distance(data[i].characters,data_center[j]);
if(cur_dis<min_dis){
min_dis=cur_dis;
clusterId=j;
}
}
//便于后续计算新的聚类中心
for(int j=0;j<D;j++){
new_data_center[clusterId][j]+=data[i].characters[j];
}
cn

最低0.47元/天 解锁文章
1050

被折叠的 条评论
为什么被折叠?



