2012-08-03 82 views
0

我正在使用InstanceQuery SQL查询构造我的Instances。但是我的查询结果并不总是和SQL中的正常一样。 由于不同的SQL构建的这个实例有不同的头文件。一个简单的例子可以在下面看到。我怀疑我的结果因为这种行为而改变。所有数据库查询的相同实例头(arff)

页眉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} 

我的问题是:我怎样才能给正确的头信息,以实例建设。

就像下面的工作流程是可能的?

  1. 从arff文件或其他地方获取预先准备好的标题信息。
  2. 给例如建设这个头信息
  3. 调用SQL函数,并得到实例(头+数据)

我使用下面的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

我试过各种方法来解决我的问题。但似乎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); 
    } 

这解决了我的问题,但我不知道是否更优雅的解决方案存在。

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的机器学习兼容)

相关问题