MPI并行化实现K-means算法,使用zoo数据集


该算法的并行化中使用了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。该步骤要调用两个函数clusterdistance,其中cluster计算每个数据点所属的新的类型,它会调用distance计算数据点到聚类中心点的距离。

5、进程0根据local_cntlocal_cluster_center计算新的聚类中心,新的聚类中心isum(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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值