上一节介绍了使用OpenNLP训练命名实体识别模型的方法,并将模型写到磁盘上形成二进制bin文件,这一节就是将模型从磁盘上载入,然后进行命名实体识别。依然是先上代码:

[java] view plain copy  
  1. import java.io.File;
  2. import java.util.HashMap;
  3. import java.util.IdentityHashMap;
  4. import java.util.Map;
  5. import java.util.Map.Entry;
  6. import opennlp.tools.cmdline.namefind.TokenNameFinderModelLoader;
  7. import opennlp.tools.namefind.NameFinderME;
  8. import opennlp.tools.tokenize.SimpleTokenizer;
  9. import opennlp.tools.tokenize.Tokenizer;
  10. import opennlp.tools.util.Span;
  11. public class NameEntityFindTester {
  12. // 默认参数
  13. private double probThreshold = 0.6;
  14. private String modelPath;
  15. private String testFileDirPath;
  16. public NameEntityFindTester() {
  17. super();
  18. // TODO Auto-generated constructor stub
  19. }
  20. public NameEntityFindTester(String modelPath, String testFileDirPath) {
  21. super();
  22. this.modelPath = modelPath;
  23. this.testFileDirPath = testFileDirPath;
  24. }
  25. public NameEntityFindTester(double probThreshold, String modelPath,
  26. String testFileDirPath) {
  27. super();
  28. this.probThreshold = probThreshold;
  29. this.modelPath = modelPath;
  30. this.testFileDirPath = testFileDirPath;
  31. }
  32. /**
  33. * 生成NameFinder
  34. *
  35. * @return
  36. */
  37. public NameFinderME prodNameFinder() {
  38. NameFinderME finder = new NameFinderME(
  39. new TokenNameFinderModelLoader().load(new File(modelPath)));
  40. return finder;
  41. }
  42. /**
  43. * 计算基本命名实体概率
  44. *
  45. * @param finder
  46. *            命名实体识别模型
  47. * @return
  48. * @throws Exception
  49. */
  50. public Map<String, String> cptBasicNameProb(NameFinderME finder)
  51. throws Exception {
  52. Map<String, String> basicNameProbResMap = new IdentityHashMap<String, String>();
  53. String testContent = NameEntityTextFactory.loadFileTextDir(this
  54. .getTestFileDirPath());
  55. // TODO 大文本情况下,消耗内存大,需要改写成分批处理模式(把一个大文件分成多个小文件再批量处理)
  56. Tokenizer tokenizer = SimpleTokenizer.INSTANCE;
  57. // 待测词,测试结果,概率
  58. String[] tokens = tokenizer.tokenize(testContent);
  59. Span[] names = finder.find(tokens);
  60. double[] nameSpanProbs = finder.probs(names);
  61. System.out.println("tokens size: " + tokens.length);
  62. System.out.println("names size: " + names.length);
  63. System.out.println("name_span_probs size: " + nameSpanProbs.length);
  64. for (int i = 0; i < names.length; i++) {
  65. String testToken = "";
  66. for (int j = names[i].getStart(); j <= names[i].getEnd() - 1; j++) {
  67. testToken += tokens[j];
  68. }
  69. String testRes = names[i].getType() + ":"
  70. + Double.toString(nameSpanProbs[i]);
  71. // TODO delete print
  72. System.out.println("find name: \"" + testToken + "\" has res: "
  73. + testRes);
  74. basicNameProbResMap.put(testToken, testRes);
  75. }
  76. return basicNameProbResMap;
  77. }
  78. /**
  79. * 过滤除去概率值过低的识别结果
  80. *
  81. * @param basicNameProbResMap
  82. * @return
  83. */
  84. public Map<String, String> filterNameProbRes(
  85. Map<String, String> basicNameProbResMap) {
  86. Map<String, String> filttedNameProbResMap = new HashMap<String, String>();
  87. for (Entry<String, String> entry : basicNameProbResMap.entrySet()) {
  88. String token = entry.getKey();
  89. String res = basicNameProbResMap.get(token);
  90. if (Double.parseDouble(res.split(":")[1]) >= this
  91. .getProbThreshold()) {
  92. filttedNameProbResMap.put(token, res);
  93. }
  94. }
  95. return filttedNameProbResMap;
  96. }
  97. /**
  98. * 预测组件总调用方法
  99. *
  100. * @return
  101. */
  102. public Map<String, String> execNameFindTester() {
  103. try {
  104. NameFinderME finder = this.prodNameFinder();
  105. Map<String, String> basicNameProbResMap = this
  106. .cptBasicNameProb(finder);
  107. Map<String, String> nameProbResMap = this
  108. .filterNameProbRes(basicNameProbResMap);
  109. return nameProbResMap;
  110. } catch (Exception e) {
  111. // TODO Auto-generated catch block
  112. e.printStackTrace();
  113. return null;
  114. }
  115. }
  116. }

