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