OpenNLP - 命名实体识别


从给定文本中查找名称、人物、地点和其他实体的过程称为命名实体识别(NER)。在本章中,我们将讨论如何使用 OpenNLP 库通过 Java 程序进行 NER。

使用开放 NLP 的命名实体识别

为了执行各种 NER 任务,OpenNLP 使用不同的预定义模型,即 en-nerdate.bn、en-ner-location.bin、en-ner-organization.bin、en-ner-person.bin 和 en-ner-time。垃圾桶。所有这些文件都是预定义的模型,经过训练可以检测给定原始文本中的各个实体。

opennlp.tools.namefind包包含用于执行 NER 任务的类和接口要使用 OpenNLP 库执行 NER 任务,您需要 -

  • 使用TokenNameFinderModel类加载相应的模型。

  • 实例化NameFinder类。

  • 找到名字并打印出来。

以下是编写从给定原始文本中检测名称实体的程序时应遵循的步骤。

第 1 步:加载模型

句子检测模型由名为TokenNameFinderModel的类表示,该类属于opennlp.tools.namefind包。

加载 NER 模型 -

  • 创建模型的InputStream对象(实例化 FileInputStream 并将字符串格式的相应 NER 模型的路径传递给其构造函数)。

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

//Loading the NER-person model 
InputStream inputStreamNameFinder = new FileInputStream(".../en-nerperson.bin");       
TokenNameFinderModel model = new TokenNameFinderModel(inputStreamNameFinder);

步骤 2:实例化 NameFinderME 类

opennlp.tools.namefind包的 NameFinderME 类包含执行 NER 任务的方法此类使用最大熵模型来查找给定原始文本中的命名实体。

实例化此类并传递在上一步中创建的模型对象,如下所示 -

//Instantiating the NameFinderME class 
NameFinderME nameFinder = new NameFinderME(model);

第三步:找出句子中的名字

NameFinderME类的find ()方法用于检测传递给它的原始文本中的名称。该方法接受一个字符串变量作为参数。

通过将句子的字符串格式传递给此方法来调用此方法。

//Finding the names in the sentence 
Span nameSpans[] = nameFinder.find(sentence);

第四步:打印句子中名字的跨度

NameFinderME类的find ()方法返回 Span 类型的对象数组。opennlp.tools.util包中名为 Span 的类用于存储集合的起始结束整数。

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

