OpenNLP - 句子分块

句子分块是指将句子分解/划分为单词部分,例如单词组和动词组。

使用 OpenNLP 对句子进行分块

为了检测句子,OpenNLP 使用一个模型,即名为 en-chunker.bin 的文件。这是一个预定义的模型,经过训练可以对给定的原始文本中的句子进行分块。

opennlp.tools.chunker 包包含用于查找非递归句法注释(例如名词短语块)的类和接口。

您可以使用 ChunkerME 类的方法 chunk() 对句子进行分块。此方法接受句子的标记和 POS 标签作为参数。因此,在开始分块过程之前,首先需要对句子进行标记并生成其部分 POS 标签。

要使用 OpenNLP 库对句子进行分块,您需要 −

  • 对句子进行标记。

  • 为其生成 POS 标签。

  • 使用 ChunkerModel 类加载 en-chunker.bin 模型

  • 实例化 ChunkerME 类。

  • 使用此类的 chunk() 方法对句子进行分块。

以下是编写程序从给定的原始文本中对句子进行分块时要遵循的步骤。

步骤 1:对句子

使用 whitespaceTokenizer 类的 tokenize() 方法对句子进行标记,如以下代码块所示。

//对句子进行标记
String sentence = "Hi welcome to Tutorialspoint";
WhitespaceTokenizer whitespaceTokenizer= WhitespaceTokenizer.INSTANCE;
String[] tokens = whitespaceTokenizer.tokenize(sentence);

步骤 2:生成 POS 标签

使用 POSTaggerME 类的 tag() 方法生成句子的 POS 标签,如以下代码块所示。

//生成 POS 标签
File file = new File("C:/OpenNLP_models/en-pos-maxent.bin");
POSModel model = new POSModelLoader().load(file);
//构造标记器
POSTaggerME tagger = new POSTaggerME(model);
//从标记生成标签
String[] tags = tagger.tag(tokens);

步骤 3:加载模型

用于对句子进行分块的模型由名为 ChunkerModel 的类表示,该类属于 opennlp.tools.chunker 包。

要加载句子检测模型 −

  • 创建模型的InputStream对象(实例化FileInputStream并将模型的路径以String格式传递给其构造函数)。

  • 实例化ChunkerModel类,并将模型的InputStream(对象)作为参数传递给其构造函数,如下面的代码块所示−

//加载chunker模型
InputStream inputStream = new FileInputStream("C:/OpenNLP_models/en-chunker.bin");
ChunkerModel chunkerModel = new ChunkerModel(inputStream);

步骤 4:实例化 chunkerME 类

opennlp.tools.chunkerchunkerME 类包含对句子进行分块的方法。这是一个基于最大熵的分块器。

实例化此类并传递上一步中创建的模型对象。

//实例化 ChunkerME 类
ChunkerME chunkerME = new ChunkerME(chunkerModel);

步骤 5:对句子进行分块

ChunkerME 类的 chunk() 方法用于对传递给它的原始文本中的句子进行分块。此方法接受两个表示标记和标签的字符串数组作为参数。

通过将前面步骤中创建的标记数组和标签数组作为参数传递来调用此方法。

//生成块
String result[] = chunkerME.chunk(tokens, tags);

示例

以下是将给定原始文本中的句子分块的程序。将此程序保存在名为 ChunkerExample.java 的文件中。

import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream;  

import opennlp.tools.chunker.ChunkerME; 
import opennlp.tools.chunker.ChunkerModel; 
import opennlp.tools.cmdline.postag.POSModelLoader; 
import opennlp.tools.postag.POSModel; 
import opennlp.tools.postag.POSTaggerME; 
import opennlp.tools.tokenize.WhitespaceTokenizer;  

public class ChunkerExample{ 
   
   public static void main(String args[]) throws IOException { 
        //对句子进行标记
        String sentence = "Hi welcome to Tutorialspoint";
        WhitespaceTokenizer whitespaceTokenizer= WhitespaceTokenizer.INSTANCE;
        String[] tokens = whitespaceTokenizer.tokenize(sentence);
        
        //生成 POS 标签
        //加载词性模型
        File file = new File("C:/OpenNLP_models/en-pos-maxent.bin");
        POSModel model = new POSModelLoader().load(file);
        
        //构造标记器
        POSTaggerME tagger = new POSTaggerME(model);
        
        //从标记生成标签
        String[] tags = tagger.tag(tokens);
        
        //加载分块器模型
        InputStream inputStream = new
        FileInputStream("C:/OpenNLP_models/en-chunker.bin");
        ChunkerModel chunkerModel = new ChunkerModel(inputStream);
        
        //实例化 ChunkerME 类
        ChunkerME chunkerME = new ChunkerME(chunkerModel);
        
        //生成块
      	String result[] = chunkerME.chunk(tokens, tags); 
  
      	for (String s : result) 
         System.out.println(s);         
   }    
}      

使用以下命令从命令提示符编译并执行已保存的 Java 文件 −

javac ChunkerExample.java
java ChunkerExample

