step1:寻找综述
没找到太好的综述。
step2:寻找技术博客文章
如寻找技术博客(如CSDN与个人博客站点)与文章(如知乎、简书),具体到新词发现任务,如:
- 基于互信息和左右信息熵的短语提取识别-码农场
- 互联网时代的社会语言学:基于SNS的文本数据挖掘 | Matrix67: The Aha Moments
- python3实现互信息和左右熵的新词发现 - 简书
step3:寻找已有实现
如从Github上搜索与筛选相关开源项目,如:
- xylander23/New-Word-Detection: 新词发现算法(NewWordDetection)
- zhanzecheng/Chinese_segment_augment: python3实现互信息和左右熵的新词发现
step4:结合知识点研读开源项目
算法初始思路
经过研究以上代码与相关文章,发现主要有2种思路:
- 不依赖分词,直接进行新词发现,如上面开源项目1
- 在原有分词基础上进行,如上面开源项目2
相比而言(更多的是感性认识,并没有对比观察多少数据从而建立起有依据的推论),不依赖分词能够避免原有分词错误而引起的后面的错误,而在原有分词基础上进行则更加准确,因为可以依赖于分词结果作为输入特征,个人认为可能方案2(即在原有分词基础上进行)可能会更好些,当然这又受限于分词的准确率。
相关特征
识别新词即确定两个词(或多个)是否能够组合成为一个词,主要看词内部的凝固度以及词外部的自由度,其中内部的凝固度可以用点间互信息
来衡量,而自由度则可以用左右邻的信息熵
来衡量。
大致流程
对于所有的候选新词分别计算以上两个特征,通过某种方式组合在一起,或线性加和或幂次乘积来给候选新词打分,同时设定一些阈值过滤掉不符合条件的候选词,并将所有过滤后的候选词按分数高低降序排序,从而得到最终的结果。
step5:改进与整合原有项目
自己主要参考项目2,但发现存在一些不足,如:
- 没有实现开箱即用的接口
- 数据结构设计不合理,比如遍历自定义的类所组成的列表进行匹配查找,耗时较多
- 虽然将引入外部词典数据进行初始化构建的模型进行了pickle持久化操作,但是其实没必要
- 不能很好地多次调用,每次调用都需要初始化或读取持久化的对象,耗时较长。
经过不断实践与探索,基本上比较好地解决了以上问题,同时在过程中也考虑了很多问题,如:
- 基于分词还是不基于分词
- 是否引入外部词典作为结果排序矫正
- 是否提供用户自定义词典以及自定义停用词接口
- 采用何种数据结构,是否照搬项目中数据结构,还是进行优化改进
- 在每次调用时都需要进行对外部词典数据初始化的过程,使用pickle文件写入读取持久化还是使用deepcopy进行对象拷贝,怎样更快
- 如何对如互信息与信息熵等统计特征进行加权组合,参数如何选取调整
- 如何引入其他信息增强发现能力以及矫正能力,比如词性信息(然而结巴的那个词典里面许多词性信息都不准确,比如说将
知识
的词性标注为动词) - 设计一个什么样的接口才能使用户很方便的使用
- 如何将该新词发现模块与分词系统等较好地整合在一起
- 如何更好地融入人工校验机制
- 是否加入机器学习、深度学习等算法,包括有监督、无监督、强化学习、在线学习等
实现
smilelight/lightText: 文本处理相关库,目前包括新词发现等功能。
后记
当今nlp各任务的各种实现从传统规则到机器学习再到深度学习比比皆是,层出不穷,然而根本就没有完美的算法,没有完美的系统,有的只是不断地改进和优化。
个人心得
在进行系统设计时,前期一定要对项目有一个比较清晰的规划,比如它的定位是什么、有哪些可以参考借鉴的已有实现,重要的搭一个能够跑起来的架子,不论啥效果;在中期优化过程中,则需要综合考虑时间空间硬件精度等多种因素,在一方面有所得有时必须建立在在其它某些方面有所失,比如各种时间空间互换、精度与时间空间互换等,在不同的时期不同的场景下主要矛盾不同,因此所对应的最佳策略也不唯一;在整个项目的生命周期中都需要不断考虑项目的拓展性,许多时候多写几个函数,多整几个文件来将不确定的、复杂的实现解耦,便于后续的排查调整。
参考
略