//Printing the sentences and their spans of a sentence 
for (Span span : spans)         
System.out.println(paragraph.substring(span);

命名实体示例

以下程序读取给定的句子并识别其中人名的跨度。将此程序保存在名为NameFinderME_Example.java的文件中。

import java.io.FileInputStream; 
import java.io.InputStream;  

import opennlp.tools.namefind.NameFinderME; 
import opennlp.tools.namefind.TokenNameFinderModel; 
import opennlp.tools.util.Span;  

public class NameFinderME_Example { 
   public static void main(String args[]) throws Exception{ 
      /Loading the NER - Person model       InputStream inputStream = new 
         FileInputStream("C:/OpenNLP_models/en-ner-person.bin"); 
      TokenNameFinderModel model = new TokenNameFinderModel(inputStream);
      
      //Instantiating the NameFinder class 
      NameFinderME nameFinder = new NameFinderME(model); 
    
      //Getting the sentence in the form of String array  
      String [] sentence = new String[]{ 
         "Mike", 
         "and", 
         "Smith", 
         "are", 
         "good", 
         "friends" 
      }; 
       
      //Finding the names in the sentence 
      Span nameSpans[] = nameFinder.find(sentence); 
       
      //Printing the spans of the names in the sentence 
      for(Span s: nameSpans) 
         System.out.println(s.toString());    
   }    
}      

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

javac NameFinderME_Example.java 
java NameFinderME_Example

执行时,上述程序读取给定的字符串(原始文本),检测其中人员的姓名,并显示他们的位置(跨度),如下所示。

[0..1) person 
[2..3) person 

姓名及其职位

String 类的 substring() 方法接受开始结束偏移并返回相应的字符串。我们可以使用此方法将名称及其跨度(位置)一起打印,如以下代码块所示。

for(Span s: nameSpans)        
   System.out.println(s.toString()+"  "+tokens[s.getStart()]);

以下程序用于从给定的原始文本中检测名称并显示它们及其位置。将此程序保存在名为NameFinderSentences.java的文件中。

import java.io.FileInputStream; 
import java.io.InputStream;  

import opennlp.tools.namefind.NameFinderME; 
import opennlp.tools.namefind.TokenNameFinderModel; 
import opennlp.tools.tokenize.TokenizerME; 
import opennlp.tools.tokenize.TokenizerModel; 
import opennlp.tools.util.Span;  

public class NameFinderSentences {  
   public static void main(String args[]) throws Exception{        
      
      //Loading the tokenizer model 
      InputStream inputStreamTokenizer = new 
         FileInputStream("C:/OpenNLP_models/entoken.bin");
      TokenizerModel tokenModel = new TokenizerModel(inputStreamTokenizer); 
       
      //Instantiating the TokenizerME class 
      TokenizerME tokenizer = new TokenizerME(tokenModel); 
       
      //Tokenizing the sentence in to a string array 
      String sentence = "Mike is senior programming 
      manager and Rama is a clerk both are working at 
      Tutorialspoint"; 
      String tokens[] = tokenizer.tokenize(sentence); 
       
      //Loading the NER-person model 
      InputStream inputStreamNameFinder = new 
         FileInputStream("C:/OpenNLP_models/enner-person.bin");       
      TokenNameFinderModel model = new TokenNameFinderModel(inputStreamNameFinder);
      
      //Instantiating the NameFinderME class 
      NameFinderME nameFinder = new NameFinderME(model);       
      
      //Finding the names in the sentence 
      Span nameSpans[] = nameFinder.find(tokens);        
      
      //Printing the names and their spans in a sentence 
      for(Span s: nameSpans)        
         System.out.println(s.toString()+"  "+tokens[s.getStart()]);      
   }    
} 

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

javac NameFinderSentences.java 
java NameFinderSentences 

执行时,上述程序读取给定的字符串(原始文本),检测其中人员的姓名,并显示他们的位置(跨度),如下所示。

[0..1) person  Mike

查找位置名称

通过加载各种模型,您可以检测各种命名实体。以下是一个 Java 程序,它加载en-ner-location.bin模型并检测给定句子中的位置名称。将此程序保存在名为LocationFinder.java 的文件中。

import java.io.FileInputStream; 
import java.io.InputStream;  

import opennlp.tools.namefind.NameFinderME; 
import opennlp.tools.namefind.TokenNameFinderModel; 
import opennlp.tools.tokenize.TokenizerME; 
import opennlp.tools.tokenize.TokenizerModel; 
import opennlp.tools.util.Span;  

public class LocationFinder { 
   public static void main(String args[]) throws Exception{
 
      InputStream inputStreamTokenizer = new 
         FileInputStream("C:/OpenNLP_models/entoken.bin"); 
      TokenizerModel tokenModel = new TokenizerModel(inputStreamTokenizer); 
       
      //String paragraph = "Mike and Smith are classmates"; 
      String paragraph = "Tutorialspoint is located in Hyderabad"; 
        
      //Instantiating the TokenizerME class 
      TokenizerME tokenizer = new TokenizerME(tokenModel); 
      String tokens[] = tokenizer.tokenize(paragraph); 
       
      //Loading the NER-location moodel 
      InputStream inputStreamNameFinder = new 
         FileInputStream("C:/OpenNLP_models/en- ner-location.bin");       
      TokenNameFinderModel model = new TokenNameFinderModel(inputStreamNameFinder); 
        
      //Instantiating the NameFinderME class 
      NameFinderME nameFinder = new NameFinderME(model);      
        
      //Finding the names of a location 
      Span nameSpans[] = nameFinder.find(tokens);        
      //Printing the spans of the locations in the sentence 
      for(Span s: nameSpans)        
         System.out.println(s.toString()+"  "+tokens[s.getStart()]); 
   }    
}   

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

javac LocationFinder.java 
java LocationFinder

执行时,上述程序读取给定的字符串(原始文本),检测其中人员的姓名,并显示他们的位置(跨度),如下所示。

[4..5) location  Hyderabad

名称查找器概率

NameFinderME类的probs ()方法用于获取最后解码序列的概率。

double[] probs = nameFinder.probs(); 

以下是打印概率的程序。将此程序保存在名为TokenizerMEProbs.java的文件中。

import java.io.FileInputStream; 
import java.io.InputStream; 
import opennlp.tools.tokenize.TokenizerME; 
import opennlp.tools.tokenize.TokenizerModel; 
import opennlp.tools.util.Span; 
public class TokenizerMEProbs { 
   public static void main(String args[]) throws Exception{     
      String sent = "Hello John how are you welcome to Tutorialspoint"; 
       
      //Loading the Tokenizer model 
      InputStream inputStream = new 
         FileInputStream("C:/OpenNLP_models/en-token.bin"); 
      TokenizerModel tokenModel = new TokenizerModel(inputStream); 
       
      //Instantiating the TokenizerME class 
      TokenizerME tokenizer = new TokenizerME(tokenModel); 
       
      //Retrieving the positions of the tokens 
      Span tokens[] = tokenizer.tokenizePos(sent); 
       
      //Getting the probabilities of the recent calls to tokenizePos() method 
      double[] probs = tokenizer.getTokenProbabilities(); 
       
      //Printing the spans of tokens 
      for( Span token : tokens) 
         System.out.println(token +" 
            "+sent.substring(token.getStart(), token.getEnd()));      
         System.out.println("  "); 
      for(int i = 0; i<probs.length; i++) 
         System.out.println(probs[i]);          
   } 
}

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

javac TokenizerMEProbs.java 
java TokenizerMEProbs

执行时,上面的程序读取给定的字符串,标记句子,然后打印它们。此外,它还返回最后解码序列的概率,如下所示。

[0..5) Hello 
[6..10) John 
[11..14) how 
[15..18) are 
[19..22) you 
[23..30) welcome 
[31..33) to 
[34..48) Tutorialspoint 
   
1.0 
1.0 
1.0 
1.0 
1.0 
1.0 
1.0 
1.0