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