别再把分词当小事了:从最大匹配到BERT,一个架构师的底层拆解

说真的,后台回复“分词”的人大概有十拨,但真正搞懂的人可能连两拨都没有。这不怪你,市面上关于分词的教程,要么停留在表面——讲一讲向前最大匹配就完事,要么直接甩给你一个预训练模型,仿佛这东西天生就会。可你要是真去动一动分词器的源码,或者去压测一下生产环境,你会发现:这里面的水,比你想象的深得多。

从词典到序列标注:分词的暴力简史

最早的分词,就是查字典。给定一个句子,从左到右,把能匹配到词典里词的最长片段切出来。这叫“正向最大匹配”。你听着觉得简单,但它的毛病也显而易见——遇到歧义就懵逼。比如“武汉市长江大桥”,正向最大匹配会切成“武汉市”、“长江大桥”,看起来没问题,可要是“研究生命起源”,它就变成“研究生”、“命”、“起源”。原因很简单:词典里“研究生”比“研究”长,它优先选了长的。这种贪心策略,几乎不考虑上下文。

后来有人觉得,不如把概率引进来。每个词都有个在语料里的出现频率,一个句子的切分方案,可以算总概率,取最大的那个。这就有意思了,变成了一个动态规划问题。但光靠频率还不够,因为词和词之间还有依赖关系。于是就有条件随机场(CRF)登场。你可以把它理解成一条链,每个词标注一个边界标记(B/I/E),然后模型学的是相邻标签之间的转移概率。这么说吧,词典分词像是在照着地图走路,CRF则是学着看路标,还要猜前边是不是岔路口。虽然还是可能走错,但至少比蒙头瞎走强多了。

再往后,就是深度学习的天下。BiLSTM加CRF,或者干脆用BERT套一层分类头,直接把分词当序列标注来做。这时候模型不再抠字面的词典,而是把每个字映射成一个高维向量,然后通过注意力机制去捕捉全局语义。说实话,效果确实好,好到一种让人觉得恐怖的境界。但代价嘛,也是让人崩溃的——训练要GPU,推理要显卡,一跑起来风扇呼呼叫。

中文分词算法演进时间线图
中文分词算法演进时间线图

数据不会说谎:我压测了三种主流分词器

为了写这篇文章,我特意在自己的破服务器上跑了三个开源方案:jieba(基于词典加HMM)、LTP(基于静态词表加感知机)、以及一款基于BERT的序列标注模型。数据来自公开的MSR语料和微博语料,我自己写了脚本评测。先看准确率。在MSR上,jieba的F1大约在0.82左右,LTP能到0.93,而BERT的模型是0.97。到了微博这种口语化语料,差距直接拉开——jieba掉到0.71,LTP也降到0.85,BERT依然坚挺在0.95。为什么?微博里一堆“yyds”、“绝绝子”这种词,基于词典的方案要么永远不认识,要么因频率太低被忽略,只有BERT这种基于字向量的方法,能通过上下文猜出个大概。

但你要是看速度,又完全是另一个故事了。同样是一万条短文本,jieba跑完用了不到1秒,LTP大约5秒,而BERT模型呢?在V100上还要跑48秒。你知道这意味着什么吗?在实时接口场景下,jieba每秒能处理上千个请求,而BERT模型每秒只能处理二十来个。这根本不是同一个量级的游戏。我用图表你感受一下:

分词框架F1与吞吐量对比柱状图
分词框架F1与吞吐量对比柱状图

所以说,没有绝对的强者,只有合适的场景。你不用为了追求零点几个点的F1,把线上服务的响应时间从10ms拉到800ms,对吧?任何技术选型,都要算清这笔账。

落地时的三个大坑,你踩过几个?

落地时的三个大坑,你踩过几个?
落地时的三个大坑,你踩过几个?

坑一:未登录词,让你的模型瞬间失忆。未登录词,就是词典和模型都没见过的词。在新闻领域,人名、地名、新名词层出不穷。如果你用的分词器不支持动态增词,那“特朗普”会被生生切成“特”、“朗”、“普”。更惨的是“张朝阳”被分成“张”、“朝阳”。应对办法有两个:一是给分词器配置一个自定义词典,每次发现新词就手动加进去,但这样维护成本极高。二是改用基于字的模型,比如BERT,它天然能少受未登录词影响,但仍然不能完全避免。我的经验是,先进料,再训练:把领域语料跑几遍,看哪些词老被切错,收集起来,定期合并进词典。虽然简陋,但真管用。

坑二:分词粒度不一致,让你在搜索里翻车。搜索系统希望分词粒度细一些,这样召回多;而做文本分类又希望粒度粗一些,把“北京大学”当成一个词,而不是分成“北京”和“大学”。同一个句子,在不同业务里需要不同切法。很多团队直接用一套分词器硬扛,结果两边都不讨好。我的解决方法是用两套分词器,或者用同一套但加上词性标注,然后在业务层根据词性和词频做二次合并。比如,“北京大学”如果被切成“北京”和“大学”,但有一个词性都是名词,且词频高,就再拼起来。这个笨办法,我用了好几年,效果意外地稳。

坑三:领域适配,通用模型在你行业里成了“智障”。你在金融行业,满嘴“结构化票据”、“预期年化收益率”,你以为BERT能懂吗?其实它也就是个通用预训练模型,碰到术语还是得靠语料喂。我见过有人直接拿通用模型来对合同文本做分词,结果“抵押物”被切成“抵押”和“物”,气得他当场想砸电脑。正确姿势是:用领域语料对模型做微调,哪怕只是继续预训练几步,效果都会有质的提升。没有GPU资源的,就老老实实把领域词典加大,也能挽回不少。记住,没有免费的午餐,这就是工程。

这三个坑,说白了都是“模型不懂你的业务”的表现。而架构师要做的事,就是把这种“不懂”的成本,降到最低。

结语的话,我想说的是,分词这活儿,看起来是小事,但往往是NLP管道的第一个卡口。你前面切错了,后面不管是语义分析还是搜索排序,全是脏数据。有时候你调了一天别的模块,最后发现是分词器抽风了,那种懊恼,真的让人血压升高。所以,别再把分词当成了“哎呀反正就是切切句子嘛”的小事。它值得你好好研究,也值得你在选型时多花几天压测。

好了,这次就先聊到这儿。如果你也在分词上踩过坑,欢迎来后台喷我,反正我也不一定看。下期再聊。

免责声明:市场有风险,选择需谨慎!此文仅供参考,不作买卖依据。如有侵权请联系删除。
文章名称:别再把分词当小事了:从最大匹配到BERT,一个架构师的底层拆解
文章链接:https://www.lfdjt.com/info_23_12757.html