NLP基础工具
简介
企业级nlp工具制作时候的心得分享,本篇更新:注音器 和 分词工具
项目依赖并非普通民用所能接触,只能大致解释原理,多的不便多说。
注音器
开门见山
python的注音器,可以理解为 pypinyin 的进化版,如果你有企业级的词库作为支撑,这个注音器是个不二之选。
调用方法
from zhuyin_tool import zhuyin
result = zhuyin(text, best_match=0, use_tokenizer=0)
text: 要注音的str
best_match: 因为有多音,有多种可能输出,=0全出,=1只出top prob首选
use_tokenizer:是否开启分词器,0不开,1开启
注:就算不开分词器,注音器也内置了最大前向匹配的基础分词
背景介绍
在工业化的使用场景下,你会发现pypinyin是不够用的,分两个方面
- 准确率问题:包括了pypinyin对多音字词的支持,评测下来准确率是90%左右浮动,差的那10%就等着源源不断的问题吧
- 业务场景支撑不行:pypinyin只能首选和全出,没有统计的支撑,举些例子:出血(xue/xie),谁(shei/shui)是。这些词的多音是都对的,但此时如果你的注音器只能出一个结果,就很尴尬了,比如你在聊天场景,你的注音库是 出血(chuxie)用户输入 chuxue 你是可以不出词吗?显然你会被人骂死。
正确的做法是,你应该基于数据统计来做注音,这能在提升注音准确率的同时,顺带给你一个分流的逻辑,比如 chuxie 50% / chuxue 50%,这会对你在做带拼音词库,百科,词表等相关业务的时候有重要的帮助,所以在此手搓了这个注音器。
原理简介
注音器的逻辑很简单,你要先有两个带拼音和统计的字典,然后最大前向匹配查字典就完了,如果有多段,记下概率后算笛卡尔积。如果要开分词器,开在最大前向匹配前。
关键在一手做字典的功力
首先你要有企业级的统计资源,比如你在:某聊天软件,某短视频字幕,某输入法,某搜索团队工作,这样你的统计回流做成的字典才能和pypinyin拉开大差距,我做下来,不同测试集正确率在97%-99%,pypinyin90%正确率。普通用户请出门左转pypinyin,已经很优秀了。
然后就是根据hive回流统计去做字典,这项目里的字典只是做个演示,从 雾凇拼音 偷了一个大致像样主字典做的,做字典程序在 build_zhuyin_dict里,给你个sample,不要真用了,这并非我在用的字典。正常做法你要从云侧去统计,spark计算。至于计算过程,你看一下 single_zhuyin_dict.json 和 multi_zhuyin_dict.json 的格式应该就明白了。
问题解释
有兄弟问了个很好的问题,比如 重 这个字,分布是:zhong 0.9,chong 0.1,那么我遇到 重大校区,即重庆大学校区的缩写,按笛卡尔积算不是照样首选zhongda吗?
答案很简单,就是你的多字词库里要有,重大校区 这种搭配,或者你要去搞二元字典,重大-校区,重大-学生,我是觉得直接收录一元和扩展搜索二元字典区别不大
主要还是你要有标注的字典资源。自己手标是不现实的,别想了,要有用户”自愿“的为你标注的业务场景,比如你在微信,你能统计到用户打chongdaxiaoqu,对话发送了 重大校区,然后你给这两个打点统计对起来,这种顶级的标注资源。相关业务云侧的统计数据,每日是TB级的,所以可想而知类似工具背后依赖的迭代字典对比开源的这些注音项目是力大砖飞的。
否则,没有资源的,请出门左转pypinyin熬。
分词器
调用方法
1 | from tokenizer import Tokenizer |
背景
也是一个基于统计语言模型的中文分词器
核心做法是利用一元模型(Unigram)和二元模型(Bigram),通过动态规划寻找最优分词路径。
为什么用这个手搓的,说是主要改了算法公式和0.5那个配比参数,公式是融合了jieba的,最后评测下来提升也是高10%。但在我看来评价有夸大成分,主要还是背后的词库好,所以能有这个提升。我的建议是用jieba,把词库换了就完事了。该程序是我现在在用的分词器,python版本的仿写,加入了一些个人的理解。
原理简述
词典加载:从CSV文件加载词语的对数概率,构建Unigram和Bigram概率表
文本预处理:用正则表达式分离英文、数字和空白字符
Trie树索引:将词典组织成前缀树,实现O(n)时间内的词语快速查找
DAG构建:为输入句子构建有向无环图,节点表示字位置,边表示可能的词语
动态规划:使用维特比算法求解最优路径,通过线性插值平滑平衡一元和二元概率
路径回溯:根据DP结果回溯得到最终的分词序列
该方法结合了词典匹配和概率图模型的优点,能够处理未登录词并考虑上下文信息。
最终的关键还是一手做词库的数据功底
词库制作
分词器依靠的是一个带分数的一元二元词库,一元类似:明天,二元类似:明天-见
你要根据统计数据去计算分数
一元分数是先从一元回流去筛选和抽一部分词库词(这个就靠你自己去想怎么做了),抽完以后,算全局概率分布,然后-logE。有条件的话你可以映射0-225。
二元分数是,在一元词库的基础上,去二元回流统计里,捞前元是一元的那些,记得按频率筛选一下。然后计算前后元的条件概率,再-logE
由于我没找到有那种开源的二元统计,这里就空着了,只传了分词器的实现部分,仅供参考。
结语
数据积累是一切算法实现的前提。
其实这个世界从来没有什么弯道超车,有的只是厚积薄发。