Stanford Corenlp是斯坦福大学的自然语言处理工具,其中中文分词是基于条件随机场CRF (Conditional Random Field) ,不是基于字典的直接匹配。最近调用Stanford Word Segmenter进行中文分词时,发现一些tokens切割不符合我们的预期,比如“大数据”被切分为“大 / 数据”,“信息安全”切分为“信息 / 安全”, “草泥马”被切分为草 / 泥马。我们希望将某些特定的词作为一个token来处理,因此想通过增加自定义词典(扩展词典)来实现。

一.网络上已有的资源

为了解决Stanford Corenlp中文分词自定义词典问题,前后耗费了大概有2- 3天的时间,几乎查找了内外网所有相关的资源,为了避免后面的童鞋再走弯路,下面归纳分析网络上关于此问题的资源:

1. Stanford Corenlp + IKAnalyzer

https://www.cnblogs.com/whuqin/p/6149742.html (还有一系列雷同文章)
这个方法看起来好像有些可行,模仿ChineseSegmenterAnnotator实现IKSegmentAnnotator,比较了这两个类,主要区别在于这两个方法
IKSegmentAnnotator

private List<String> splitWords(String str) throws Exception{...}

ChineseSegmenterAnnotator

private void splitCharacters(CoreMap annotation) {...}

我认为该方法就是把stanford的分词器(基于CRF)换成了IKAnalyzer的分词器IKSegmenter(基于词典匹配),代码不全,也没有任何注释,还要研究IKAnalyzer指定扩展词典和删除词典。对于仅应用分词而非研究分词的人来说,很难搞清楚,反正我是没运行成功,如果有小伙伴明白这种处理方法,请多多指教。

2. 引入自定义词典

https://blog.csdn.net/dushenzhi/article/details/8734173
下面把这段代码我能看懂的部分进行解释

java -mx1g -cp seg.jar edu.stanford.nlp.ie.crf.CRFClassifier//-mx1g 指定运行内存
//-cp 或者-classpath也可以,指定jar包路径
/* seg.jar分词jar包,在stanford-segmenter-2018-10-16文件夹下面,我下载下来的分词jar包命名是 stanford-segmenter-3.9.2.jar*/-sighanCorporaDict data-loadClassifier data/ctb.gz-testFile preprocess-$1.txt  //测试文件,即要分词的文本-inputEncoding UTF-8    //urf-8编码-sighanPostProcessing true-serDictionary data/dict-chris6.ser.gz,data/cedict.txt,data/ntusd.txt  //分词词典为原词典data/dict-chris6.ser.gz和自定义的词典data/cedict.txt,data/ntusd.txt(自定义词典可以有多个)-keepAllWhitespaces false >$1_seged.txt//分词结果输出到文件$1_seged.txt

下面来运行这段代码
测试文本,preprocess-$1.txt中的内容:大数据时代,信息安全尤为重要
采用原始词典的分词结果为:大 / 数据 / 时代,信息 / 安全 / 尤为 / 重要
自定义词典,cedict.txt的内容:
大数据
信息安全
分词结果

再来测试一个文本:昨天我看见一只草泥马
用原始词典分词

增加自定义词典:草泥马
分词结果

两个测试结果均不符合扩展词典中定义的分词规则,暂时认为这种方法自定义词典不起作用,如果有小伙伴测试到起作用的样本,告诉我哦

3. 一大波僵尸操作

https://blog.csdn.net/a313827758/article/details/87977576
这一波操作反正我是看的稀里糊涂

segment.serDictionary = edu/stanford/nlp/models/segmenter/chinese/dict-chris6.ser.gz,yourDictionaryFile

配置词典属性在stanford-chinese-corenlp-2018-10-05-models/StanfordCoreNLP-chinese.properties中修改,用notepad++打开修改后直接保存就可以,但是这里没有交代清楚yourDictionaryFile怎么生成 (后面我会提到)
网上能找到的该问题解决方案大概也就分这3类,能力有限,非专业研究分词,如果有错误请及时指出。

二、Stanford Corenlp官网给出的方法

https://nlp.stanford.edu/software/segmenter-faq.html
以前这个链接只有第一个问题关于retrain the Chinese Segmenter。今天再打开竟然多了第二个问题,how i can add words to the dictionary,如何往词典中加词,这不就是增加语料、增加自定义词典嘛。激动的是,我昨天才刚刚给stanford发了邮件,沟通关于自定义词典的事情,今天官网就更新了,我就默认是我的功劳吧,小有成就感,官方的效率好高

1. 翻译和解释

问题1:怎么重新训练中文分词器
<1>准备语料

