如何在Weka中移除信息增益属性选择后数据集的指定列
嘿,我看你已经用Weka的信息增益完成了属性排序,接下来要砍掉那些没价值的列、留下有用的属性对吧?我来帮你把代码补全,顺便讲讲两种实用的实现方式,按需选就行~
方法一:自动保留前N个高价值属性
这是最省心的方式,直接用Ranker指定要保留的属性数量,Weka会自动帮你生成筛选后的数据集:
import weka.core.Instances; import weka.attributeSelection.InfoGainAttributeEval; import weka.attributeSelection.Ranker; import weka.attributeSelection.AttributeSelection; import java.io.FileReader; import java.io.BufferedReader; public class InfoGainAttributeFilter { public static void main(String[] args) throws Exception { // 加载ARFF数据集 Instances data = new Instances(new BufferedReader(new FileReader("iris.arff"))); // 必须指定类别属性(通常是最后一列,索引从0开始) data.setClassIndex(data.numAttributes() - 1); // 初始化信息增益评估器和排名搜索器 InfoGainAttributeEval eval = new InfoGainAttributeEval(); Ranker search = new Ranker(); // 设置要保留的属性数量,比如这里保留前3个最有价值的 search.setNumToSelect(3); // 执行属性选择操作 AttributeSelection attSel = new AttributeSelection(); attSel.setEvaluator(eval); attSel.setSearch(search); attSel.SelectAttributes(data); // 生成只保留高价值属性的新数据集 Instances filteredData = attSel.reduceDimensionality(data); // 验证结果 System.out.println("原始属性数: " + data.numAttributes()); System.out.println("筛选后属性数: " + filteredData.numAttributes()); System.out.println("\n筛选后的数据集:\n" + filteredData); } }
关键步骤说明
- 指定类别属性:Weka需要明确知道哪一列是预测目标,所以用
setClassIndex把最后一列设为类别列,要是你的类别列在其他位置,改索引就行。 - 配置Ranker:
setNumToSelect(3)就是告诉Weka只留信息增益排名前三的属性,你可以根据自己的需求调整这个数字。 - 一键生成新数据集:
reduceDimensionality(data)方法会自动帮你删除冗余属性,不用手动操作列的删除。
方法二:手动自定义筛选属性
要是你不想单纯保留前N个,而是想结合业务需求挑选特定属性(比如跳过某个排名高但业务上没用的),可以用手动筛选的方式:
import weka.core.Instances; import weka.attributeSelection.InfoGainAttributeEval; import weka.attributeSelection.Ranker; import weka.attributeSelection.AttributeSelection; import java.io.FileReader; import java.io.BufferedReader; import java.util.Arrays; public class CustomAttributeFilter { public static void main(String[] args) throws Exception { Instances data = new Instances(new BufferedReader(new FileReader("iris.arff"))); data.setClassIndex(data.numAttributes() - 1); InfoGainAttributeEval eval = new InfoGainAttributeEval(); Ranker search = new Ranker(); // 这里先获取所有属性的排名,不限制数量 search.setNumToSelect(-1); AttributeSelection attSel = new AttributeSelection(); attSel.setEvaluator(eval); attSel.setSearch(search); attSel.SelectAttributes(data); // 获取按信息增益从高到低排序的属性索引数组 int[] rankedIndices = attSel.selectedAttributes(); System.out.println("属性排名(索引从高到低): " + Arrays.toString(rankedIndices)); // 手动选择要保留的属性,比如选第0和第2个索引的属性 int[] keepIndices = {rankedIndices[0], rankedIndices[2]}; // 别忘了把类别属性加进去(如果它不在已选列表里) int classIndex = data.classIndex(); boolean classIsKept = Arrays.stream(keepIndices).anyMatch(idx -> idx == classIndex); if (!classIsKept) { int[] updatedKeepIndices = new int[keepIndices.length + 1]; System.arraycopy(keepIndices, 0, updatedKeepIndices, 0, keepIndices.length); updatedKeepIndices[keepIndices.length] = classIndex; keepIndices = updatedKeepIndices; } // 生成新数据集,删除不需要的属性 Instances filteredData = new Instances(data, 0); // 倒序删除,避免索引混乱 for (int i = filteredData.numAttributes() - 1; i >= 0; i--) { boolean shouldKeep = Arrays.stream(keepIndices).anyMatch(idx -> idx == i); if (!shouldKeep) { filteredData.deleteAttributeAt(i); } } // 输出结果 System.out.println("\n自定义筛选后的数据集:\n" + filteredData); } }
额外小技巧
要是你想先看看每个属性的具体信息增益值再做决定,可以加这段代码:
// 打印每个属性的信息增益值 double[] gainValues = eval.evaluateAttributes(data); for (int i = 0; i < gainValues.length; i++) { System.out.println("属性 [" + data.attribute(i).name() + "] 的信息增益: " + gainValues[i]); }
这样就能清楚看到每个属性的价值,再决定留哪些~
内容的提问来源于stack exchange,提问作者Saeide
相关产品推荐
相关产品推荐

