很多人做中文NLP项目的第一步,往往不是纠结用什么模型,而是先栽在“分词”上。英文有天然的空格边界,中文没有;而分词结果的每一个错误,都会顺着流水线传染给词性标注、命名实体识别,最终污染上层一切应用——文本分类、信息抽取、知识图谱构建,几乎没有哪个任务能逃过这一劫。所以我才坚持把分词、词性标注、命名实体识别这三件事放在一起讲:它们不是三个彼此独立的“入门练习”,而是同一套地基工程,拆开看各有各的难点,合起来才是完整的中文文本结构化方案。
这篇文章算是我的一个阶段复盘。做自然语言处理的这些年,我在小到几万条评论语料、大到上亿级别的行业报告里反复处理过这三类任务,中间踩过的坑、总结出的选型和调参经验,比教科书里写得更实在。如果你是刚接触NLP的学生,或者正在做文本挖掘、知识库、智能问答之类项目的工程师,这篇文章应该能帮你把三件事的顺序、原理和工具取舍一次理顺。
1. 分词没那么简单:歧义与未登录词两大难题
1.1 从一句话到一串词:中文为什么没有天然边界
对中文来说,分词是英文里不存在的特殊问题。英文句子每个单词之间都有空格,计算机用空格切分就能拿到接近合理的token串;中文是连续的汉字序列,词和词之间没有分隔符,算法必须先判断在哪里断开,才会得到有意义的词汇单元。
问题在于,这个“判断”并不总是唯一的。比如“研究生命起源”这句,既可以理解成“研究/生命/起源”,也可以理解成“研究生/命/起源”,上下文稍微一变,合法切分就完全不同。再比如经典的“乒乓球拍卖完了”——“乒乓球拍/卖完了”和“乒乓球/拍卖/完了”在脱离语境时都成立。这种场景在真实语料里大量出现,有时候连人都需要靠更大的上下文才能判断,机器就更不用说。
所以我一直跟团队强调一个概念:分词是中文NLP的上游水位,水位一高,下游全淹。后来我们做词性标注和NER时遇到的大量诡异结果,追根溯源,一半以上都是分词阶段埋下的雷。
1.2 三类主流分词算法:词典匹配、统计模型与混合式
分词算法演进到今天,大体可以分成三条路线。初学时不一定要把每条路都吃透,但至少要明白它们各自的思路和边界。
第一条是词典最大匹配。核心逻辑很简单:准备一个足够大的词典,从前向后(正向最大匹配)或从后向前(逆向最大匹配)尝试切出最长的词。正向最大匹配处理“我们研究生命起源”时会先从“我”开始找最长词,大概率得到“我们/研究/生命/起源”;但在“南京市长江大桥”这种句子上就很容易翻车,正向最大匹配会切出“南京市/长江大桥”,而“南京市长江大桥”这种歧义结构,逆向匹配可能又给出另一种结果。所以实践中常用双向最大匹配加消歧规则,谁切出来的词数量更少、单字更少,就倾向谁。
第二条是统计模型。不再依赖词典,而是根据大规模语料统计来判断切分概率。最简单的N-gram模型会计算“研究/生命”和“研究生/命”这两组词序列在语料里出现的概率,谁概率高选谁。再进一步就是用隐马尔可夫模型(HMM),把分词视为按字标注问题——每个字可以标注为词首、词中、词尾或单字词,用维特比算法求解整个序列最可能的标注结果。统计模型的优势是能处理一部分词典里没有的组合,但对低频片段容易产生偏差。
第三条是混合式,也是现在大多数开源中文分词工具的默认方案。先靠词典做召回主体,再用统计模型处理未登录词和歧义片段。比如广泛使用的中文分词库jieba,底层就是词典最大匹配加HMM的混合结构。这种方案的工程性和准确性比较平衡,也是我早期项目里最常用的起点。
1.3 分词最大的两个坑:歧义与未登录词
前面提过的“武汉市长江大桥”“研究生命起源”属于交集型歧义和组合型歧义,这类问题靠上下文能解决一部分,但靠单句分词器很难根治。更让项目头疼的是另一个问题:未登录词。
未登录词指的是词典里原本不存在的新词、人名、地名、产品名、专业缩写。比如“某某直播间的弹幕里全是新梗,我只想问‘这是什么意思’”,这里的网络新词大概率不在常用词典里,分词器就把它拆成“这/是/什么/意思”,语义倒不丢,但如果你要做关键词提取或实体识别,这个新词就彻底漏掉了。
处理未登录词的常见思路有两个:一个是在分词阶段给模型提供更强的上下文表征,让它在训练时见过类似模式后能泛化;另一个是工程上最直接的办法——自定义词典。无论是jieba还是其他工具,都支持在词典里追加领域词汇,加上词频和词性信息。这个操作在快速原型阶段几乎是必做的,后面我会专门讲自定义词典怎么维护才不会帮倒忙。
2. 词性标注:为每个词标好“身份标签”
2.1 词性标注为什么重要:它不只是语法课作业
词性标注(Part-of-Speech Tagging,POS Tagging)的任务是给句子里的每个词打上标签,指出它是名词、动词、形容词、副词还是其他类别。对初学者来说,这看起来像是中学语文课的“词性判断”,但放到NLP里,它解决的是很实际的歧义和结构化问题。
比如“打”这个字,在不同语境里可以是动词(“打篮球”)、量词(“一打啤酒”),甚至是介词性用法(“打去年开始”)。如果电脑只知道字面,不知道它在句子里承担的角色,后续的句法分析、语义角色判断、关键词权重计算都会出现偏差。我做情感分析项目时就有过一个很直观的体验:形容词和副词的组合往往决定了句子情绪的强烈程度,比如“这部电影非常好看”里,“非常”是副词强化“好看”的形容词程度。如果词性标注不可靠,这类权重就无法准确建模。
另外,词性标注也是句法分析、命名实体识别和关系抽取等上层结构预测的重要输入。可以说,它是让计算机从“认识词”走向“理解句子”的桥梁。
2.2 主流词性标注方法与常用词性体系
词性标注的方法演进,和分词非常相似。规则时代的做法是查词典加手工规则:如果词典里“领导”可以标名词也可以标动词,就根据上下文“领导我们”“公司领导”之类的模式判断。规则法在小领域能凑合用,但规则相互冲突后维护成本极高,很快就退居辅助地位。
随后是统计机器学习时代,主流工具用HMM或条件随机场(CRF)来做序列标注。HMM的思路是:词性序列是隐含状态,句子里的词是观测值,利用转移概率(前一个词性到后一个词性的概率)和发射概率(某个词性生成某个词的概率),通过维特比算法找最可能的词性序列。CRF则更进一步,不假设严格的独立性,可以直接把上下文特征组合成特征函数,在兼顾左右信息的基础上做全局最优标注。在那个年代,CRF几乎就是词性标注的优选方案,一直到深度学习出现。
深度学习方法现在基本有两种形态:一是双向LSTM(BiLSTM)编码词序列,再对每个位置做分类;二是用BERT这类预训练模型把整句话编码成上下文相关的向量,再在上面接一个分类头。预训练模型的优势很明显:它天然注意词所在的具体上下文,对兼类词的消歧能力比传统模型强一大截。
至于词性体系,中英文各不相同。英文里最常见的是宾州树库(Penn Treebank)的约45个标签集,中文领域则流传多种标注规范,核心类别大致包括名词、动词、形容词、代词、数词、量词、副词、介词、连词、助词、语气词等,但细分粒度差别很大。做中文项目的时候,我强烈建议在一开始就固定标签体系不要乱改,否则后续下游任务的适配会被反复折腾。
2.3 词性标注实践中容易踩的坑
第一个坑是分词错误连带标签错误。这个词性问题表面上在标注层,根子却在分词层——词边界一旦切错,标注模型根本无从正确分类。所以排查标注错误时,我一般先看原始切分对不对,而不是急着调标注模型的参数。
第二个坑是领域词性偏移。通用语料里“安装”大概率是动词,但在软件工程文档里,“安装包”“安装步骤”里的“安装”却在组合成名词性结构。如果模型没有见过来自该领域的训练数据,标出来的结果会显得非常“教科书化”,但不贴合业务。这时候需要补充领域标注数据,或者用词典强行指定领域词的优先词性。
第三个坑和工程习惯有关:不要丢掉词性标注的原始输出。有些项目组为了省存储,只保留分词结果,词性标完就丢弃。等到做特征分析或多轮迭代时又要重新跑一遍全量语料,白白浪费算力和时间。我会在管线上把标注结果直接输出成结构化字段(比如JSON或TSV),长期保留,以便后续各种分析任务随时取用。
3. 命名实体识别:从词典到深度序列标注的进阶之路
3.1 NER 到底要解决什么样的问题
命名实体识别(Named Entity Recognition,NER)解决的是更具体的一件事:从文本中找出人名、地名、机构名、时间、金额、产品名等专有名词,并标注其类别。
它和分词、词性标注最大的区别在于——前两者处理的是“每一个字/词”的角色,而NER关心的是“连续片段”的边界和类型。比如“张三在北京市朝阳区人民法院工作”这句话,识别结果应该是“张三/人名”“北京市朝阳区人民法院/机构名”。你不但要知道“北京市朝阳区人民法院”从哪里开始到哪里结束,还得给它归对类别。这一步做不好,后面的关系抽取无从谈起。
我早年用规则做文本抽取时最深的体会是:人名的识别远比想象中复杂。中文姓氏并不仅是常见百家姓,“令狐”“欧阳”这类复姓也频繁出现;人名又常和历史人物、网络昵称混在一起,词典根本拦不住。这类问题一旦出现,规则的破洞就一个接一个,所以后来我才坚决转向序列标注方案。
3.2 三条技术路线:规则、特征工程、深度学习
规则与词典路线是NER的起点。词典匹配能解决固定词表内的实体(如药品名、车型、赛事名),正则表达式可以稳定抓取邮箱、日期、金额、身份证号这类模式高度固定的字段。对纯垂直领域、文本格式相对规整的场景,规则方案甚至可以上线。但它有个致命问题:覆盖率完全取决于词表规模,遇到未收录的新实体就失效,且维护成本随时间陡增。
传统机器学习路线,更准确地说是“特征工程+CRF”路线。做法是把NER建模为序列标注问题:给每个字(或词)标上B、I、O之类的标签,B表示实体开始(Begin),I表示实体内部(Inside),O表示非实体(Outside)。输入则是一串人工设计的特征,如前一个词、后一个词、是否数字、是否大写、词性标签、词在词典中是否出现等。CRF模型可以利用标签之间的依赖约束来保证输出序列合法(如I标签不能出现在B之前)。这种方案在BERT普及前的很多年里都是工业界的主力,直到今天,当标注数据很少时,它依然是非常务实的选择。
深度学习路线里,BiLSTM-CRF是最经典的组合:BiLSTM在字级别编码双向上下文,输出每个位置属于各实体类别的得分;CRF层再对这些得分做序列级约束,保证标签转移路径合理。后来预训练模型的兴起基本取代了BiLSTM的编码部分,直接用BERT等模型提取上下文特征,再接CRF或线性分类层。效果提升非常明显,尤其在长文本、歧义性强、实体类型多的场景里,F1值能比传统方案高出很大一截。
3.3 B、I、O标注的具体写法和注意事项
这里的BIO标注格式是整个NER实践的基础,值得单独列一下。举个例子:
“张三在北京某科技公司工作。”
人名的词边界较清晰地表示为:
张 B-PER 三 I-PER 在 O 北 B-LOC 京 I-LOC 某 O 科 B-ORG 技 I-ORG 公 I-ORG 司 I-ORG 工 O 作 O我见过不少刚入门的同学在这个环节吃亏。一个常见错误是全篇只有O和B,没有I,于是实体稍长一点模型就无从判断内部关系;另一个错误是不同标注员对实体边界理解不一致,同一段文本标注出完全不同的结果,导致训练集噪声很大。所以在标注开始之前,标注规范的制定和一致性校验先于模型构建,这一步偷懒,后面模型调参再努力也补不回来。
3.4 NER工程化的典型坑与应对经验
第一类坑是标签不平衡。绝大多数文本里O类标签占比远高于实体标签,模型很容易学会“猜O”而得到很高的准确率但F1却很平庸。常见的应对方式是给损失函数里的实体类别加权,或者对O类样本做下采样。我通常还会单独监控每一类实体的F1,而不只看总体指标,因为“总体不错”很可能是被数量占比大的一类实体拉高,其他类别实际崩了。
第二类坑是嵌套实体。比如“中国工商银行北京市分行”整体是机构名,而其中“北京市”又是地名。扁平BIO标注无法同时表达两层实体,这也是很多“NER模型效果不错但总差一口气”的原因之一。常规做法是分层标注或采用阅读理解式的抽取方案(比如把“找出文中的机构名”当作问题去问答)。如果项目规模不大,我也接受先取最长实体,通过后处理规则把嵌套的低层实体再抽取一轮。
4. 工具选型:中文NLP工具箱里的实战对比与取舍
4.1 不要什么都自己造轮子,但要清楚轮子的边界
处理中文NLP基础任务,成熟的开源工具已经足够覆盖大部分场景。真正需要自己动手写模型的场景非常有限——要么是极其特殊的领域和实体类型,要么是对推理性能有苛刻要求。多数情况下,选一个合适的基础工具并做好配置,比从零训练模型性价比高得多。
我的经验是把工具分成几类。第一类是轻型分词组件,安装简单、速度极快,适合做清洗、统计、关键词抽取这类不追求精细结构的任务;第二类是一站式中文NLP工具包,一次调用就能给出分词、词性、NER、依存句法等多种结果,适合快速搭建完整文本分析管线;第三类是深度学习框架加预训练模型,适合标注数据充足、需要追求领域内SOTA效果的项目。下面这张表是我自己整理的一个粗略参考,参数指标依版本和任务会有浮动:
| 工具类型 | 典型代表 | 优势 | 需要注意的点 |
|---|---|---|---|
| 轻型分词库 | jieba | 安装简单、速度快、自定义词典方便 | NER和词性标注能力弱,长文本质量一般 |
| 一站式中文NLP工具链 | HanLP、LTP、LAC | 多任务统一输出,接口清晰 | 部分任务依赖较大模型,离线初次加载慢 |
| 跨语言工业级框架 | spaCy、Stanza | 生态完整,训练/推理流程标准化 | 中文预训练模型往往需要额外适配 |
| 预训练微调方案 | BERT家族 | 效果上限高、多任务迁移强 | 需要GPU资源、需要标注数据、推理成本高 |
4.2 落地选型时优先看三个维度
面对这么多选项,怎么定夺?我一般只看三件事。
第一是实时性需求。如果任务是离线批量处理几百万条文本,哪怕每条花几十毫秒也没问题;如果要做在线接口,延迟就必须压到几十毫秒内。此时轻量分词库或者量化后的模型是合理选择,大模型直接部署很危险。
第二是领域适配成本。你做金融公告、法律文书还是客服对话,差异极大。如果只是想先把流程跑通,那用通用工具可以;但如果实体类型高度垂直(比如“案号”“法条”“税种”),几乎必然要引入自定义词典或领域微调。这时候选型时就得考虑该工具是否支持便捷的词典扩展和模型重训。
第三是数据与算力现状。有标注数据、有GPU,那自然可以走预训练微调;如果两者都没有,传统的CRF或现成工具反而更可靠。一个反面教材是我早期做某个文本抽检项目时,一开始就上了BERT,结果因为标注数据太少、领域噪声太大,效果还没用词典加规则好,白白忙了两周。后来老老实实回到“规则+CRF”的组合,先把流程跑起来,攒够数据再升级,反而稳妥。
4.3 自定义词典的实战配置与一个经典小坑
自定义词典是让通用工具快速适配领域的最短路径。以jieba为例,词典文件的每一行大致是“词语 词频 词性”,例如:
鸿蒙应用开发 10 nz 数据中台 20 n 私域运营 15 vn加载方式也很简单:把文件放在路径里,调用时传入即可。需要注意的词频数值会直接影响分词器在歧义路径里的选择。词频太低,新词可能还是拼不过现有组合;词频设得太高,又可能把不该合并的词绑在一起。
我踩过的一个经典小坑是这样的:在某个商品评论项目里,我把“不美丽”作为自定义词加了进去,想把它当作情感短语识别。结果词频设太高,导致所有“不/美丽/的/包装”这类句子都被强制切分成“不美丽/的/包装”。表面看切对了,但后续词性标注和情感模型需要的是“不”作为否定词修饰“美丽”的独立结构,词被合并后反而丢失了这种语言学关系,标注结果变差。后来我调整策略:自定义词典只用来加真正的实体和专有术语,不轻易加短语结构。
另外一个习惯是:每次修改自定义词典后,都要在同一份评测集上重新跑一遍分词和下游任务,对比F1变化。不要凭直觉判断“加了词一定更好”,因为分词器的行为是全局的,一个词加入可能影响一大片相邻句子的切分。
5. 三件事如何协作:完整流水线与一次真实项目的复盘
5.1 流水线顺序:从字符到结构化字段
在实际项目中,分词、词性标注、NER极少彼此独立,而是按固定顺序串成一条流水线:原始文本 → 清洗与分句 → 分词 → 词性标注 → 命名实体识别 → 结构化输出。
这样排列是有原因的。分词为词性标注提供基本的词单元,词性标注又为NER提供丰富的上下文特征(比如“机构名”通常由名词短语构成,后面常跟“有限公司”“集团”这类词)。虽然现在也有联合模型,但流水线的价值在于每个环节都可以单独调试、单独替换、单独统计错误。我在一次线上问题排查中,顺着结果一路向上查,最终定位到分词环节把某个产品名切碎了,才导致下游NER把实体一分为二。如果用的是端到端黑盒模型,类似问题定位起来会困难得多。
5.2 联合模型与流水线的取舍
既然流水线错误会传导,那为什么不直接做“联合模型”一次输出所有结构?这种想法很自然,实际学术界也的确有大量把分词、词性标注、NER放在一个模型里联合建模的工作。联合模型的优势是共享表征、避免错误级联,但它的工程代价也很明显:调试不直观、某个子任务效果不好时很难单独修。
我的取舍原则是:如果你在做一个长期维护的系统,且团队成员能接受分环节排查,流水线足够可靠;如果你追求极致的整体精度且有充足标注数据与算力,再去考虑端到端联合方案。还有一种折中策略——用预训练模型给每个环节都提一层上下文向量,各环节共享同一套向量但不共用标签层。这样既保留了一定独立性,又让上游信息更丰富。
5.3 从零搭一套基础任务管线的步骤参考
如果是面对一批全新的业务文本,我的标准动作大致是这样的:
先把文本做清洗和分句,去掉无意义的HTML标签、多余空白、特殊符号,再按句号、问号、感叹号切分句子。接着选一个基础工具,先快速输出全量数据的分词和词性结果,存成带字段的表格文件,方便后续按条件筛选。然后挑出几百条典型文本,人工检查分词和词性结果,找出最常出现的错误模式,针对这些模式去更新自定义词典或规则。之后再用BIO标注一小批高质量语料去微调NER模型,或者至少先用现成NER模型跑一遍并做规则后处理。最后输出结构化字段,比如提取出“机构名+关键词+时间”这样的三元组,交给上层业务去消费。
这套流程看似朴素,但每一步都是为下一步服务的。清洗做得不好,后续所有字段都会带噪声;分句做得不好,跨句实体就被硬生生截断;评测集不建立,你连自己改没改好都不知道。我见过太多人兴致勃勃地装了一堆工具库,却把数据清洗和评测集这两件事完全跳过,最后模型F1始终上不去,还以为是算法不够先进。
5.4 一个值得长期复用的习惯:先建评测集,再调任何参数
这三个任务都属于序列标注的范畴,效果好坏要用精确率(Precision)、召回率(Recall)和F1来评价。我可以分享一个发生过很多次的经历:某次觉得分词效果很差,直接开调自定义词典,加了一堆术语,结果分词表面看着顺眼很多,但下游NER的F1反而下降了。原因正如同前面说的——新词典在改变切分路径的同时,破坏了原本稳定的特征分布。
从那之后,我给自己定了一条规矩:任何一次词典或模型改动,都要在固定的评测集上记录F1变化,不准凭感觉上线。评测集不需要很大,几百条覆盖常见模式、边界情况的句子就够,关键是固定不变、多次复用。这个习惯看起来笨,但在长期项目里节省的时间远超当初建评测集的半小时。
如果你刚开始接触这三个任务,我也想补一句朴素建议:不要急着追新模型。先用现成工具在目标文本上跑一遍,人工看看错误长什么样,再做有针对性的修正。很多问题根本不在模型能力,而在于词典、清洗和标注规范这些“琐事”上。把地基打稳,上层建筑才立得起来。我至今还保留着第一个项目的分词评测集,有时候翻出来看看,反而比看最新论文更能提醒自己基础任务的重要性。