【问题标题】:Load Naïve Bayes model in java code using weka jar使用 weka jar 在 java 代码中加载朴素贝叶斯模型
【发布时间】:2017-06-08 20:56:34
【问题描述】:

我使用 weka 并通过使用 weka GUI 制作了朴素贝叶斯分类器。然后我按照tutorial 保存了这个模型。现在我想通过 Java 代码加载这个模型,但是我找不到任何方法来使用 weka 加载保存的模型。

这是我的要求,我必须单独制作模型,然后在单独的程序中使用它。

如果有人能在这方面指导我,我将不胜感激。

【问题讨论】:

    标签: java weka naivebayes


    【解决方案1】:

    您可以使用以下命令在 java 中轻松加载保存的模型:

    Classifier myCls = (Classifier) weka.core.SerializationHelper.read(pathToModel);
    

    为了完整的 Java 工作流程,我在 SO 文档中写了以下文章,现在复制到这里:

    Weka 中的文本分类

    使用 LibLinear 进行文本分类

    • 从 .arff 文件创建训练实例

      private static Instances getDataFromFile(String path) throws Exception{
      
          DataSource source = new DataSource(path);
          Instances data = source.getDataSet();
      
          if (data.classIndex() == -1){
              data.setClassIndex(data.numAttributes()-1);
              //last attribute as class index
          }
      
          return data;    
      }
      

    Instances trainingData = getDataFromFile(pathToArffFile);
    
    • 使用 StringToWordVector 将字符串属性转换为数字表示:

      • 此过滤器的重要功能:

        1. tf-idf 表示
        2. 词干
        3. 小写单词
        4. 停用词
        5. n-gram 表示*

       

      StringToWordVector() filter = new StringToWordVector();    
      filter.setWordsToKeep(1000000);
      if(useIdf){
          filter.setIDFTransform(true);
      }
      filter.setTFTransform(true);
      filter.setLowerCaseTokens(true);
      filter.setOutputWordCounts(true);
      filter.setMinTermFreq(minTermFreq);
      filter.setNormalizeDocLength(new SelectedTag(StringToWordVector.FILTER_NORMALIZE_ALL,StringToWordVector.TAGS_FILTER));
      NGramTokenizer t = new NGramTokenizer();
      t.setNGramMaxSize(maxGrams);
      t.setNGramMinSize(minGrams);    
      filter.setTokenizer(t);     
      WordsFromFile stopwords = new WordsFromFile();
      stopwords.setStopwords(new File("data/stopwords/stopwords.txt"));
      filter.setStopwordsHandler(stopwords);
      if (useStemmer){
          Stemmer s = new /*Iterated*/LovinsStemmer();
          filter.setStemmer(s);
      }
      filter.setInputFormat(trainingData);
      
      • 将过滤器应用于训练数据:trainingData = Filter.useFilter(trainingData, filter);

      • 创建 LibLinear 分类器

        1. 下面的 SVMType 0 对应于 L2 正则化逻辑回归
        2. 设置setProbabilityEstimates(true) 打印输出概率

          Classifier cls = null; LibLINEAR liblinear = new LibLINEAR(); liblinear.setSVMType(new SelectedTag(0, LibLINEAR.TAGS_SVMTYPE)); liblinear.setProbabilityEstimates(true); // liblinear.setBias(1); // default value cls = liblinear; cls.buildClassifier(trainingData);

      • 保存模型

        System.out.println("Saving the model..."); ObjectOutputStream oos; oos = new ObjectOutputStream(new FileOutputStream(path+"mymodel.model")); oos.writeObject(cls); oos.flush(); oos.close();

      • .arff 文件创建测试实例

        实例 trainingData = getDataFromFile(pathToArffFile);

      • 加载分类器

      Classifier myCls = (Classifier) weka.core.SerializationHelper.read(path+"mymodel.model");

      • 使用与上面相同的 StringToWordVector 过滤器或为 testingData 创建一个新过滤器,但请记住将 trainingData 用于此命令:filter.setInputFormat(trainingData); 这将使训练和测试实例兼容。 或者你可以使用InputMappedClassifier

      • 将过滤器应用于 testingData:testingData = Filter.useFilter(testingData, filter);

      • 分类!

      1.获取测试集中每个实例的类值

      for (int j = 0; j res 是一个双精度值,对应于.arff 文件中定义的名义类。要获得名义类使用:testintData.classAttribute().value((int)res)


    2.获取每个实例的概率分布

     for (int j = 0; j < testingData.numInstances(); j++) {
        double[] dist = first.distributionForInstance(testInstances.get(j));
     }
    

    dist 是一个双精度数组,其中包含.arff 文件中定义的每个类的概率

    注意。分类器应支持概率分布并通过以下方式启用它们:myClassifier.setProbabilityEstimates(true);

    【讨论】:

    • 当我在一个简单的 java 项目中使用该代码时,它运行良好。当我转移到 Java EE 并使用此代码获取模型对象时,它给了我异常,因为无法将 java.util.ArrayList 的实例分配给实例中类型为 weka.core.FastVector 的字段 weka.core.Instances.m_Attributes weka.core.Instances 奇怪的是,相同的代码在简单的 Java 项目中工作,但在 Java EE 中出现问题。
    • 确实很奇怪。你用的是同一个版本的Weka吗?因为据我所知 FastVector 类已被弃用。也许这是导致问题的原因。
    • 以前我使用的是 weka.jar 但它没有 Maven 但 Maven 存在于 weka-stable 3.6.6 。我正在使用它并得到了这个例外。为了避免库混淆,我还通过类路径使用了以前的 lib Weka.jar。在那我得到了 ClassNotFound 异常。所以在 JavaEE 中,无论使用哪个库都会出现异常。
    • 我认为是 3.6.6 weka 版本导致了异常。 ClassNotFound 异常是由于 jar 未正确链接而引起的。尝试从这里stackoverflow.com/questions/7672933/… 遵循指令来链接您的 jar。顺便问一下 weka.jar 是什么版本?
    • 我从 Weka 网站下载了它。没有提到版本的名称。
    猜你喜欢
    • 2013-09-09
    • 2012-04-09
    • 2019-11-26
    • 2020-06-28
    • 2016-02-05
    • 2013-04-18
    • 2019-02-21
    • 2016-08-16
    • 2019-03-27
    相关资源
    最近更新 更多