语料数据集按照如图所示的格式,每个句子占一行,词与词之间用空格隔开
<2>转化为Penn trees(不知道咋翻译,google译为:宾夕法尼亚树)格式
其中一种方法是利用这个工具 Treebanks tool,这个工具不在segmenter的下载文件中,在corenlp-full中,下面给出路径
stanford-corenlp-full-2018-10-05\stanford-corenlp-3.9.2.jar\edu\stanford\nlp\trees\Treebanks.class
执行这行命令转化格式

java edu.stanford.nlp.trees.Treebanks -words ctb7.mrg

但是我没找到ctb7.mrg这个文件
<3>还可以包含一些命名实体识别的词,如姓名、地点、公司名等,每行一个词

用这个命令把这些词转化成词典格式

java edu.stanford.nlp.wordseg.ChineseDictionary -inputDicts names.txt,places.txt,words.txt,... -output dict.ser.gz

edu.stanford.nlp.wordseg.ChineseDictionary在stanford-segmenter-2018-10-16/stanford-segmenter-3.9.2.jar里面,names.txt,places.txt,words.txt里面放的是你想增加的词,可以有多个txt文件,dict.ser.gz为输出结果
下面是我的代码

mywords.txt中的内容
大数据
信息安全
网络安全
dict.ser.gz中的内容(咱也看不懂是啥^^)

这里有个想法,可以把生成的dict.ser.gz放在一.3 yourDictionaryFile的位置,但是我尝试过好像对分词结果没什么影响。 有兴趣的小伙伴可以再尝试
<4>如果要在原来词典dict-chris6.ser.gz的基础上增加词典,用下面这个命令

 java -mx15g edu.stanford.nlp.ie.crf.CRFClassifier -prop ctb.prop -serDictionary dict-chris6.ser.gz -sighanCorporaDict data -trainFile train.txt -serializeTo newmodel.ser.gz > newmodel.log 2> newmodel.err

edu.stanford.nlp.ie.crf.CRFClassifier在stanford-segmenter-2018-10-16/stanford-segmenter-3.9.2.jar里面,下面是我执行的命令
生成newmodel.err, newmodel.log和newmodel.ser.gz,新生成的newmodel.ser.gz比原来的词典dict-chris6.ser.gz小的多,说明新词典中只包含新加入的词(train.txt中的词),而不是把新词和原始词典结合在一起

到这里为止第一个问题的答案解释完了,好奇心驱使我用新词典替换掉原始词典,嗯。。。报错了

问题在于ArrayList不能转化为Set,又掉坑里了,分别打开新旧词典一查到底
原始词典的文件头HashSet:

新生成的词典文件头ArrayList

我也不知道为啥,全部操作都是按照官方的命令,也没有错误!!!

三. 官方权威回复

使出浑身解数,搞了2天实在没招了,抱着最后一点点希望,给stanford发了邮件,没想到Stanford老师的效率这么高,24小时之内就回复我了,发件人名字竟然是John Bauer(应该是原创开发者之一),解释的非常详细,第一次这么近距离跟大佬对话,激动!!!我还找了Stanford John Bauer的照片^^

1.Email round 1

我:为什么新生成的词典与原始词典格式不同(HashSet vs. ArrayList)
这个问题没有正面回答
我:官网说新词典是基于原始词典训练生成的,为什么size小那么多
Answer The command you gave it will only train on the given sentences. You need a complete training corpus with a large number of training sentences to retrain the segmenter. Unfortunately, we cannot share our existing corpus because of licensing restrictions.

The dict file is a dictionary composed of a bunch of the words in the training file. I suppose you could manually expand it (see edu.stanford.nlp.wordseg.ChineseDictionary), add a few words, and re-serialized it. Unfortunately, there isn’t a ton of support right now for doing that.
我:如何生成新词典,生成后在哪里替换旧词典
Answer ----------------------------------------------------------------------------------------------------------------------------------
我按照邮件中给出的方法操作

生成新词典(新词+原始词典结合在一起)

运行segDemo,替换旧词典
结果

竟然结果还不对,真是期望越大,失望越大,啊啊啊==

Round 2

再次邮件骚扰
为什么分词结果不符合自定义的词典呢?
直接贴邮件回复,老师也太nice了,各种生动的例子,看到草泥马我乐了好半天,估计老师是google直接翻译的吧,哈哈哈
结论分词器只是参照自定义的语料,并非是强制的分词边界,毕竟Stanford segmenter是基于CRF,不是词典强制分词,这也就能解释有些新词works,有些却无效。
---------------------------------------------------------------End -----------------------------------------------------------------
全程边执行命令,边截图,边码字,眼睛要瞎了,先写到这里,很多细节都没提到,比如涉及到的所有.txt都要用utf-8 noBOM编码,用notepad++修改编码为utf-8。细节后面再补充,如果各位小伙伴操作有什么问题直接留言