大家依然可以从详细的注释上获得很多的信息,设定的参数只有命名实体概率过滤的阈值,这个是可有可无的一个值,因为OpenNLP会自动过滤一波,但是如果有更高的要求,可以自己设定一个,我默认设定成0.6。然后再简单介绍几个重要的方法:1.prodNameFinder()是载入磁盘上的模型,直接传入模型的磁盘地址;2.cptBasicNameProb()是进行命名实体识别的核心方法,结果映射Map选用IdentityHashMap,因为考虑一个实体有可能被定为多个类别的情况,首先制作一个内嵌的基础分词器,其实这个分词器没有意义,是针对英文的,这就是我们为什么一开始要讲中文分词结果中间隔上空格重新写入文本的原因,基础分词器将文本内容按空格分开,放入一个String数组中,对finder的find()方法传入这个数组,就得到了命名实体识别的结果,用finder的prob()方法可以得到识别结果的概率。这时得到的命名实体结果并不是直接的词,而是一个二维数组,每一行代表识别出来的一个命名实体,该行的每一列存储命名实体对应的词元素在之前传入的String数组中的下标,因为懂命名实体识别的人都知道,命名实体也可以是多个词组成的词组,不只是词。返回的Map以这样的形式存放结果:

[html] view plain copy  
  1. <Name, Type:Probility>

key是实体,后面是所属的实体类别以及概率值;3.filterNameProbRes()方法传入刚才得到的Map结果集,返回过滤后的新Map结果集。

随便用了一些很少的关于电子诈骗的语料进行测试,最终识别出来的结果是这个样子的,可以看到,识别出了1个person和10个action,基本上还都有那么点意思,还有person的训练词库本身词量就很少,导致这个结果。

同样,源代码开源在:https://github.com/Ailab403/ailab-mltk4j,test包里面对应有完整的调用demo,以及file文件夹里面的测试语料和已经训练好的模型。

转载于:https://www.cnblogs.com/mansiisnam/p/5360783.html

