基于MapReduce实现的Kmeans算法(非调库)

本文详细介绍了如何使用Hadoop MapReduce实现KMeans聚类算法。通过随机初始化中心点,Mapper计算数据点与中心点的距离并分配簇,Reducer计算新中心点。在每次迭代中,检查中心点的变化以决定是否停止。最终输出聚类结果。项目源代码已上传至GitHub。
摘要由CSDN通过智能技术生成

简单基于MapReduce实现了下KMeans。

算法思路

KMeans算法作为一种划分式的聚类算法,利用MapReduce进行实现的主要难点在于满足KMeans每次迭代划分过程的中间结果保存。
因此利用HDFS进行中心点的存储,以实现各节点间的数据共享。
基于MapReduce的KMeans算法流程如下:

  1. 随机分配簇,初始化中心点,存入HDFS。
  2. Mapper中读取数据文件中的每条数据并与中心点进行距离计算,输出key为最近的中心点序号。
  3. Reducer中进行归并,计算新的中心点,存入新的中心文件。
  4. 判断停机条件,不满足则复制新的中心文件到原中心文件,重复2,3步骤。
  5. 输出聚类结果,包括数据点信息与对应簇序号。

初始化中心点

利用Mapper读取每一个元素的向量信息,随机赋值,在Reducer中计算中心点信息。由于中心点的计算与迭代时的计算相同,与迭代计算共用一个reducer类。

CenterRandomMapper

随机赋值的mapper类。

    protected void setup(Context context) throws IOException, InterruptedException {
   
        // 读取k值
        Configuration configuration = context.getConfiguration();;
        k = configuration.getInt("cluster.k", 3);
    }

setup中读取配置的聚类簇数量。

	protected void map(Object key, Text value, Context context) throws IOException, InterruptedException {
   
        // 随机分配簇
        int index = (int) (Math.random() * k);
        System.out.println(index);
        context.write(new Text(Integer.toString(index)), value);
    }

map方法中,根据聚类簇数量,对每个元素赋予随机的类簇序号,作为输出的key。value为元素向量,保持不变。

CenterRandomAdapter

初始化中心点的任务配置类,实现一个static方法。

	public static void createRandomCenter(String dataPath, String centerPath, int k){
   
        Configuration hadoopConfig = new Configuration();
        hadoopConfig.setInt("cluster.k", k);
        try {
   
            Job job = Job.getInstance(hadoopConfig, "random center task");

            job.setJarByClass(KmeansRun.class);
            job.setMapperClass(CenterRandomMapper.class);
            job.setReducerClass(KmeansReducer.class);

            job.setOutputKeyClass(Text.class);
            job.setOutputValueClass(Text.class);

            job.setMapOutputKeyClass(Text.class);
            job.setMapOutputValueClass(Text.class);

            // 输出为新计算得到的center,已存在则删除
            Path outPath = new Path(centerPath);
            outPath.getFileSystem(hadoopConfig).delete(outPath, true);

            //job执行作业时输入和输出文件的路径
            FileInputFormat.addInputPath(job, new Path(dataPath));
            FileOutputFormat.setOutputPath(job, new Path(centerPath));

            //执行job,直到完成
            job.waitForCompletion(true);
            System.out.println("random center task");
        }
}

该方法包含三个参数,分别为数据文件地址,中心点文件地址以及聚类数。首先在配置中设置聚类数,方便mapper中进行读取。
设置对应的mapper和reducer类以及输入输出格式,需要注意的是reducer使用了KmeansReducer类,即正式迭代时计算中心点的reducer。由于HDFS不能直接进行同名文件的覆盖,所以在每次生成新的中心点文件时,需要判断是否已经存在同名文件,存在则删除。

分配元素对应簇,计算中心点

利用Mapper将所有元素与中心点进行对比,分配到最近的簇中。利用Reducer进行求和并计算新的中心点信息。

KmeansMapper
    private ArrayList<ArrayList<Double>> centers = null;
    @Override
    protected void setup(Context context) throws IOExceptio
  • 9
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值