无监督构建词库:更快更好的新词发现算法
作者丨苏剑林
单位丨追一科技
研究方向丨NLP,神经网络
个人主页丨kexue.fm
新词发现是 NLP 的基础任务之一,主要是希望通过无监督发掘一些语言特征(主要是统计特征),来判断一批语料中哪些字符片段可能是一个新词。
“新词发现”是一个比较通俗的叫法,更准确的叫法应该是“无监督构建词库”,因为原则上它能完整地构建一个词库出来,而不仅仅是“新词”。当然,你可以将它跟常用词库进行对比,删掉常见词,就可以得到新词了。
分词的目的
分词一般作为文本挖掘的第一步,仿佛是很自然的,但事实上也应该问个为什么:为什么要分词?人本来就是按照字来书写和理解的呀?
当模型的记忆和拟合能力足够强(或者简单点,足够智能)的时候,我们完全可以不用分词的,直接基于字的模型就可以做,比如基于字的文本分类、问答系统等,早已有人在研究。但是,即便这些模型能够成功,也会因为模型复杂而导致效率下降,因此,很多时候(尤其是生产环境中),我们会寻求更简单、更高效的方案。
什么方案最高效?以文本分类为例,估计最简单高效的方案就是“朴素贝叶斯分类器”了,类似的,比较现代的是 FastText,它可以看作是“朴素贝叶斯”的“神经网络版”。要注意,朴素贝叶斯基于一个朴素的假设:特征之间相互独立。这个假设越成立,朴素贝叶斯的效果就越好。然而,对于文本来说,显然上下文紧密联系,这个假设还成立吗?
注意到,当特征之间明显不独立的时候,可以考虑将特征组合之后,使得特征之间的相关性减弱,再用朴素贝叶斯。比如,对于文本,如果以字为特征,则朴素假设显然不成立,如“我喜欢数学”中的“喜”和“欢”、“数”和“学”都明显相关,这时候我们可以考虑将特征进行组合,得到“我/喜欢/数学”,这样三个片段之间的相关性就没有那么强了,因此可以考虑用上述结果。
可以发现,这个过程很像分词,或者反过来说,分词的主要目的之一,就是将句子分为若干个相关性比较弱的部分,便于进一步处理。从这个角度来看,分的可能不一定是“词”,也可能是短语、常用搭配等。
说白了,分词就是为了削弱相关性,降低对词序的依赖,这一点,哪怕在深度学习模型中,都是相当重要的。有些模型,不分词但是用 CNN,也就是把若干个字组合作为特征来看,这也是通过字的组合来减弱特征间的相关性的体现。
算法大意
既然分词是为了削弱相关性,那么我们分词,就是在相关性弱的地方切断了。文章《【中文分词系列】 2. 基于切分的新词发现》[1] 其实就是这个意思,只是那里认为,文本的相关性仅由相邻两字(2grams)来决定,这在很多时候都是不合理的,比如“林心如”中的“心如”、“共和国”中的“和国”,凝固度(相关性)都不是很强,容易错切。
因此,本文就是在前文的基础上改进,那里只考虑了相邻字的凝固度,这里同时考虑多字的内部的凝固度(ngrams),比如,定义三字的字符串内部凝固度为:
这个定义其实也就是说,要枚举所有可能的切法,因为一个词应该是处处都很“结实”的,4 字或以上的字符串凝固度类似定义。一般地,我们只需要考虑到 4 字(4grams)就好(但是注意,我们依旧是可以切出 4 字以上的词来的)。
考虑了多字后,我们可以设置比较高的凝固度阈值,同时防止诸如“共和国”之类的词不会被切错,因为考虑三字凝固度,“共和国”就显得相当结实了,所以,这一步就是“宁放过,勿切错”的原则。
但是,“各项”和“项目”这两个词,它们的内部凝固度都很大,因为前面一步是“宁放过,勿切错”,因此这样会导致“各项目”也成词,类似的例子还有“支撑着”、“球队员”、“珠海港”等很多例子。但这些案例在 3grams 中来看,凝固度是很低的,所以,我们要有一个“回溯”的过程,在前述步骤得到词表后,再过滤一遍词表,过滤的规则就是,如果里边的 n 字词,不在原来的高凝固度的 ngrams 中,那么就得“出局”。
所以,考虑 ngrams 的好处就是,可以较大的互信息阈值情况下,不错切词,同时又排除模凌两可的词。就比如“共和国”,三字互信息很强,两字就很弱了(主要还是因为“和国”不够结实),但是又能保证像“的情况”这种不会被切出来,因为阈值大一点,“的情”和“的情况”都不结实了。
详细的算法
完整的算法步骤如下:
第一步,统计:选取某个固定的 n,统计 2grams、3grams、…、ngrams,计算它们的内部凝固度,只保留高于某个阈值的片段,构成一个集合 G;这一步,可以为 2grams、3grams、…、ngrams 设置不同的阈值,不一定要相同,因为字数越大,一般来说统计就越不充分,越有可能偏高,所以字数越大,阈值要越高;
第二步,切分:用上述 grams 对语料进行切分(粗糙的分词),并统计频率。切分的规则是,只有一个片段出现在前一步得到的集合 G 中,这个片段就不切分,比如“各项目”,只要“各项”和“项目”都在 G 中,这时候就算“各项目”不在 G 中,那么“各项目”还是不切分,保留下来;
第三步,回溯:经过第二步,“各项目”会被切出来(因为第二步保证宁放过,不切错)。回溯就是检查,如果它是一个小于等于 n 字的词,那么检测它在不在 G 中,不在就出局;如果它是一个大于 n 字的词,那个检测它每个 n 字片段是不是在 G 中,只要有一个片段不在,就出局。还是以“各项目”为例,回溯就是看看,“各项目”在不在 3gram中,不在的话,就得出局。
每一步的补充说明:
1. 较高的凝固度,但综合考虑多字,是为了更准,比如两字的“共和”不会出现在高凝固度集合中,所以会切开(比如“我一共和三个人去玩”,“共和”就切开了),但三字“共和国”出现在高凝固度集合中,所以“中华人民共和国”的“共和”不会切开;
2. 第二步就是根据第一步筛选出来的集合,对句子进行切分(你可以理解为粗糙的分词),然后把“粗糙的分词结果”做统计,注意现在是统计分词结果,跟第一步的凝固度集合筛选没有交集,我们认为虽然这样的分词比较粗糙,但高频的部分还是靠谱的,所以筛选出高频部分;
3. 第三步,例如因为“各项”和“项目”都出现高凝固度的片段中,所以第二步我们也不会把“各项目”切开,但我们不希望“各项目”成词,因为“各”跟“项目”的凝固度不高(“各”跟“项”的凝固度高,不代表“各”跟“项目”的凝固度高),所以通过回溯,把“各项目”移除(只需要看一下“各项目”在不在原来统计的高凝固度集合中即可,所以这步计算量是很小的)。
代码实现
import pymongo
import redb = pymongo.MongoClient().baike.items# 语料生成器,并且初步预处理语料
# 这个生成器例子的具体含义不重要,只需要知道它就是逐句地把文本yield出来就行了
def text_generator():for d in db.find().limit(5000000):yield re.sub(u'[^\u4e00-\u9fa50-9a-zA-Z ]+', '\n', d['text'])
min_count = 32
order = 4
corpus_file = 'wx.corpus' # 语料保存的文件名
vocab_file = 'wx.chars' # 字符集
ngram_file = 'wx.ngrams' # ngram集
output_file = 'wx.vocab' # 最后导出的词表write_corpus(text_generator(), corpus_file) # 将语料转存为文本
count_ngrams(corpus_file, order, vocab_file, ngram_file) # 用Kenlm统计ngram
ngrams = KenlmNgrams(vocab_file, ngram_file, order, min_count) # 加载ngram
ngrams = filter_ngrams(ngrams.ngrams, ngrams.total, [0, 1, 3, 5]) # 过滤ngram
ngtrie = SimpleTrie() # 构建ngram的Trie树for w in Progress(ngrams, 100000, desc=u'build ngram trie'):_ = ngtrie.add_word(w)candidates = {} # 得到候选词
for t in Progress(text_generator(), 1000, desc='discovering words'):for w in ngtrie.tokenize(t): # 预分词candidates[w] = candidates.get(w, 0) + 1
# 频数过滤
candidates = {i: j for i, j in candidates.items() if j >= min_count}
# 互信息过滤(回溯)
candidates = filter_vocab(candidates, ngrams, order)# 输出结果文件
with open(output_file, 'w') as f:for i, j in sorted(candidates.items(), key=lambda s: -s[1]):s = '%s\t%s\n' % (i.encode('utf-8'), j)f.write(s)
评测
https://kexue.fm/usr/uploads/2019/09/1023754363.zip
https://github.com/bojone/word-discovery/blob/master/evaluate.py
总结
本文复现了笔者之前提出了新词发现(词库构建)算法,主要是做了速度上的优化,然后做了做简单的效果评测。但具体效果读者还是得在使用中慢慢调试了。
祝大家使用愉快,Enjoy it!
相关链接
点击以下标题查看作者其他文章:
当Bert遇上Keras:这可能是Bert最简单的打开姿势
一文读懂「Attention is All You Need」| 附代码实现
基于CNN的阅读理解式问答模型:DGCNN
基于DGCNN和概率图的轻量级信息抽取模型
#投 稿 通 道#
让你的论文被更多人看到
如何才能让更多的优质内容以更短路径到达读者群体,缩短读者寻找优质内容的成本呢?答案就是:你不认识的人。
总有一些你不认识的人,知道你想知道的东西。PaperWeekly 或许可以成为一座桥梁,促使不同背景、不同方向的学者和学术灵感相互碰撞,迸发出更多的可能性。
PaperWeekly 鼓励高校实验室或个人,在我们的平台上分享各类优质内容,可以是最新论文解读,也可以是学习心得或技术干货。我们的目的只有一个,让知识真正流动起来。
? 来稿标准:
• 稿件确系个人原创作品,来稿需注明作者个人信息(姓名+学校/工作单位+学历/职位+研究方向)
• 如果文章并非首发,请在投稿时提醒并附上所有已发布链接
• PaperWeekly 默认每篇文章都是首发,均会添加“原创”标志
? 投稿邮箱:
• 投稿邮箱:hr@paperweekly.site
• 所有文章配图,请单独在附件中发送
• 请留下即时联系方式(微信或手机),以便我们在编辑发布时和作者沟通
?
现在,在「知乎」也能找到我们了
进入知乎首页搜索「PaperWeekly」
点击「关注」订阅我们的专栏吧
关于PaperWeekly
PaperWeekly 是一个推荐、解读、讨论、报道人工智能前沿论文成果的学术平台。如果你研究或从事 AI 领域,欢迎在公众号后台点击「交流群」,小助手将把你带入 PaperWeekly 的交流群里。
▽ 点击 | 阅读原文 | 查看作者博客
无监督构建词库:更快更好的新词发现算法相关推荐
- 从无监督构建词库看「最小熵原理」,套路是如何炼成的
作者丨苏剑林 单位丨广州火焰信息科技有限公司 研究方向丨NLP,神经网络 个人主页丨kexue.fm 在深度学习等端到端方案已经逐步席卷 NLP 的今天,你是否还愿意去思考自然语言背后的基本原理?我们 ...
- 发现新词 | NLP之无监督方式构建词库(一)
文章目录 一.数据介绍及处理 二.寻找未登录词 1.统计语料库中的词信息 2.利用互信息熵得到初始化词库 3.对语料库进行切分 4.利用搜索引擎判断新词 5.迭代寻找新词 6.方法总结 一.数据介绍及 ...
- 网吧无盘服务器为什么玩地下城和穿越火线卡其它游戏不卡,为什么网吧的电脑配置更低,玩游戏却更快更爽?...
原标题:为什么网吧的电脑配置更低,玩游戏却更快更爽? 随着互联网时代的到来,现在家家户户都有一台或几台电脑几乎成为常态,有人认为网吧行业可能会因此受到冲击,但是相反我国的营业性网吧不仅没有减少,还继续 ...
- MesaLink v0.7.0发布 | 迎接TLS 1.3时代 更快更安全
MesaLink是百度安全实验室研发的一个内存安全并且兼容OpenSSL C API的传输层安全(TransportLayer Security, TLS)协议栈.近年来TLS漏洞频发,以2014年的 ...
- 清华大学丁霄汉:深度网络重参数化——让你的模型更快更强
不到现场,照样看最干货的学术报告! 嗨,大家好.这里是学术报告专栏,读芯术小编不定期挑选并亲自跑会,为大家奉献科技领域最优秀的学术报告,为同学们记录报告干货,并想方设法搞到一手的PPT和现场视频--足 ...
- 实用的it知识学习_怎样能更快更好的学习好书法?分享一些比较实用的理论知识...
如何能更快更高效的学习书法?首先了解一些书法理论知识是很有必要的!它能让你在学习书法的过程中不至于迷茫 !能助你更快学好书法! 一.书论在实践中产生 我们大部分人都觉得学习书法可以没有理论,但不可无技 ...
- 极智Paper | YOLOv7 更高 更快 更强
欢迎关注我的公众号 [极智视界],获取我的更多笔记分享 大家好,我是极智视界,本文解读一下 更高.更快.更强的 YOLOv7:Trainable bag-of-freebies sets ne ...
- 与阿里云整个生态体系共同成长,更快更好的为房地产行业客户提供高价值的服务。...
免费开通大数据服务:https://www.aliyun.com/product/odps "最早是新业务要做,但是买服务器来不及,管理员没到位,而且新业务的成本很高,是否能成功也是未知,因 ...
- 与阿里云整个生态体系共同成长,更快更好的为房地产行业客户提供高价值的服务。
免费开通大数据服务:https://www.aliyun.com/product/odpsyu "最早是新业务要做,但是买服务器来不及,管理员没到位,而且新业务的成本很高,是否能成功也是未知 ...
最新文章
- hbase的集群搭建
- [云炬创业管理笔记]第三章测试4
- zoj 3791 An Easy Game
- html5内容切换特效,html5+jQuery图片和文字内容同时左右切换特效
- 李国庆离开当当,广东消委会告长隆,智能校服提供定位功能,全球首个5G火车站来了,这就是今天的大新闻...
- 北航计算机学院有河南的,北航计划在豫招生165人 河南多所高职公布预录名单...
- 前端开发之基础知识-HTML(一)
- ASP.NET MVC 3发布报错(ASP.NET MVC 3在没有安装环境的服务器上运行)的解决方案
- Wi-Fi 6连续两年出货量国内登顶,锐捷无线靠什么这么6?
- 批量修改图像命名方式
- python--迭代器与生成器
- 媒体查询@media scree
- 步进伺服控制程序 用三菱plc和威纶触摸屏编写
- 介绍几款WAP网页制作工具
- asp.net打开客户端bartender文件
- 曲线运动与万有引力公式_高中物理公式大全
- 程序员年薪40万被国企同学怒怼:没啥贡献,凭什么工资这么高!
- 切比雪夫不等式与马尔可夫不等式
- python面向对象游戏_【Python之旅】第四篇(四):基于面向对象的模拟人生游戏类...
- SHAP:解释模型预测的通用方法
热门文章
- rac下asm管理的表空间-数据文件的重命名
- Android应用开发之(通过ClipboardManager, ClipData进行复制粘贴)
- 2021年宝鸡中学高考成绩查询,宝鸡各高中2020年高考喜报成绩一览
- c语言创建线程函数怎么使用方法,如何用C语言实现多线程
- Android适配华为手机,华为Mate 10将适配Android P 更流畅体验
- docker 查看虚拟网卡_最简单的免费虚拟化方案:Hyper-V Server + Windows Admin Center
- plt图片输出 python_利用Python制作词云,wordcloud神器你值得拥有
- oracle查看字典结构体,Oracle-17-数据字典查看约束信息
- python关联分析引擎_PowerBI x Python 之关联分析(上)
- 四十七、微信小程序开发页面结构WXML