OpenNLP - 命名實體識別



從給定文字中查詢姓名、人員、地點和其他實體的過程稱為命名實體識別(NER)。在本章中,我們將討論如何使用 OpenNLP 庫透過 Java 程式執行 NER。

使用 OpenNLP 進行命名實體識別

為了執行各種 NER 任務,OpenNLP 使用不同的預定義模型,例如 en-ner-date.bin、en-ner-location.bin、en-ner-organization.bin、en-ner-person.bin 和 en-ner-time.bin。所有這些檔案都是預定義的模型,經過訓練可以檢測給定原始文字中的相應實體。

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);

步驟 3:查詢句子中的名稱

NameFinderME類的find()方法用於檢測傳遞給它的原始文字中的名稱。此方法接受一個字串變數作為引數。

透過將句子的字串格式傳遞給此方法來呼叫此方法。

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

步驟 4:列印句子中名稱的跨度

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);

NER 示例

以下程式讀取給定的句子並識別其中人員名稱的跨度。將此程式儲存在名為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

NameFinder 機率

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
廣告

© . All rights reserved.