mahout之canopy聚类算法

来源:互联网 发布:java里把大括号替换 编辑:程序博客网 时间:2024/05/22 05:31

mahout中数据挖掘算法是运行在hadoop之上的分布式算法,可以分布式运行也可以在单机上运行。

这篇博文是本人你学习mahout算法的开始,以下是个人对mahout中实现的canopy的理解,如果错误,欢迎纠正


首先下载mahout-0.12的源码,解压后有个examples文件夹,该文件夹里面有对mahout算法使用的例子,打开

\examples\src\main\java\org\apache\mahout\clustering\syntheticcontrol\canopy\job.java。该文件里面写了如何使用canopy算法。以下以此为主线进行讲解


该文件也可以在以下地址下载到:



首先,可以很直观的看到,Job类继续了AbstractJob类,何为AbstractJob类呢,它是org.apache.mahout.common包下的一个抽象类,该类封装运行时输出输出路径,以及通过命令行运行jar包时,参数的解析和存储等,所以自己写改写mahout算法或者基于原有的mahout算法添加等都要继承它。AbstractJob抽象类也继承了 Configured类和 Tool 接口。Configured类是运行配置类相关。Tool接口中有个run方法,所以继续AbstractJob都要实现run方法。run中一般实现命令行运行时参数的解析和赋值,然后调用mahout中canopy算法进行使用。


在job.java文件中,main方法如下:

 public static void main(String[] args) throws Exception {
    if (args.length > 0) {
      log.info("Running with only user-supplied arguments");
      ToolRunner.run(new Configuration(), new Job(), args);
    } else {
      log.info("Running with default arguments");
      Path output = new Path("hdfs://192.168.95.131:9000/user/mahout/Canopyoutput");
      HadoopUtil.delete(new Configuration(), output);
      //输入文件数据之间一定要以空格隔开,否则解析会出错
      run(new Path("movement_libras.data1.txt"), output, new EuclideanDistanceMeasure(), 0.3, 0.6);
    }
  }

意思是:如果提交任务时有传参数的话,则运行  ToolRunner.run(new Configuration(), new Job(), args)。其中ToolRunner类作用是让继承了AbstractJob类的 Job调用自己的run方法(重载tool中的run方法),其中args为run方法的参数。

接下来,我们来看下job.java如何实现tool中的run方法,代码如下:

@Override
  public int run(String[] args) throws Exception {

  //添加默认的输入目录
    addInputOption();

 //添加默认的输出目录
    addOutputOption();

//添加默认的距离计算方法
    addOption(DefaultOptionCreator.distanceMeasureOption().create());

//添加默认的t1门限值
    addOption(DefaultOptionCreator.t1Option().create());

//添加默认的t2门限值
    addOption(DefaultOptionCreator.t2Option().create());

//添加是否去输出目录进行覆盖
    addOption(DefaultOptionCreator.overwriteOption().create());

    Map<String, List<String>> argMap = parseArguments(args);
    if (argMap == null) {
      return -1;
    }
    Path input = getInputPath();
    Path output = getOutputPath();
    if (hasOption(DefaultOptionCreator.OVERWRITE_OPTION)) {
      HadoopUtil.delete(new Configuration(), output);
    }
    String measureClass = getOption(DefaultOptionCreator.DISTANCE_MEASURE_OPTION);
    double t1 = Double.parseDouble(getOption(DefaultOptionCreator.T1_OPTION));
    double t2 = Double.parseDouble(getOption(DefaultOptionCreator.T2_OPTION));
    DistanceMeasure measure = ClassUtils.instantiateAs(measureClass, DistanceMeasure.class);
    run(input, output, measure, t1, t2);
    return 0;
  }

在run方法中,刚开始是添加默认的参数,然后解析comment line的命令,最后调用job.java自身写的run方法


job.java自身的run方法如下:

private static void run(Path input, Path output, DistanceMeasure measure,
      double t1, double t2) throws Exception {
    Path directoryContainingConvertedInput = new Path(output,
        DIRECTORY_CONTAINING_CONVERTED_INPUT);//output是父目录,DIRECTORY_CONTAINING_CONVERTED_INPUT是父目录下的子目录
    InputDriver.runJob(input, directoryContainingConvertedInput, //data里面存放着数据序列化的文件
        "org.apache.mahout.math.RandomAccessSparseVector");
    CanopyDriver.run(new Configuration(), directoryContainingConvertedInput,
        output, measure, t1, t2, true, 0.0, false);
    // run ClusterDumper
    ClusterDumper clusterDumper = new ClusterDumper(new Path(output,
       "clusters-0-final"), new Path(output, "clusteredPoints"));
    //String aa="C:\\Users\\whl\\Desktop\\WHL\\common-knowleage\\hadoop\\mahout-exec\\canopy\\output\\a.txt";
    //clusterDumper.setTermDictionary(aa, "text");AbstractJob
    //Job job=new Job();
    //this.outputFile=new File(aa);
    clusterDumper.printClusters(null);
    
    //cluster-0-finall文件夹存放的是聚类中心的信息
    //clusteredPoints存放的是点的聚类结果信息
  }

其中InputDriver job中,只有mapper处理类,是为了将数据输出为cannopy能够处理的数据类型,要求原始数据类型行代表一条记录,记录内不同属性的值用空格隔开。

其中cannopy要求输入的数据为sequencefileinputformat类型,在sequenceFile中,mapper的输入的value类型是vectorwritable,输出是clusterwritable;ruducer的输入输出都是clusterwritable。在hdfs中,序列化的类型都继承了writable接口,实现了read和write函数,read函数作用将从序列化文件读入内存,而write函数的作用是将类序列化,在hadoop中,已经实现了intwritable,doublewritable,longwritable。而mahout.math中实现了算法相关的序列化类。同时,hadoop中mapper向reducer传递的数据也是序列化表示形式。

 CanopyDriver以inputDriver的输出文件作为它的输入文件,运行map,reduce聚类算法,其中true表示进行数据的聚类过程,如果为false则表示只计算了中心点向量,不对数据进行聚类划分。0.0参数表示聚类的门限值(vectors having pdf below this value will not be clustered. Its value should be between 0 and 1.,具体还未搞清楚),false参数表示是否序列化( execute sequentially if true)。

ClusterDumper类可以将聚类结果打印出来


为清楚的点:

    addInputOption();
    addOutputOption();
    addOption(DefaultOptionCreator.distanceMeasureOption().create());

   默认参数的添加,内部是如何解析赋值的,如何覆盖默认参数?

option的使用见:

http://blog.csdn.net/utopia_1919/article/details/51832471博文

接下来学习如何使用canopy

0 0