您的位置:首页 > 其它

调用Weka API,在使用分类器(以随机森林Random Forest为例)的同时使用特征选择方法

2017-10-11 21:32 671 查看
这也是在科研中的现实需求,本来不是很想用weka的,但感觉相比之下比R工作量小些。

说一下这个问题的背景和需求,我们都知道,特征选择是机器学习算法正确发挥作用的前提,我在之前这篇博客中也大概介绍了Weka中使用的特征选择算法。按照网友的介绍,其实一般不用单独使用Weka的特征选择类,例如这里说的:http://blog.sciencenet.cn/blog-713110-568654.html。但问题在于,如果我们使用的训练数据和测试数据是两个集合,那么并不能按照类似上面这篇文章中说的,用meta-classifier,并使用10折交叉验证。

所以,我自己对照Weka的User Manual,简单写了一下,如果测试数据和训练数据是两个完全不同的数据集时,如何正确在使用分类器的时候使用特征选择方法,下面的代码段以随机森林(Random Forest)为例进行说明。简单加了一些注释,不清楚的地方,请大家自行查阅Weka的Document。

import java.util.Enumeration;

import weka.core.Attribute;
import weka.core.Instances;
import weka.core.converters.ConverterUtils.DataSource;
import weka.attributeSelection.CfsSubsetEval;
import weka.attributeSelection.GreedyStepwise;
import weka.filters.Filter;
import weka.filters.supervised.attribute.AttributeSelection;
import weka.classifiers.trees.RandomForest;
import weka.classifiers.Evaluation;

public class WekaUse {

public static void main(String[] args) throws Exception {

DataSource source=new DataSource("data\\X.csv");//训练数据
Instances data=source.getDataSet();
if(data.classIndex()==-1)
data.setClassIndex(data.numAttributes()-1);//使用最后一个特征作为类别特征

DataSource sourceTest=new DataSource("data\\Y.csv");//测试数据
Instances test=sourceTest.getDataSet();
if(test.classIndex()==-1)
test.setClassIndex(test.numAttributes()-1);

AttributeSelection filter=new AttributeSelection();
CfsSubsetEval eval=new CfsSubsetEval();
GreedyStepwise search=new GreedyStepwise();
search.setSearchBackwards(true);
filter.setEvaluator(eval);
filter.setSearch(search);
filter.setInputFormat(data);

Instances newData=Filter.useFilter(data, filter);//使用特征选择方法,生成新的训练数据
Enumeration<Attribute> oldDataAttributes = data.enumerateAttributes();

int index=0;
while(oldDataAttributes.hasMoreElements()){
Attribute oldAttribute=oldDataAttributes.nextElement();
String thisAttributeString=oldAttribute.toString();
Enumeration<Attribute> newDataAttributes = newData.enumerateAttributes();

int exist=0;
while(newDataAttributes.hasMoreElements()){
Attribute newAttribute=newDataAttributes.nextElement();
String newString=newAttribute.toString();
System.out.println(newString);
if(newString.equals(thisAttributeString))
exist=1;
}
if(exist==0){
test.deleteAttributeAt(index);
index--;
}
index++;
}//这段代码的主要作用是将测试数据修改成和新的训练数据一样的格式,这部分代码写得不够简略,但可以实现相应功能。

RandomForest forest=new RandomForest();
forest.buildClassifier(newData);//用经过特征选择的训练数据训练随机森林

Evaluation classifierEval=new Evaluation(test);
classifierEval.evaluateModel(forest, test);

System.out.println(classifierEval.toSummaryString("\nResults\n\n", false));
System.out.println(classifierEval.areaUnderROC(0));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: