调用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));
}
}
说一下这个问题的背景和需求,我们都知道,特征选择是机器学习算法正确发挥作用的前提,我在之前这篇博客中也大概介绍了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));
}
}
相关文章推荐
- 使用随机森林和mRMR进行特征选择
- 调用Weka API和使用GUI进行分类时,输出结果相反的原因及解决方法
- 【Machine Learning】使用随机森林进行特征选择
- 使用PHP调用微信API,使用微信做通知类应用的方法
- 随机森林之特征选择
- 机器学习:用随机森林来选择特征
- Win32 api使用中调用GetOpenFileName打开文件对话框无响应的解决方法
- 使用J2SE API读取Properties文件的六种方法(选择自 kindani 的 Blog )
- 调用未绑定的父类方法和使用supper 函数 之间的选择.
- 【原】matlab与调用lingo/lindo api的方法以及简单的使用
- weka的java使用(3)——特征选择
- 用随机森林做特征选择
- 借助weka实现的分类器进行针对文本分类问题的特征词选择实验(实验代码备份)
- 使用LIBSVM对原始文本语料进行文本分类(二)——特征选择(信息增益方法)
- 面向高斯核朴素贝叶斯分类器的特征选择方法
- 本地方法(JNI)——使用调用API
- 容器的定义和使用 构造方法 普通方法的调用 查看API及类的继承与子类
- android以欺骗的方法使用隐藏API调用举例(国际化,多语言)
- Scikit-Learn 随机森林分类器的使用
- 仿APiDemo使用ProgressDialog 并解决调用dismiss方法后没有对话框不消失的问题