(转)OpenNLP进行中文命名实体识别(下:载入模型识别实体)相关推荐

  1. 【ACL2021】基于边界检测增强的中文命名实体识别

    点击下面卡片,关注我呀,每天给你送来AI技术干货! 来自:复旦DISC 作者:石霭青 引言 命名实体识别(Named Entity Recognition,NER)是自然语言处理领域的一个基础任务,是 ...

  2. 基于深度学习的命名实体识别研究综述——论文研读

    基于深度学习的命名实体识别研究综述 摘要: 0引言 1基于深度学习的命名实体识别方法 1.1基于卷积神经网络的命名实体识别方法 1.2基于循环神经网络的命名实体识别方法 1.3基于Transforme ...

  3. 序列标注 | (5) 命名实体识别技术综述

    本文是对 <命名实体识别技术综述>的摘录和笔记. 论文链接 文章目录 1. 简介 2. 研究难点 3. 主要方法 4. 研究热点 5. 数据集和评价指标 6. 参考文献 1. 简介 命名实 ...

  4. 【NLP】一文了解命名实体识别

    导读:从1991年开始,命名实体识别逐渐开始走进人们的视野,在各评测会议的推动下,命名实体识别技术得到了极大地发展,从最初的基于规则和字典的方法,到现在热门的注意力机制.图神经网络等方法,命名实体识别 ...

  5. 命名实体识别(基于规则-无监督学习-机器学习-深度学习)

    文章目录 1 简介 2 NER标注语料库 3 NER工具库 4 序列标注标签方案 5 四类NER方法(规则-无监督学习-机器学习-深度学习) 5.1 基于规则的NER 5.2 基于无监督学习方法 5. ...

  6. 一文了解命名实体识别

    导读:从1991年开始,命名实体识别逐渐开始走进人们的视野,在各评测会议的推动下,命名实体识别技术得到了极大地发展,从最初的基于规则和字典的方法,到现在热门的注意力机制.图神经网络等方法,命名实体识别 ...

  7. 信息抽取(五)实体命名识别之嵌套实体识别哪家强,我做了一个简单的对比实验

    实体命名识别之嵌套实体识别哪家强 嵌套实体识别 实体矩阵构建框架 方法比较 GlobalPointer TPLinker Tencent Muti-head Deep Biaffine 实验结果 总结 ...

  8. 神圣的NLP!一文理解词性标注、依存分析和命名实体识别任务

    词性标注(Part-of-Speech Tagging, POS).命名实体识别(Name Entity Recognition,NER)和依存句法分析(Dependency Parsing)是自然语 ...

  9. A Transformer-based System for English Named Entity Recognition 基于Transformer的英语命名实体识别系统

    (1)  目的和背景 ① 研究任务: 复杂的复合命名实体可能是复杂的名词短语.动名词.不定式.甚至是完整的句子.这种歧义使很难根据他们的上下文认识它们.为了解决复杂命名实体识别,提出了一个基于 Tra ...

最新文章

  1. 一个完整网站的代码_网站优化三步走,怎样给自己的网站做优化?
  2. 通过简易的前台代码实现无限二级域名转向(来自无忧 biyuan老矣)
  3. 从零开始学习Docker
  4. 开发经验漫谈 -- Git在开发流程中的运用
  5. git 源代码自动检查_Visual Studio中Git的简单使用
  6. 2018-2019-2 20165312《网络攻防技术》Exp7 网络欺诈防范
  7. linux常用命令(1)——文件管理
  8. linux登录日志保存多久,Centos清除系统日志和登录记录-Linux清除系统日志和登录记录的方法-吾爱编程网...
  9. APP开发手记01(app与web的困惑)
  10. 博图编写温度程序_数字式温度控制器程序设计
  11. Java校招120道面试题目合集
  12. 孟岩:参与设计20多个区块链经济系统后,我总结出4个原则和7个陷阱 |区块链捕手
  13. idea创建maven项目失败, Failed to create a Maven project
  14. 185电缆的接法图解_三相电缆线的接法图解
  15. Bzoj4763 雪辉
  16. secureFX上传中文文件名乱码
  17. [转]UML八大误解
  18. 看保罗-艾伦的《我用微软改变世界》有感,谈中国原创发明创业的苦逼环境!操蛋的中国VC!
  19. ThinkPHP框架总结之配置及使用
  20. 一、stm32开发环境搭建

热门文章

  1. 复习笔记(七)——C++友元
  2. Mysql生产指定时间段随机日期函数
  3. java防止表单二次提交_防止表单重复提交
  4. 哨兵机器人钢力士_哨兵胳膊都被卸了?巴西厂X战警钢力士正式公布
  5. 详解python中的round()函数
  6. vue-cli打包遇到的问题
  7. LBP特征的理论介绍
  8. Activiti工作流引擎使用详解(一)
  9. Java提高篇——Java 异常处理
  10. Java 中 ConcurrentHashMap 原理分析