目前,我正在进行一个项目,将搜索查询分类为以下八种类型:{运动员,演员,艺术家,政治家,地理,设施,QA,定义}。经过一番努力,我使用多层感知器分类器对300个样本查询进行评估,并采用分层10折交叉验证,成功地将78%的实例正确分类,我认为这是一个相当不错的结果。
我使用Weka Java库将整个项目实现为Java代码,因此我可以编写一个程序,动态地将查询输入分类器并检索其查询类型。我成功地实现了整个分类器训练部分。下一步将是使用classifyInstance()或distributionForInstance()来确定查询被分类到的类别。
然而,classifyInstance()仅返回一个双精度值,我不知道如何从中获取实际的查询类型。Weka wikispaces告诉我可以使用
unlabeled.classAttribute().value((int) clsLabel);
在调用classifyInstance()后获取类的字符串表示,但在我的情况下,这似乎总是返回空字符串。
使用distributionForInstance(),我能够成功地检索到一个包含八个介于0和1之间的双精度值的数组(这很好,因为我分类了八种查询类型)。然而,这个数组的顺序是什么?结果数组中的第一个元素是否是我训练文件中出现的第一个类?还是这个结果数组中有一些其他预定义的元素顺序(例如按字母顺序排列)?Weka文档对此没有任何信息。
我希望有人能帮我解决这个问题!
回答:
在Weka内部,所有值都被处理为双精度值。当你创建Attribute
时,你传递给它一个字符串数组,列出可能的标称值。分类返回的双精度值是原始数组中所选属性的索引。所以,如果你的代码看起来像这样:
String[] attributeValues = {"a", "b", "c"};Attribute a = new Attribute("attributeName", attributeValues);
并且classifyInstance()
返回2
,那么它选择的类将是attributeValues[2]
或c
。
使用distributionForInstance()
方法时,两个数组的索引是匹配的,因此attributeValues[0]
是返回数组第一个元素的字符串名称。
更新(因为被扣分)如果您让Weka自己创建Instances
对象(例如,如果您从arff文件读取),上述方法将不起作用。根据您的问题来看,这似乎不是这种情况,但如果是,请发布代码,以便我们了解发生了什么。