我正在使用InstanceQuery SQL查询构建我的Instances。但是我的查询结果并不总是与SQL中的正常顺序相同。 由于不同SQL构造的此实例具有不同的标头。下面是一个简单的例子。我怀疑我的结果会因为这种行为而改变。
标题1
@attribute duration numeric
@attribute protocol_type {tcp,udp}
@attribute service {http,domain_u}
@attribute flag {SF}
标题2
@attribute duration numeric
@attribute protocol_type {tcp}
@attribute service {pm_dump,pop_2,pop_3}
@attribute flag {SF,S0,SH}
我的问题是:如何向实例构建提供正确的标头信息。
是否可以使用以下工作流程?
我正在使用以下sql函数从数据库中获取实例。
public static Instances getInstanceDataFromDatabase(String pSql
,String pInstanceRelationName){
try {
DatabaseUtils utils = new DatabaseUtils();
InstanceQuery query = new InstanceQuery();
query.setUsername(username);
query.setPassword(password);
query.setQuery(pSql);
Instances data = query.retrieveInstances();
data.setRelationName(pInstanceRelationName);
if (data.classIndex() == -1)
{
data.setClassIndex(data.numAttributes() - 1);
}
return data;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
答案 0 :(得分:0)
我尝试了各种解决问题的方法。但似乎weka内部API现在不允许解决这个问题。为了我的目的,我修改了weka.core.Instances附加命令行代码。此代码也在此answer
中给出根据这个,这是我的解决方案。我创建了一个SampleWithKnownHeader.arff文件,其中包含正确的标头值。我用以下代码读取了这个文件。
public static Instances getSampleInstances() {
Instances data = null;
try {
BufferedReader reader = new BufferedReader(new FileReader(
"datas\\SampleWithKnownHeader.arff"));
data = new Instances(reader);
reader.close();
// setting class attribute
data.setClassIndex(data.numAttributes() - 1);
}
catch (Exception e) {
throw new RuntimeException(e);
}
return data;
}
之后,我使用以下代码创建实例。我不得不使用StringBuilder和实例的字符串值,然后将相应的字符串保存到文件。
public static void main(String[] args) {
Instances SampleInstance = MyUtilsForWeka.getSampleInstances();
DataSource source1 = new DataSource(SampleInstance);
Instances data2 = InstancesFromDatabase
.getInstanceDataFromDatabase(DatabaseQueries.WEKALIST_QUESTION1);
MyUtilsForWeka.saveInstancesToFile(data2, "fromDatabase.arff");
DataSource source2 = new DataSource(data2);
Instances structure1;
Instances structure2;
StringBuilder sb = new StringBuilder();
try {
structure1 = source1.getStructure();
sb.append(structure1);
structure2 = source2.getStructure();
while (source2.hasMoreElements(structure2)) {
String elementAsString = source2.nextElement(structure2)
.toString();
sb.append(elementAsString);
sb.append("\n");
}
} catch (Exception ex) {
throw new RuntimeException(ex);
}
MyUtilsForWeka.saveInstancesToFile(sb.toString(), "combined.arff");
}
我的文件代码保存实例如下所示。
public static void saveInstancesToFile(String contents,String filename) {
FileWriter fstream;
try {
fstream = new FileWriter(filename);
BufferedWriter out = new BufferedWriter(fstream);
out.write(contents);
out.close();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
这解决了我的问题,但我想知道是否存在更优雅的解决方案。
答案 1 :(得分:0)
我解决了Add
过滤器的类似问题,该过滤器允许向Instances
添加属性。您需要为两个数据集添加正确的Attibute
及适当的值列表(在我的情况下 - 仅测试数据集):
加载列车和测试数据:
/* "train" contains labels and data */
/* "test" contains data only */
CSVLoader csvLoader = new CSVLoader();
csvLoader.setFile(new File(trainFile));
Instances training = csvLoader.getDataSet();
csvLoader.reset();
csvLoader.setFile(new File(predictFile));
Instances test = csvLoader.getDataSet();
使用Add
过滤器设置新属性:
Add add = new Add();
/* the name of the attribute must be the same as in "train"*/
add.setAttributeName(training.attribute(0).name());
/* getValues returns a String with comma-separated values of the attribute */
add.setNominalLabels(getValues(training.attribute(0)));
/* put the new attribute to the 1st position, the same as in "train"*/
add.setAttributeIndex("1");
add.setInputFormat(test);
/* result - a compatible with "train" dataset */
test = Filter.useFilter(test, add);
结果,"训练"和"测试"是相同的(兼容Weka机器学习)