hadoop MultipleTextOutputFormat 解析mahout 中kmeans算法输出到不同文件

来源:互联网 发布:免费gis软件 编辑:程序博客网 时间:2024/04/28 22:39

hadoop 1.0.4 ,mahout 0.5

首先说明,本篇博客参考:http://blog.csdn.net/wypblog/article/details/17001131 。其次,这里的hadoop版本用处不是很大,虽然使用的是hadoop1.0.4的版本,但是用到的还是之前的JobConf,因为Job设置不了MultipleTextOutputFormat类。具体参考:http://blog.csdn.net/longshenlmj/article/details/9050359 。最后,mahout使用的版本是0.5的,如果要改为0.7的话,代码基本不用变,但是需要引入0.7中的相应路径的类(WeightedVectorWritable的路径0.5和0.7是不一样的)。

需求:把mahout中 kmeans算法算的clusteredPoints文件(这个是对原始数据的分类后的文件)按照不同的类别输出到不同的文件,同一个类别输出到同一个文件。

在hadoop1.0.4,mahout 0.5的环境中需要引入2个jar包,这样在编写代码的时候才不会报错,可以在http://www.docjar.com/jar_detail/commons-cli-2.0-mahout.jar.html  https://guava-libraries.googlecode.com/files/guava-r07.zip 下载(不同错误,可能需要找到相应的jar包才行)。

具体代码如下:

MultiFileDriver:

package hadoop.file.multifile;import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path;import org.apache.hadoop.io.IntWritable;import org.apache.hadoop.io.Text;import org.apache.hadoop.mapred.FileInputFormat;import org.apache.hadoop.mapred.FileOutputFormat;import org.apache.hadoop.mapred.JobClient;import org.apache.hadoop.mapred.JobConf;import org.apache.hadoop.mapred.JobStatus;import org.apache.hadoop.mapred.SequenceFileInputFormat;import org.apache.mahout.common.AbstractJob;import org.apache.mahout.common.HadoopUtil;/** * multiple files output driver * @author fansy * */public class MultiFileDriver extends AbstractJob {public static Configuration getMyConf(){Configuration conf=new Configuration();conf.set("mapred.job.tracker", "master:9001");conf.set("fs.default.name","master:9000");return conf;}@Overridepublic int run(String[] args) throws Exception {addInputOption();    addOutputOption();    addOption("prefix","pre", "the output file prefix name","prefix");    if (parseArguments(args) == null) {      return -1;}    Path input = getInputPath();    Path output = getOutputPath();    String prefix=getOption("prefix");    MyMultiOutputFormat.prefix=prefix;        HadoopUtil.delete(MultiFileDriver.getMyConf(), output);    JobConf job=new JobConf(MultiFileDriver.getMyConf(),MultiFileDriver.class);    job.setJobName("output multipul file  by input:"+input.getName());        FileInputFormat.setInputPaths(job, input);        FileOutputFormat.setOutputPath(job, output);                job.setMapperClass(MultiMapper.class);         job.setInputFormat(SequenceFileInputFormat.class);        job.setOutputFormat(MyMultiOutputFormat.class);                job.setOutputKeyClass(IntWritable.class);        job.setOutputValueClass(Text.class);         job.setNumReduceTasks(0);        int jobState=JobClient.runJob(job).getJobState();        if(jobState==JobStatus.SUCCEEDED){        return 0;        }        return -1;    }}
MutiMapper:

package hadoop.file.multifile;import java.io.IOException;import org.apache.hadoop.io.IntWritable;import org.apache.hadoop.io.Text;import org.apache.hadoop.mapred.MapReduceBase;import org.apache.hadoop.mapred.Mapper;import org.apache.hadoop.mapred.OutputCollector;import org.apache.hadoop.mapred.Reporter;import org.apache.mahout.clustering.WeightedVectorWritable;/** * use the old api * @author fansy * */public class MultiMapper extends MapReduceBase implements Mapper<IntWritable,WeightedVectorWritable,IntWritable,Text>{private Text outValue=new Text();/*@Overridepublic void map(IntWritable key,WeightedVectorWritable value,Context cxt) throws IOException, InterruptedException{String vec=value.getVector().asFormatString();outValue.set(vec);cxt.write(key, outValue);}*/@Overridepublic void map(IntWritable key, WeightedVectorWritable value,OutputCollector<IntWritable, Text> output, Reporter reporter)throws IOException {String vec=value.getVector().asFormatString();outValue.set(vec);output.collect(key, outValue);}}

 输出格式类:

package hadoop.file.multifile;import org.apache.hadoop.io.IntWritable;import org.apache.hadoop.io.Text;import org.apache.hadoop.mapred.lib.MultipleTextOutputFormat;public class MyMultiOutputFormat extends MultipleTextOutputFormat<IntWritable, Text> {public static String prefix ="prefix";@Overridepublic String generateFileNameForKeyValue(IntWritable key, Text value,String name){return prefix+"_"+key.get();}}
测试类:

package hadoop.file.multifile;import org.apache.hadoop.util.ToolRunner;import org.junit.Test;import junit.framework.TestCase;public class MultiFileDriverTest extends TestCase {@Testpublic void testRun() throws Exception{String[] args={"-i","/user/Administrator/output/clusteredPoints/part-m-00000","-o","/user/fansy/multi/01"};//String[] args={"-i","aa"};ToolRunner.run(MultiFileDriver.getMyConf(), new MultiFileDriver(), args);}}
测试输出不同文件截图如下:


把输入参数增加一个 -pre center,然后再次进行测试,发现输出文件的前缀并不是center,还是prefix,说明在MyMultiOutputFormat中设置static变量没有作用;这里其实主要是想实现可定制前缀的设计思路。这种思路不行的话,可以考虑使用文件的方式,即得到prefix变量之后把其写入hdfs中的一个文件,然后在MyMultiOutputFormat中把其读取出来进行赋值,这样应该是ok的。


如果您觉得lz的blog或者资源还ok的话,可以选择给lz投一票,多谢。(投票地址:http://vote.blog.csdn.net/blogstaritem/blogstar2013/fansy1990 )



分享,成长,快乐

转载请注明blog地址:http://blog.csdn.net/fansy1990





0 0