MapReduce框架实现的kmeans算法

      MapReduce是Hadoop处理平台的核心部分,实现了海量数据的并行处理。本文主要介绍基于MapReduce框架实现的kmeans(参考http://blog.csdn.net/qll125596718/article/details/8243404)算法。

      下面是代码的实现:sample.java

      

package kmeans;
 
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.io.Writable;
 
public class Sample implements Writable{
    private static final Log log=LogFactory.getLog(Sample.class);
    public static final int DIMENTION=60;
    public double arr[];
     
    public Sample(){
        arr=new double[DIMENTION];
    }
     
    public static double getEulerDist(Sample vec1,Sample vec2){
        if(!(vec1.arr.length==DIMENTION && vec2.arr.length==DIMENTION)){
            log.error("vector's dimention is not "+DIMENTION);
            System.exit(1);
        }
        double dist=0.0;
        for(int i=0;i
   
   


kmeans的代码:
package kmeans;
 
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Vector;
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.filecache.DistributedCache;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
 
public class KMeans extends Configured implements Tool{
    private static final Log log = LogFactory.getLog(KMeans.class);
 
    private static final int K = 2;
    private static final int MAXITERATIONS = 300;
    private static final double THRESHOLD = 0.01;
     
    public static boolean stopIteration(Configuration conf) throws IOException{
        FileSystem fs=FileSystem.get(conf);
        Path pervCenterFile=new Path("hdfs://192.168.7.119:9010/user/sn/Input/centers");
        Path currentCenterFile=new Path("hdfs://192.168.7.119:9010/user/sn/Output/part-r-00000");
        if(!(fs.exists(pervCenterFile) && fs.exists(currentCenterFile))){
            log.info("两个质心文件需要同时存在");
            System.exit(1);
        }
        //比较前后两次质心的变化是否小于阈值,决定迭代是否继续
        boolean stop=true;
        String line1,line2;
        FSDataInputStream in1=fs.open(pervCenterFile);
        FSDataInputStream in2=fs.open(currentCenterFile);
        InputStreamReader isr1=new InputStreamReader(in1);
        InputStreamReader isr2=new InputStreamReader(in2);
        BufferedReader br1=new BufferedReader(isr1);
        BufferedReader br2=new BufferedReader(isr2);
        Sample prevCenter,currCenter;
        while((line1=br1.readLine())!=null && (line2=br2.readLine())!=null){
            prevCenter=new Sample();
            currCenter=new Sample();
            String []str1=line1.split("\\s+");
            String []str2=line2.split("\\s+");
            assert(str1[0].equals(str2[0]));
            for(int i=1;i<=Sample.DIMENTION;i++){
                prevCenter.arr[i-1]=Double.parseDouble(str1[i]);
                currCenter.arr[i-1]=Double.parseDouble(str2[i]);
            }
            if(Sample.getEulerDist(prevCenter, currCenter)>THRESHOLD){
                stop=false;
                break;
            }
        }
        //如果还要进行下一次迭代,就用当前质心替代上一次的质心
        if(stop==false){
            fs.delete(pervCenterFile,true);
            if(fs.rename(currentCenterFile, pervCenterFile)==false){
                log.error("质心文件替换失败");
                System.exit(1);
            }
        }
        return stop;
    }
     
    public static class ClusterMapper extends Mapper
     
     
      
       {
        Vector
      
      
       
        centers = new Vector
       
       
        
        ();
        @Override
        //清空centers
        public void setup(Context context){
            for (int i = 0; i < K; i++) {
                centers.add(new Sample());
            }
        }
        @Override
        //从输入文件读入centers
        public void map(LongWritable key, Text value, Context context)
                throws IOException, InterruptedException {
            String []str=value.toString().split("\\s+");
            if(str.length!=Sample.DIMENTION+1){
                log.error("读入centers时维度不对");
                System.exit(1);
            }
            int index=Integer.parseInt(str[0]);
            for(int i=1;i
        
        
         
          {
        int prev=-1;
        Sample center=new Sample();;
        int count=0;
        @Override
        //更新每个质心(除最后一个)
        public void reduce(IntWritable key,Iterable
         
         
           values,Context context) throws IOException,InterruptedException{ while(values.iterator().hasNext()){ Sample value=values.iterator().next(); if(key.get()!=prev){ if(prev!=-1){ for(int i=0;i 
           
         
        
        
       
       
      
      
     
     

新手第一次学习MapReduce框架实现kmeans算法,对算法和MapReduce编程还不是太多的了解,还需要更多的深入了解。未来希望用Hadoop实现海量数据的数据挖掘。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
K-Means算法是一种常见的无监督聚类算法,适用于大规模数据集的聚类分析。在Java编程语言中,实现K-Means算法可以使用一些开源的第三方机器学习库,例如Weka、Apache Mahout等。 以Weka为例,其提供了丰富的聚类算法实现,包括K-Means。用户可以使用Weka提供的API来实现K-Means算法。首先需要将数据转化为Weka框架中的Instances格式,即一个Instances对象表示一个实例集合,其中每个实例由多个属性组成。然后,通过构建一个SimpleKMeans对象,将转化后的数据传递给SimpleKMeans对象,即可进行聚类分析。 简单示例代码如下: ```java import weka.clusterers.SimpleKMeans; import weka.core.Instances; import weka.core.converters.ConverterUtils.DataSource; public class KMeansDemo { public static void main(String[] args) { try { Instances data = DataSource.read("path/to/dataset.arff"); SimpleKMeans kmeans = new SimpleKMeans(); kmeans.setSeed(10); kmeans.setPreserveInstancesOrder(true); kmeans.setNumClusters(3); kmeans.buildClusterer(data); System.out.println(kmeans.toString()); // 输出聚类结果 } catch (Exception e) { e.printStackTrace(); } } } ``` 上述代码首先从数据源加载数据集,然后创建一个SimpleKMeans对象,设置其参数(例如种子、簇数等),最后将数据集传递给kmeans实例对象进行聚类分析。最终输出结果可以通过SimpleKMeans对象的toString方法获取。 需要注意的是,K-Means算法需要对原始数据进行预处理(例如特征缩放、归一化等),特别是当数据集的特征数很多时。此外,Weka还提供了其他调节聚类效果的参数,例如聚类中心初始化方法、聚类质量评估方法等,用户可以根据实际情况进行调节。 综上所述,使用Java实现K-Means算法可以通过第三方机器学习库,例如Weka、Mahout等来完成。在实现过程中需要注意数据预处理及算法调节参数的设置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值