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



我已经为我的实例训练了一个分类器,现在想将其导出到 Android 应用程序,其中 Weka 库将不可用。

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

还有其他方法可以使用分类器来评估和标记其他未标记的实例吗?是否有任何较小的独立图书馆专门为此设计?

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

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

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

在更加关注 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 文件中定义的顺序。
如果你想运行RandomForest,

你可以使用我写的一个小脚本,将RandomForest分类器的WEKA的-printTrees选项的输出转换为Java源代码。

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

您需要包含在 Android 应用中的代码将仅包含三个类:具有生成模型的类 + 两个用于进行分类的类。

相关内容

  • 没有找到相关文章

最新更新