Stanford Corenlp中文分词自定义词典(扩展词典)相关推荐

  1. 如何在基于Lucene的中文分词器中添加自定义词典(如Paoding、mmseg4j、IK Analyzer)...

    如何在基于Lucene的中文分词器中添加自定义词典(如Paoding.mmseg4j.IK Analyzer) 2013-07-08 21:54:29|  分类: 计算机 |字号 订阅 1. 使用Pa ...

  2. Lucene分词器,使用中文分词器,扩展词库,停用词

    2019独角兽企业重金招聘Python工程师标准>>> Lucene分词器,使用中文分词器,扩展词库,停用词 博客分类: 搜索引擎,爬虫 停止词:lucene的停止词是无功能意义的词 ...

  3. 中文分词算法 之 基于词典的正向最大匹配算法

    基于词典的正向最大匹配算法(最长词优先匹配),算法会根据词典文件自动调整最大长度,分词的好坏完全取决于词典. 算法流程图如下: Java实现代码如下: /*** 基于词典的正向最大匹配算法* @aut ...

  4. NLP-基础任务-中文分词算法(1)-基于词典: 机械分词(词典字符串匹配):前向最大匹配、后向最大匹配、双向最大匹配【OOV:基于现有词典,不能进行新词发现处理】

    分词与NLP关系:分词是中文自然语言处理的基础,没有中文分词,我们对语言很难量化,进而很能运用数学的知识去解决问题.对于拉丁语系是不需要分词的. 拉丁语系与亚系语言区别 拉丁语言系不需要分词,因为他们 ...

  5. stanford python中文分词

    总结,只有三步: 一 下载coreNLP https://stanfordnlp.github.io/CoreNLP/download.html 二 下载 http://nlp.stanford.ed ...

  6. solr6.6配置IK中文分词、IK扩展词、同义词、pinyin4j拼音分词

    solr基本指令: jetty部署[推荐]: Linux: $ bin/solr start: Windows: bin\solr.cmd start 创建core: Linux: $ bin/sol ...

  7. NLP-基础任务-中文分词算法(2)-基于词典:基于N-gram语言模型的分词算法【基于词典的分词方法】【利用维特比算法求解最优路径】【比机械分词精度高】【OOV:基于现有词典,不能进行新词发现处理】

    例子:"经常有意见分歧" 词典:["经常","有","意见","意","见",& ...

  8. python双向最大匹配算法_中文分词算法 之 基于词典的逆向最大匹配算法

    在之前的博文中介绍了基于词典的正向最大匹配算法,用了不到50行代码就实现了,然后分析了词典查找算法的时空复杂性,最后使用前缀树来实现词典查找算法,并做了3次优化. 下面我们看看基于词典的逆向最大匹配算 ...

  9. IK分词器扩展词典、停用词典、同义词典

    1.扩展词典         扩展词:就是不想哪些词分开,让他们成为一个词,比如"哈利波特" 自定义扩展词库 进入到elasticsearch的conf/analysis-ik/目 ...

最新文章

  1. 转 机器学习系列 08:深入理解拉格朗日乘子法、KKT 条件和拉格朗日对偶性
  2. Appium+python自动化3-启动淘宝app
  3. nginx proxy_next_upstream导致的一个重复提交错误
  4. C#语言中的可访问性约束
  5. D3.js比例尺 定量比例尺 之 线性比例尺(v3版本)
  6. mysql 慢查询sql实例_Mysql sql慢查询监控脚本代码实例
  7. 《Windows Phone 8 Development Internals》读书笔记-1-2-1-连载
  8. 动态规划|最大k乘积问题(C语言)
  9. js计算数组中每个元素出现的次数(2种方法)
  10. ip和端口正则表达式
  11. linux ping策略打开_Linux Iptables允许或阻止ICMP ping请求
  12. 数据可视化js框架 d3.js入门
  13. Xib和StoryBoard的区别
  14. 怎样打开.jar格式文件,怎样运行.jar格式文件
  15. 节奏大师服务器不稳定,节奏大师无法登陆的原因及解决方法
  16. 欧姆龙PLC CP1H与变频器通信要点总结
  17. 一个使用kindle近3年的菜鸟的几点建议
  18. [原创] IE中的图片显示不出来
  19. 沟通表达的实用技巧和练习方法
  20. Egret 学习笔记

热门文章

  1. HTML5期末大作业:日式料理网站设计——简洁日式料理餐饮(4页) HTML+CSS+JavaScript 父亲美食HTM5网页设计作业成品
  2. 光波长与RGB数值的转换
  3. ubuntu 14.04 使用极点五笔输入法
  4. Cesium的学习之路(二):底图切换
  5. 默慈金数 (hdu3723)
  6. Unity BIM模型导入调研
  7. SparkSession简单介绍
  8. 某酷ckey签名生成算法系列--(三)ast代码控制流平坦化
  9. 冷酷小叶的Java学习笔记Day3
  10. Oracle从周一到周日的日期排序