开发环境:Intellij IDEA14 、Maven3.2、JDK1.7、Hadoop2.6 、mahout0.10
源码下载及运行参考:https://github.com/fansy1990/randomforest_classify
设计思路:
Mahout 随机森林算法(Random Forest)利用建立好的模型(BuildForest的输出结果)以及描述文件(Describe的输出结果),来对没有标签的数据进行分类。受TestForest中的CMapper的启发,其主要代码如下:
String line = value.toString(); if (!line.isEmpty()) { Instance instance = converter.convert(line); double prediction = forest.classify(dataset, rng, instance); lkey.set(dataset.getLabel(instance)); lvalue.set(Double.toString(prediction)); context.write(lkey, lvalue); }
这里还有一个问题,TestForest里面的line里面是包含Label的,如果我们传入的line不包含label,那么通过converter.conver进行转换为Instance,肯定是有问题的,那怎么办呢?
这个问题可以通过自定义Converter来解决,具体如下:
package util; import com.google.common.base.Preconditions; import org.apache.commons.lang3.ArrayUtils; import org.apache.mahout.classifier.df.data.Dataset; import org.apache.mahout.classifier.df.data.Instance; import org.apache.mahout.math.DenseVector; /** * Created by Fansy on 2015/11/2. */ public class DataConverter { // private static final Pattern COMMA_SPACE = Pattern.compile("[, ]"); private String splitter; private final Dataset dataset; public DataConverter(Dataset dataset,String splitter) { this.dataset = dataset; this.splitter=splitter; } public Instance convert(String string) { // all attributes (categorical, numerical, label), ignored // get rid of label ,the data only contains (categorical, numerical),ignored int nball = dataset.nbAttributes() + dataset.getIgnored().length-1; // 把label列添加到vector中,方便直接调用forest的classify函数 String[] tokens = string.split(splitter); Preconditions.checkArgument(tokens.length == nball, "Wrong number of attributes in the string: " + tokens.length + ". Must be " + nball); int nbattrs = dataset.nbAttributes(); DenseVector vector = new DenseVector(nbattrs); int aId = 0; for (int attr = 0; attr < nball;) { if(dataset.getLabelId()==attr){// label 列所在下标 vector.set(aId++,0);// 对于label列直接赋值0 } if (!ArrayUtils.contains(dataset.getIgnored(), attr)) { String token = tokens[attr].trim(); if ("?".equals(token)) { // missing value return null; } if (dataset.isNumerical(aId)) { vector.set(aId++, Double.parseDouble(token)); } else { // CATEGORICAL vector.set(aId, dataset.valueOf(aId, token)); aId++; } attr++; } } return new Instance(vector); } }这里在计算nball时,使用-1,即去掉Label这一个属性,这样我们的数据就可以通过Preconditions.checkArgument的验证了。
接着,在对line进行解析的过程中,要判断当前的id是否是Label(由于Label是在Describe的阶段指定的,所以这里还需要通过dataset.getLabelId来确定),如果是的话,那么就把vector的当前值赋值为0(当然这里赋值为任何的数值型都是可以的)。这样,等于是我们把传入的无label的数据人为的加入了一个任意指定的label,这样做的必要性是为了调用forest的classify函数。
分享,成长,快乐
脚踏实地,专注
转载请注明blog地址:http://blog.csdn.net/fansy1990