Java 给定属性索引,WEKA生成的模型似乎无法预测类别和分布 概述
我正在使用WEKA API 3.7.10(开发人员版本)来使用我预先制作的Java 给定属性索引,WEKA生成的模型似乎无法预测类别和分布 概述,java,machine-learning,weka,decision-tree,prediction,Java,Machine Learning,Weka,Decision Tree,Prediction,我正在使用WEKA API 3.7.10(开发人员版本)来使用我预先制作的.model文件 我做了25个模型:五个算法的五个结果变量 交替决策树 随机森林 后勤推进 随机子空间 我在J48、随机子空间和随机森林方面有问题 必要文件 以下是创建后我的数据的ARFF表示: @relation WekaData @attribute ageDiagNum numeric @attribute raceGroup {Black,Other,Unknown,White} @attribute st
.model
文件
我做了25个模型:五个算法的五个结果变量
- 交替决策树
- 随机森林
- 后勤推进
- 随机子空间
ARFF
表示:
@relation WekaData
@attribute ageDiagNum numeric
@attribute raceGroup {Black,Other,Unknown,White}
@attribute stage3 {0,I,IIA,IIB,IIIA,IIIB,IIIC,IIINOS,IV,'UNK Stage'}
@attribute m3 {M0,M1,MX}
@attribute reasonNoCancerSurg {'Not performed, patient died prior to recommended surgery','Not recommended','Not recommended, contraindicated due to other conditions','Recommended but not performed, patient refused','Recommended but not performed, unknown reason','Recommended, unknown if performed','Surgery performed','Unknown; death certificate or autopsy only case'}
@attribute ext2 {00,05,10,11,13,14,15,16,17,18,20,21,23,24,25,26,27,28,30,31,33,34,35,36,37,38,40,50,60,70,80,85,99}
@attribute time2 {}
@attribute time4 {}
@attribute time6 {}
@attribute time8 {}
@attribute time10 {}
@data
65,White,IIA,MX,'Not recommended, contraindicated due to other conditions',14,?,?,?,?,?
我需要从各自的模型中获取二进制属性time2
到time10
下面是我用来从所有模型文件中获取预测的代码片段:
private static Map<String, Object> predict(Instances instances,
Classifier classifier, int attributeIndex) {
Map<String, Object> map = new LinkedHashMap<String, Object>();
int instanceIndex = 0; // do not change, equal to row 1
double[] percentage = { 0 };
double outcomeValue = 0;
AbstractOutput abstractOutput = null;
if(classifier.getClass() == RandomForest.class || classifier.getClass() == RandomSubSpace.class) {
// has problems predicting time2 to time10
instances.setClassIndex(5);
} else {
// works as intended in LogitBoost and ADTree
instances.setClassIndex(attributeIndex);
}
try {
outcomeValue = classifier.classifyInstance(instances.instance(0));
percentage = classifier.distributionForInstance(instances
.instance(instanceIndex));
} catch (Exception e) {
e.printStackTrace();
}
map.put("Class", outcomeValue);
if (percentage.length > 0) {
double percentageRaw = 0;
if (outcomeValue == new Double(1)) {
percentageRaw = percentage[1];
} else {
percentageRaw = 1 - percentage[0];
}
map.put("Percentage", percentageRaw);
} else {
// because J48 returns an error if percentage[i] because it's empty
map.put("Percentage", new Double(0));
}
return map;
}
- 正如我之前所说的,
和LogitBoost
与其他三种方法相比,在这个简单的方法中没有问题,因为我遵循了教程ADTree
- [Solved]基于我的调整,并返回
如果被告知预测边界异常排列
到time2
time10
堆栈跟踪将根错误指向以下行:java.lang.ArrayIndexOutOfBoundsException: 0 at weka.classifiers.meta.Bagging.distributionForInstance(Bagging.java:586) at weka.classifiers.trees.RandomForest.distributionForInstance(RandomForest.java:602) at weka.classifiers.AbstractClassifier.classifyInstance(AbstractClassifier.java:70)
解决方案:我在为二进制变量outcomeValue = classifier.classifyInstance(instances.instance(0));
到time2
创建time10
的FastVector()
FastVector赋值过程中出现了一些复制粘贴错误,现在出现了一个新问题。它不再提供任何预测,而是返回一个错误:
它可以追溯到这条线java.lang.ArrayIndexOutOfBoundsException: 11 at weka.core.DenseInstance.value(DenseInstance.java:332) at weka.core.AbstractInstance.isMissing(AbstractInstance.java:315) at weka.classifiers.trees.j48.C45Split.whichSubset(C45Split.java:494) at weka.classifiers.trees.j48.ClassifierTree.getProbs(ClassifierTree.java:670) at weka.classifiers.trees.j48.ClassifierTree.classifyInstance(ClassifierTree.java:231) at weka.classifiers.trees.J48.classifyInstance(J48.java:266)
解决方案:事实上,我用outcomeValue = classifier.classifyInstance(instances.instance(0));
随机运行了这个程序,它成功了——给出了结果变量和相关分布J48
我希望有人能帮我解决这个问题。我真的不知道这段代码出了什么问题,因为我已经在线检查了Javadocs和示例,并且持续的预测仍然存在
(我目前正在检查WEKA GUI的主程序,但请在这里帮助我:-)我现在只研究了RandomForest问题。那是因为装袋课 从数据实例本身而不是从模型中提取不同类的数量。 你在你的文本中说time2到time10是二进制的,但你只是没有在你的ARFF文件中说, 所以Bagging类不知道有多少类 因此,您只需在ARFF文件中指定time2是二进制的,例如: @属性time2{0,1} 你再也不会有例外了 我没有研究J48问题,因为它可能与ARFF定义是同一个问题 测试代码:
public static void main(String [] argv) {
try {
Classifier cls = (Classifier) weka.core.SerializationHelper.read("bosom.100k.2.j48.MODEL");
J48 c = (J48)cls;
DataSource source = new DataSource("data.arff");
Instances data = source.getDataSet();
data.setClassIndex(6);
try {
double outcomeValue = c.classifyInstance(data.instance(0));
System.out.println("outcome "+outcomeValue);
double[] p = c.distributionForInstance(data.instance(0));
System.out.println(Arrays.toString(p));
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
我现在就试试,谢谢你的回复,完成后我会更新你。我刚刚用你的J48型号试过,没有任何异常:它返回0?是的,它给我[1.0;0.0],这与它的答案0是一致的。决策树不返回概率,所以有这样的值是可以的。我不确定问题是否来自J48模型,但我怀疑它来自于您在测试时创建的实例。您能否将失败的实例保存在磁盘上并发布它们?是的,因为决策树不会生成评分;他们只是做了一系列艰难的决定,所以你不能像其他分类器那样得到真正的值。不管怎样,我不知道如何在stackoverflow中正确地格式化我的代码……好吧,即使有像决策树这样的艰难决策,也有可能输出实数;虽然我现在不知道在Weka中J48实现的所有细节,但我知道C4.5算法在语料库上运行时,实际上计算了语料库中实例的比率;所以我怀疑你在J48中看到的实数实际上对应于这样的语料库比率,这不能真正被认为是概率。我怀疑基于决策树的算法能否从一个例子中给出可靠的概率分布。至少,我不会将它们解释为pdf:-)
public static void main(String [] argv) {
try {
Classifier cls = (Classifier) weka.core.SerializationHelper.read("bosom.100k.2.j48.MODEL");
J48 c = (J48)cls;
DataSource source = new DataSource("data.arff");
Instances data = source.getDataSet();
data.setClassIndex(6);
try {
double outcomeValue = c.classifyInstance(data.instance(0));
System.out.println("outcome "+outcomeValue);
double[] p = c.distributionForInstance(data.instance(0));
System.out.println(Arrays.toString(p));
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}