【问题标题】:How to use OpenNLP with Java?如何在 Java 中使用 OpenNLP?
【发布时间】:2011-08-15 17:19:23
【问题描述】:

我想对一个英文句子进行 POSTtag 并进行一些处理。我想使用openNLP。我已经安装了

当我执行命令时

I:\Workshop\Programming\nlp\opennlp-tools-1.5.0-bin\opennlp-tools-1.5.0>java -jar opennlp-tools-1.5.0.jar POSTagger models\en-pos-maxent.bin < Text.txt

它给出输出POSTagging Text.txt中的输入

    Loading POS Tagger model ... done (4.009s)
My_PRP$ name_NN is_VBZ Shabab_NNP i_FW am_VBP 22_CD years_NNS old._.


Average: 66.7 sent/s
Total: 1 sent
Runtime: 0.015s

我希望它安装正确?

现在我如何从 Java 应用程序内部进行 POSTtagging?我已将 openNLPtools、jwnl、maxent jar 添加到项目中,但如何调用 POSTtagging?

【问题讨论】:

    标签: java nlp pos-tagger opennlp


    【解决方案1】:

    上面的答案确实提供了一种使用 OpenNLP 现有模型的方法,但如果您需要训练自己的模型,也许下面的方法会有所帮助:

    这里有一个详细的教程和完整的代码:

    https://dataturks.com/blog/opennlp-pos-tagger-training-java-example.php

    根据您的域,您可以自动或手动构建数据集。手动构建这样的数据集真的很痛苦,POS tagger 之类的工具可以帮助简化这个过程。

    训练数据格式

    训练数据作为文本文件传递,其中每一行是一个数据项。该行中的每个单词都应以“word_LABEL”之类的格式进行标记,单词和标签名称之间用下划线“_”分隔。

    anki_Brand overdrive_Brand
    just_ModelName dance_ModelName 2018_ModelName
    aoc_Brand 27"_ScreenSize monitor_Category
    horizon_ModelName zero_ModelName dawn_ModelName
    cm_Unknown 700_Unknown modem_Category
    computer_Category
    

    训练模型

    这里重要的类是 POSModel,它保存了实际的模型。我们使用 POSTaggerME 类进行模型构建。下面是从训练数据文件构建模型的代码

    public POSModel train(String filepath) {
      POSModel model = null;
      TrainingParameters parameters = TrainingParameters.defaultParams();
      parameters.put(TrainingParameters.ITERATIONS_PARAM, "100");
    
      try {
        try (InputStream dataIn = new FileInputStream(filepath)) {
            ObjectStream<String> lineStream = new PlainTextByLineStream(new InputStreamFactory() {
                @Override
                public InputStream createInputStream() throws IOException {
                    return dataIn;
                }
            }, StandardCharsets.UTF_8);
            ObjectStream<POSSample> sampleStream = new WordTagSampleStream(lineStream);
    
            model = POSTaggerME.train("en", sampleStream, parameters, new POSTaggerFactory());
            return model;
        }
      }
      catch (Exception e) {
        e.printStackTrace();
      }
      return null;
    
    }
    

    使用模型做标记。

    最后,我们可以看到如何使用模型来标记看不见的查询:

        public void doTagging(POSModel model, String input) {
        input = input.trim();
        POSTaggerME tagger = new POSTaggerME(model);
        Sequence[] sequences = tagger.topKSequences(input.split(" "));
        for (Sequence s : sequences) {
            List<String> tags = s.getOutcomes();
            System.out.println(Arrays.asList(input.split(" ")) +" =>" + tags);
        }
    }
    

    【讨论】:

      【解决方案2】:

      这是我拼凑起来的一些(旧)示例代码,后面还有现代化的代码:

      package opennlp;
      
      import opennlp.tools.cmdline.PerformanceMonitor;
      import opennlp.tools.cmdline.postag.POSModelLoader;
      import opennlp.tools.postag.POSModel;
      import opennlp.tools.postag.POSSample;
      import opennlp.tools.postag.POSTaggerME;
      import opennlp.tools.tokenize.WhitespaceTokenizer;
      import opennlp.tools.util.ObjectStream;
      import opennlp.tools.util.PlainTextByLineStream;
      
      import java.io.File;
      import java.io.IOException;
      import java.io.StringReader;
      
      public class OpenNlpTest {
      public static void main(String[] args) throws IOException {
          POSModel model = new POSModelLoader().load(new File("en-pos-maxent.bin"));
          PerformanceMonitor perfMon = new PerformanceMonitor(System.err, "sent");
          POSTaggerME tagger = new POSTaggerME(model);
      
          String input = "Can anyone help me dig through OpenNLP's horrible documentation?";
          ObjectStream<String> lineStream =
                  new PlainTextByLineStream(new StringReader(input));
      
          perfMon.start();
          String line;
          while ((line = lineStream.read()) != null) {
      
              String whitespaceTokenizerLine[] = WhitespaceTokenizer.INSTANCE.tokenize(line);
              String[] tags = tagger.tag(whitespaceTokenizerLine);
      
              POSSample sample = new POSSample(whitespaceTokenizerLine, tags);
              System.out.println(sample.toString());
      
              perfMon.incrementCounter();
          }
          perfMon.stopAndPrintFinalResult();
      }
      }
      

      输出是:

      Loading POS Tagger model ... done (2.045s)
      Can_MD anyone_NN help_VB me_PRP dig_VB through_IN OpenNLP's_NNP horrible_JJ documentation?_NN
      
      Average: 76.9 sent/s 
      Total: 1 sent
      Runtime: 0.013s
      

      这基本上是在作为 OpenNLP 一部分包含的 POSTaggerTool 类中工作的。 sample.getTags() 是一个 String 数组,它本身具有标签类型。

      这需要直接访问训练数据的文件,这真的很糟糕。

      为此更新的代码库略有不同(并且可能更有用。)

      首先,一个 Maven POM:

      <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
          <modelVersion>4.0.0</modelVersion>
      
          <groupId>org.javachannel</groupId>
          <artifactId>opennlp-example</artifactId>
          <version>1.0-SNAPSHOT</version>
          <dependencies>
              <dependency>
                  <groupId>org.apache.opennlp</groupId>
                  <artifactId>opennlp-tools</artifactId>
                  <version>1.6.0</version>
              </dependency>
              <dependency>
                  <groupId>org.testng</groupId>
                  <artifactId>testng</artifactId>
                  <version>[6.8.21,)</version>
                  <scope>test</scope>
              </dependency>
          </dependencies>
          <build>
              <plugins>
                  <plugin>
                      <groupId>org.apache.maven.plugins</groupId>
                      <artifactId>maven-compiler-plugin</artifactId>
                      <version>3.1</version>
                      <configuration>
                          <source>1.8</source>
                          <target>1.8</target>
                      </configuration>
                  </plugin>
              </plugins>
          </build>
      </project>
      

      这是作为测试编写的代码,因此位于./src/test/java/org/javachannel/opennlp/example

      package org.javachannel.opennlp.example;
      
      import opennlp.tools.cmdline.PerformanceMonitor;
      import opennlp.tools.postag.POSModel;
      import opennlp.tools.postag.POSSample;
      import opennlp.tools.postag.POSTaggerME;
      import opennlp.tools.tokenize.WhitespaceTokenizer;
      import org.testng.annotations.DataProvider;
      import org.testng.annotations.Test;
      
      import java.io.File;
      import java.io.FileOutputStream;
      import java.io.IOException;
      import java.net.URL;
      import java.nio.channels.Channels;
      import java.nio.channels.ReadableByteChannel;
      import java.util.stream.Stream;
      
      public class POSTest {
          private void download(String url, File destination) throws IOException {
              URL website = new URL(url);
              ReadableByteChannel rbc = Channels.newChannel(website.openStream());
              FileOutputStream fos = new FileOutputStream(destination);
              fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
          }
      
          @DataProvider
          Object[][] getCorpusData() {
              return new Object[][][]{{{
                      "Can anyone help me dig through OpenNLP's horrible documentation?"
              }}};
          }
      
          @Test(dataProvider = "getCorpusData")
          public void showPOS(Object[] input) throws IOException {
              File modelFile = new File("en-pos-maxent.bin");
              if (!modelFile.exists()) {
                  System.out.println("Downloading model.");
                  download("http://opennlp.sourceforge.net/models-1.5/en-pos-maxent.bin", modelFile);
              }
              POSModel model = new POSModel(modelFile);
              PerformanceMonitor perfMon = new PerformanceMonitor(System.err, "sent");
              POSTaggerME tagger = new POSTaggerME(model);
      
              perfMon.start();
              Stream.of(input).map(line -> {
                  String whitespaceTokenizerLine[] = WhitespaceTokenizer.INSTANCE.tokenize(line.toString());
                  String[] tags = tagger.tag(whitespaceTokenizerLine);
      
                  POSSample sample = new POSSample(whitespaceTokenizerLine, tags);
      
                  perfMon.incrementCounter();
                  return sample.toString();
              }).forEach(System.out::println);
              perfMon.stopAndPrintFinalResult();
          }
      }
      

      这段代码实际上并没有测试任何东西——它是一个冒烟测试,如果有的话——但它应该作为一个起点。另一个(可能)好的事情是,如果您还没有下载模型,它会为您下载模型。

      【讨论】:

      • 非常非常非常非常感谢。我终于走上了正轨?你能告诉我在哪里可以找到 - NN MD、VB...以及所有这些标签的含义吗?
      • 我不知道!我现在正在努力,因为我刚刚意识到——多亏了你的问题——OpenNLP 对我自己的任务有多么有用。 :)
      • 如何从这个输出中排序名词和形容词?
      • 您应该迁移您的示例代码,因为模型不应再通过POSModelLoader 加载(请参阅Javadoc)。相反,您可以使用构造函数POSModel(InputStream in) 通过引用实际模型文件的InputStream 加载模型文件。此外,POSModelLoader 类仅存在于 OpenNLP 的早期版本(版本
      • 在 1.6.0 中,最初编写的代码实际上运行正常,包括使用构造函数 - 它甚至没有标记为已弃用(尽管 PlainTextByLineStream 已弃用。)您使用的是 1.6.0快照?无论如何,我将代码更新为更符合 1.6。谢谢!
      【解决方案3】:

      网址http://bulba.sdsu.edu/jeanette/thesis/PennTags.html 不再起作用。我在第 14 张幻灯片上找到了以下内容 http://www.slideshare.net/gagan1667/opennlp-demo

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-29
        • 2015-01-13
        • 1970-01-01
        • 1970-01-01
        • 2014-08-12
        • 2016-10-16
        • 1970-01-01
        • 2023-03-13
        相关资源
        最近更新 更多