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

这也是在科研中的现实需求,本来不是很想用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));
	}
}


  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值