mahout决策树之Partial Implementation源码分析 part2

决策树Partial Implementation源码的第二部分为:BuildForest,其源码所在位置为:MAHOUT_HOME/example/src/main/java/org/apache/mahout/classifier/df/mapreduce/BuildForest.java,现对其进行简要分析:

打开源码可以看到,BuildForest有如下四个步骤:

(1)创建一个DecisionTreeBuilder对象,并设置四个参数:

DecisionTreeBuilder treeBuilder = new DecisionTreeBuilder();
treeBuilder.setM(m);
treeBuilder.setComplemented(complemented);
treeBuilder.setMinSplitNum(minSplitNum);
treeBuilder.setMinVarianceProportion(minVarianceProportion)
(2)新建Builder接口,此处因为是并行参数(-p)所以使用PartialBuilder实现类:

Builder forestBuilder = new PartialBuilder(treeBuilder, dataPath, datasetPath, seed, getConf());
初始化的ParitalBuilder类的参数为:treeBuilder(DecisionTreeBuilder),这个参数只设置了四个参数,其他都未设置;

dataPath:输入训练数据的路径;datasetPath:对训练数据的描述文件的路径;seed:初始种子(暂时未深究);

getConf():各种配置参数(个人猜测);

(3)创建森林,设置树的个数:

DecisionForest forest = forestBuilder.build(nbTrees);
nbTrees表示要创建树的个数;

(4)把上面创建的森林写入HDFS:

DFUtils.storeWritable(getConf(), forestPath, forest);
上面四个步骤是BuildForest的四个主要操作,其他都是一些参数设置之类的辅助操作。对于上面四个步骤,其中第三歩,调用build方法最为复杂,现简要分析如下:

Builder是抽象类,定义了build非抽象方法,实现类PartialBuilder不用覆写此方法,而直接调用其父类(Builder)的build方法,Builder的build方法可分为如下几步:

<1>设置参数,包括seed,nbTrees,treeBuilder:

 setRandomSeed(conf, seed);
 setNbTrees(conf, nbTrees);
 setTreeBuilder(conf, treeBuilder);
<2>把训练数据的描述文件放入内存中(这样理解是否?个人理解就是类似全局变量的作用):

DistributedCache.addCacheFile(datasetPath.toUri(), conf);
<3>新建Job任务,名字为‘decision forest builder’:

Job job = new Job(conf, "decision forest builder");
<4>对新建的job进行配置:

configureJob(job);
<5>提交任务,等待结果:

runJob(job){
   return job.waitForCompletion(true);
}
<6>调用parseOutput方法得到森林(forest),删除输出文件,返回结果:

DecisionForest forest = parseOutput(job);
HadoopUtil.delete(conf, outputPath);
return forest;
这里为什么要删除outputPath呢?下面再说。

其中第<4>、<6>步在Builder中都是抽象方法,由其实现类进行覆写实现,在PartialBuilder中的configureJob()和parseOutput()如下:

cofigureJob():设置这个job的相关参数,Mapper为Step1Mapper,输出Key和Value类型分别为:TreeID、MapredOutput,输入文件为dataPath,输出文件为outputPath;

    FileInputFormat.setInputPaths(job, getDataPath());
    FileOutputFormat.setOutputPath(job, getOutputPath(conf));
   
    job.setOutputKeyClass(TreeID.class);
    job.setOutputValueClass(MapredOutput.class);
    
    job.setMapperClass(Step1Mapper.class);
这里输出文件的路径设置为outputPath,所以在上面第<6>步中要删除这个文件;

parseOutput():其操作如下:

    Node[] trees = new Node[numTrees];       
    processOutput(job, outputPath, keys, trees);
    return new DecisionForest(Arrays.asList(trees));
processOutput():操作如下:

for (Pair<TreeID,MapredOutput> record : new SequenceFileIterable<TreeID, MapredOutput>(path, conf)) {
     MapredOutput value = record.getSecond();
     if (trees != null) {
          trees[index] = value.getTree();
     }
     index++;
}
processOutput的操作也就是把输出文件的内容全部读入trees(Node[])中,然后以trees为参数建立一个DecisionForest返回;

DecisionForest返回过程如下:DecisionForest-->processOutput(PartialBuilder)-->parseOutput(PartialBuilder)-->build(PartialBuilder);

在build方法中的<3>、<4>、<5>步是整个BuilderForest的关键所在,所涉及到的类目前可以很明显的看到的有:TreeID(map输出Key类型)、MapredOutput(map输出Value类型)、Step1Mapper(job的Mapper操作);


<3><4><5>步下次再看。。


分享,快乐,成长


转载请注明出处:http://blog.csdn.net/fansy1990

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值