使用没有整个weka库的weka决策树分类器?

时间:2013-01-24 17:46:35

标签: export libraries classification weka labeling

我为我的实例训练了一个分类器,现在想将它导出到一个Android应用程序,Weka库将无法使用。

仅仅在Android应用程序中添加Weka库是不合适的,因为它的大小(6.5 Mb)。

有没有其他方法可以使用我的分类器来评估和标记其他未标记的实例?是否有专门针对此设计的小型独立库?

当然,我最终可以编写自己的库来解释Weka的输出模型,但对我来说这似乎是合乎逻辑的,这种解决方案已经存在。 (虽然它以某种方式逃脱了我)

3 个答案:

答案 0 :(得分:2)

没有独立的库可以做你想要的。您可以删除不需要的Weka的所有部分并将其打包到库中。

在您的特定情况下,最简单的方法是使用Weka学习的决策树,并将其直接放入一系列if...else语句中的代码中。您甚至可以编写一个脚本来获取决策树的(图形)输出并为您编写该代码。

答案 1 :(得分:1)

在更加关注weka的输出模型之后,我注意到通过使用以Java类形式生成树的选项,我可以从weka库中单独使用它。

您可以删除生成的WekaWrapper并仅保留内部类,这是树的基本实现:

该课程看起来像这样:

public class WekaWrapper
  extends Classifier {

  /**
   * Returns only the toString() method.
   *
   * @return a string describing the classifier
   */
  public String globalInfo() {
    return toString();
  }

  /**
   * Returns the capabilities of this classifier.
   *
   * @return the capabilities
   */
  public Capabilities getCapabilities() {
    weka.core.Capabilities result = new weka.core.Capabilities(this);

    result.enable(weka.core.Capabilities.Capability.NOMINAL_ATTRIBUTES);
    result.enable(weka.core.Capabilities.Capability.NOMINAL_CLASS);
    result.enable(weka.core.Capabilities.Capability.MISSING_CLASS_VALUES);

    result.setMinimumNumberInstances(0);

    return result;
  }

  /**
   * only checks the data against its capabilities.
   *
   * @param i the training data
   */
  public void buildClassifier(Instances i) throws Exception {
    // can classifier handle the data?
    getCapabilities().testWithFail(i);
  }

  /**
   * Classifies the given instance.
   *
   * @param i the instance to classify
   * @return the classification result
   */
  public double classifyInstance(Instance i) throws Exception {
    Object[] s = new Object[i.numAttributes()];

    for (int j = 0; j < s.length; j++) {
      if (!i.isMissing(j)) {
        if (i.attribute(j).isNominal())
          s[j] = new String(i.stringValue(j));
        else if (i.attribute(j).isNumeric())
          s[j] = new Double(i.value(j));
      }
    }

    // set class value to missing
    s[i.classIndex()] = null;

    return WekaClassifier.classify(s);
  }

  /**
   * Returns the revision string.
   * 
   * @return        the revision
   */
  public String getRevision() {
    return RevisionUtils.extract("1.0");
  }

  /**
   * Returns only the classnames and what classifier it is based on.
   *
   * @return a short description
   */
  public String toString() {
    return "Auto-generated classifier wrapper, based on weka.classifiers.trees.Id3 (generated with Weka 3.6.9).\n" + this.getClass().getName() + "/WekaClassifier";
  }

  /**
   * Runs the classfier from commandline.
   *
   * @param args the commandline arguments
   */
  public static void main(String args[]) {
    runClassifier(new WekaWrapper(), args);
  }
}

class WekaClassifier {
  private static void checkMissing(Object[] i, int index) {
    if (i[index] == null)
      throw new IllegalArgumentException("Null values are not allowed!");
  }

  public static double classify(Object[] i) {
    return node0(i);
  }

  protected static double node0(Object[] i) {
    return 0.0; // unacc
  }
}

所以,是的,事实上你可以做到这一点非常容易。要记住的事情:

  • 对实例进行分类,调用classify(Object [])方法;
  • 返回值将是浮点值;
  • 返回值在注释中解释,紧接在return命令旁边;
  • 参数没有验证,所以要小心你输入它们的顺序(这部分由weka依赖部分完成);
  • 订单是arff文件中定义的订单。

答案 2 :(得分:0)

如果你想运行RandomForests,你可以使用我编写的一个小脚本,它将RandomForest分类器的WEKA&#-printTrees选项的输出转换为Java源代码。

http://pielot.org/2015/06/exporting-randomforest-models-to-java-source-code/

您需要包含在Android应用中的代码仅包含三个类:具有生成模型的类+两个类,以使分类有效。