【问题标题】:Same Instances header ( arff ) for all my database queries我所有数据库查询的相同实例标头( arff )
【发布时间】:2014-11-12 06:20:28
【问题描述】:

我正在使用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}

我的问题是:如何为实例构造提供正确的标头信息。

类似下面的工作流程是可能的吗?

  1. 从 arff 文件或其他地方获取预先准备好的标头信息。
  2. 给实例构造这个头信息
  3. 调用sql函数并获取Instances(header + data)

我正在使用以下 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);
    }
}

【问题讨论】:

    标签: weka


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      我用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);
      

      结果“train”和“test”的header是一样的(兼容Weka机器学习)

      【讨论】:

        猜你喜欢
        • 2013-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-17
        • 2014-08-15
        • 1970-01-01
        相关资源
        最近更新 更多