Java调用预训练Bagging随机森林classifyInstance报数组越界错误求助
解决Weka Bagging随机森林classifyInstance数组越界异常
问题背景
在Java环境中调用预训练的Bagging随机森林模型执行classifyInstance方法时,抛出ArrayIndexOutOfBoundsException异常,但相同代码运行SMO、朴素贝叶斯模型完全正常。
错误栈信息
java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1 at weka.classifiers.meta.Bagging.distributionForInstance(Bagging.java:791) at weka.classifiers.AbstractClassifier.classifyInstance(AbstractClassifier.java:173) at com.msc.sinhalasongpredictorbackend.service.ClassifyService.runRandomForest(ClassifyService.java:97)
相关代码片段
private Integer runRandomForest() throws Exception { Bagging randomForest = (Bagging) SerializationHelper.read(randomForestLocation); CSVLoader loader = new CSVLoader(); try (InputStream fis = new FileInputStream(csvFeatureOutput)) { loader.setSource(fis); Instances trainingDataSet = loader.getDataSet(); List values = new ArrayList(); values.add("1.0"); trainingDataSet.insertAttributeAt(new Attribute("label", values), trainingDataSet.numAttributes()); trainingDataSet.setClassIndex(trainingDataSet.numAttributes() - 1); for (Instance i : trainingDataSet) { Double result = randomForest.classifyInstance(i); return result.intValue(); } return -1; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e.getMessage()); } }
输入CSV单条实例数据
13.46,0.1023,0.002532,221.9,0.001693,0.06354,0.05821,26.46,13.22,134.3,0.000406,0.0742,0.3509,0.2297,0.2114,0.1953,0.2013,0.1948,0.1646,0.1817,0,0.166,15.16,1359,107900,22360000,29.32,0.1582,0.001677,1679,0.00328,0.1308,0.5461,67.77,215.6,462.1,0.0095,-0.8899,0.4612,-0.04562,0.2517,-0.005843,-0.004694,0.01806,0.006126,0.02237,0,0.3106,58.65,3476,279200,51460000,?
错误原因分析
Weka模型对输入实例的属性结构有严格要求:预测时的实例属性数量、顺序、类型必须与模型训练时完全一致,包括类属性的位置和类别数量。
你的代码中手动插入了一个新的标称型label属性(仅包含"1.0"一个类别),并将其设为类索引,这导致输入实例的属性结构与预训练模型的训练数据集结构不匹配。Bagging在合并基分类器的预测分布时,会基于训练时的类类别数量分配数组长度,而当前输入实例的类属性只有1个类别,从而触发数组越界。
修复方案
移除手动插入label属性的代码,直接将CSV原有最后一列设为类索引,确保输入实例结构与预训练模型一致:
修改后的代码:
private Integer runRandomForest() throws Exception { Bagging randomForest = (Bagging) SerializationHelper.read(randomForestLocation); CSVLoader loader = new CSVLoader(); try (InputStream fis = new FileInputStream(csvFeatureOutput)) { loader.setSource(fis); Instances trainingDataSet = loader.getDataSet(); // 直接将原有最后一列设为类索引,无需新增属性 trainingDataSet.setClassIndex(trainingDataSet.numAttributes() - 1); for (Instance i : trainingDataSet) { Double result = randomForest.classifyInstance(i); return result.intValue(); } return -1; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e.getMessage()); } }
额外验证点:
- 确认预训练模型的训练数据集与当前CSV的属性数量、顺序、类型完全一致
- CSV最后一列的
?会被Weka识别为缺失值,不影响结构匹配,模型预测时会自动处理
内容的提问来源于stack exchange,提问作者Malinda Peiris
相关产品推荐
相关产品推荐