执行时,上述程序读取给定的字符串并将其中的句子分块,然后显示它们,如下所示。

Loading POS Tagger model ... done (1.040s) 
B-NP 
I-NP 
B-VP 
I-VP

检测标记的位置

我们还可以使用 ChunkerME 类的 chunkAsSpans() 方法检测块的位置或跨度。此方法返回 Span 类型的对象数组。opennlp.tools.util 包中名为 Span 的类用于存储集合的 startend 整数。

您可以将 chunkAsSpans() 方法返回的跨度存储在 Span 数组中并打印它们,如下面的代码块所示。

//Generating the tagged chunk spans 
Span[] span = chunkerME.chunkAsSpans(tokens, tags); 
       
for (Span s : span) 
   System.out.println(s.toString()); 

示例

以下是检测给定原始文本中的句子的程序。将此程序保存在名为 ChunkerSpansEample.java 的文件中。

import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream;  

import opennlp.tools.chunker.ChunkerME; 
import opennlp.tools.chunker.ChunkerModel; 
import opennlp.tools.cmdline.postag.POSModelLoader; 
import opennlp.tools.postag.POSModel; 
import opennlp.tools.postag.POSTaggerME; 
import opennlp.tools.tokenize.WhitespaceTokenizer; 
import opennlp.tools.util.Span;  

public class ChunkerSpansEample{ 
   
   public static void main(String args[]) throws IOException { 
        //加载词性模型
        File file = new File("C:/OpenNLP_models/en-pos-maxent.bin");
        POSModel model = new POSModelLoader().load(file);
        
        //构造标记器
        POSTaggerME tagger = new POSTaggerME(model);
        
        //对句子进行标记
        String sentence = "Hi welcome to Tutorialspoint";
        WhitespaceTokenizer whitespaceTokenizer= WhitespaceTokenizer.INSTANCE;
        String[] tokens = whitespaceTokenizer.tokenize(sentence);
        
        //从标记生成标签
        String[] tags = tagger.tag(tokens);
        
        //加载分块器模型
        InputStream inputStream = new
        FileInputStream("C:/OpenNLP_models/en-chunker.bin");
        ChunkerModel chunkerModel = new ChunkerModel(inputStream);
        ChunkerME chunkerME = new ChunkerME(chunkerModel);
        
        //生成带标签的块跨度
      	Span[] span = chunkerME.chunkAsSpans(tokens, tags); 
       
      	for (Span s : span) 
         System.out.println(s.toString());  
   }    
}

使用以下命令从命令提示符编译并执行保存的 Java 文件 −

javac ChunkerSpansEample.java
java ChunkerSpansEample

执行时,上述程序读取给定的字符串及其中的块的跨度,并显示以下输出 −

正在加载 POS 标记器模型... 完成(1.059 秒)
[0..2) NP
[2..4) VP

Chunker 概率检测

ChunkerME 类的 probs() 方法返回最后解码序列的概率。

//获取最后解码的序列
double[] probs = chunkerME.probs();

以下程序用于打印 chunker 最后解码的序列的概率。将此程序保存在名为 ChunkerProbsExample.java 的文件中。

import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import opennlp.tools.chunker.ChunkerME; 
import opennlp.tools.chunker.ChunkerModel; 
import opennlp.tools.cmdline.postag.POSModelLoader; 
import opennlp.tools.postag.POSModel;
import opennlp.tools.postag.POSTaggerME; 
import opennlp.tools.tokenize.WhitespaceTokenizer;  

public class ChunkerProbsExample{ 
   
   public static void main(String args[]) throws IOException { 
        //加载词性模型
        File file = new File("C:/OpenNLP_models/en-pos-maxent.bin");
        POSModel model = new POSModelLoader().load(file);
        
        //构造标记器
        POSTaggerME tagger = new POSTaggerME(model);
        
        //对句子进行标记
        String sentence = "Hi welcome to Tutorialspoint";
        WhitespaceTokenizer whitespaceTokenizer= WhitespaceTokenizer.INSTANCE;
        String[] tokens = whitespaceTokenizer.tokenize(sentence);
        
        //从标记生成标签
        String[] tags = tagger.tag(tokens);
        
        //加载分块器模型
        InputStream inputStream = new
        FileInputStream("C:/OpenNLP_models/en-chunker.bin");
        ChunkerModel cModel = new ChunkerModel(inputStream);
        ChunkerME chunkerME = new ChunkerME(cModel);
        
        //生成块标签
        chunkerME.chunk(tokens, tags);
        
        //获取最后解码序列的概率 
      	double[] probs = chunkerME.probs(); 
      	for(int i = 0; i<probs.length; i++) 
         System.out.println(probs[i]);       
   }    
}   

使用以下命令从命令提示符编译并执行已保存的 Java 文件 −

javac ChunkerProbsExample.java
java ChunkerProbsExample

执行时,上述程序读取给定的字符串,对其进行分块,并打印最后解码序列的概率。

0.9592746040797778 
0.6883933131241501 
0.8830563473996004 
0.8951150529746051