我有一个ArrayList测试集。此列表包含我在WEKA中进行SMO评估的数据。我想使用Evaluation weka类来对我的testset进行分类。在最简单的情况下,我有一个由ArrayList中的一个图像提取的特征。为了在下面使用我的列表,必须进行什么转换:
Evaluation eval = new Evaluation(testset); // how can I cast testset2 Instances object?
eval.evaluateModelOnce(c, data);
这段代码来自here:我正在使用它来训练SMO模型。训练数据集包含存储在.arff文件中的特征提取的训练图像。在测试过程中,我在我的代码中读取一个图像,我计算了这些特征,将它们存储在arrayList中,而不将它们存储在.arff文件中。我想将列表直接转换为Instances对象并继续进行分类。
编辑:我试图做其他事情,首先将arrayList转换为数组双数据,并继续我继续我的火车集:
int numAtts = data[0].length;
FastVector atts = new FastVector(numAtts);
for (int att = 0; att < numAtts; att++) {
atts.addElement(new Attribute("Attribute" + att, att));
}
int numInstances = data.length;
Instances dataset = new Instances("Dataset", atts, numInstances);
for (int inst = 0; inst < numInstances; inst++) {
dataset.add(new Instance(1.0, data[inst]));
}
不过我收到了:
Exception in thread "main" java.lang.ClassCastException: javax.management.Attribute cannot be cast to weka.core.Attribute
编辑:
我改变了一点我的代码
double data[][] = new double[1][];
data[0] = dt;
System.out.println(args[1]);
System.out.println(args[2]);
ClothesAnalysis asdf = new ClothesAnalysis();
weka.classifiers.Classifier c = asdf.loadModel(new File(args[1]), args[2]);
String opt = ("-C 100 -K weka.classifiers.functions.supportVector.NormalizedPolyKernel");
String[] options = opt.split(" ");
int numAtts = data[0].length;
FastVector atts = new FastVector(numAtts);
for (int att = 0; att < numAtts; att++) {
atts.addElement(new weka.core.Attribute("Attribute" + att, att));
}
int numInstances = data.length;
Instances dataset = new Instances("Dataset", atts, numInstances);
for (int inst = 0; inst < numInstances; inst++) {
dataset.add(new Instance(1.0, data[inst]));
}
dataset.setClassIndex(dataset.numAttributes() - 1);
Evaluation eval = new Evaluation(dataset);
eval.evaluateModel(c, dataset);
System.out.println(eval.toSummaryString("\nResults\n======\n", false));
我收到错误:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 84
at weka.filters.unsupervised.attribute.ReplaceMissingValues.convertInstance(ReplaceMissingValues.java:274)
at weka.filters.unsupervised.attribute.ReplaceMissingValues.input(ReplaceMissingValues.java:140
)
at weka.classifiers.functions.SMO.distributionForInstance(SMO.java:1368)
at weka.classifiers.Classifier.classifyInstance(Classifier.java:84)
at
weka.classifiers.Evaluation.evaluateModelOnceAndRecordPrediction(Evaluation.java:1448)
at weka.classifiers.Evaluation.evaluateModel(Evaluation.java:1407)
at LBP.LBPDemo.main(LBPDemo.java:466)
EDIT2:我的问题是我必须添加类标签的最后一个属性,所以我想添加:
atts.addElement(new weka.core.Attribute(" class {1, 2, 3, 4, 5, 6, 7}" , numAtts-1));
这是我的问题的索引。但是,这不是向数据集添加索引的正确方法。当我在最后一个属性中打印数据集时,我得到:
@attribute ' class {1, 2, 3, 4, 5, 6, 7}' numeric
我想删除撇号和数字以便正确读取。
假设您需要一个Instances对象,则无法将ArrayList转换为该对象。
我想你需要使用DataSource的getDataSet()和自定义Loader(constructor)。
我想它应该是这样的:
new DataSource(new ListLoader(testData)).getDataSet();
我不确定这是否彻底回答了你的问题,但如果你想在生成实例时使用ArrayList<Attribute>
而不是FastVector
作为参数,请尝试为实例实现一个新的构造函数:
/**
* Creates an empty set of instances. Uses the given
* attribute information. Sets the capacity of the set of
* instances to 0 if its negative. Given attribute information
* must not be changed after this constructor has been used.
*
* @param name the name of the relation
* @param attInfo the attribute information
* @param capacity the capacity of the set
* @throws IllegalArgumentException if attribute names are not unique
*/
public Instances(String name, ArrayList<Attribute> attInfo, int capacity) {
// check whether the attribute names are unique
HashSet<String> names = new HashSet<String>();
StringBuffer nonUniqueNames = new StringBuffer();
for (Attribute att: attInfo) {
if (names.contains(att.name())) {
nonUniqueNames.append("'" + att.name() +"' ");
}
names.add(att.name());
}
if (names.size() != attInfo.size())
throw new IllegalArgumentException("Attribute names are not unique!" +
" Causes: " + nonUniqueNames.toString());
names.clear();
m_RelationName = name;
m_ClassIndex = -1;
m_Attributes = attInfo;
for (int i = 0; i < numAttributes(); i++) {
attribute(i).setIndex(i);
}
m_Instances = new ArrayList<Instance>(capacity);
}
...您可以将此代码复制粘贴到weka.core.Instances类
我发现这个解决方案用于将数据从内存加载到weka实例中。不是最美丽的,但它的工作原理。基本上,您将arff文件内容生成为字符串,然后从该字符串的StringReader
创建Instances对象。
String arffString = "@relation RelationName\n\n@attribute attributeName1\n@attribute attributeName2 {No,Yes}\n\n@data\n'atribute1value',?\n";
unlabeledData = new Instances(
new BufferedReader(new StringReader(arffString)));