
做NLP相关项目也有几年时间了从最开始用正则表达式硬匹配到后来用统计模型再到现在折腾预训练模型绕了一大圈发现不管上层玩法怎么变底层的分词、词性标注、命名实体识别这些核心任务始终是绕不开的基本功。很多刚入门的朋友总觉得这些任务太老、太简单一上来就直奔大模型结果真做落地项目时被OOV未登录词、标注体系不一致、边界切分错误这些小问题折腾到怀疑人生。这篇内容我就把这几个NLP核心任务从头到尾梳理一遍讲讲它们各自在解决什么问题、互相之间是什么关系、常用的方案有哪些以及我在真实项目里踩过的坑和排查思路。不管你是刚开始接触NLP还是已经跑过几个模型但想补一补底层知识这篇内容应该都能给你一些实在的参考。1. 任务全景这三个基础任务到底在解决什么问题1.1 从一句话到结构化信息的完整链路先回到一个最朴素的场景你拿到一句中文文本比如武汉市长江大桥欢迎你人眼一看就知道这是个地名加欢迎语但计算机拿到的是没有任何分隔的字符序列。分词要做的就是把字符序列切成有意义的词语单元词性标注则给每个词打上名词、动词、形容词这类语法标签命名实体识别更进一步从词序列里识别出人名、地名、组织机构名等实体及其类型。这三个任务在逻辑上是从低到高的递进关系。分词是前置基础词性标注通常建立在分词结果之上命名实体识别又往往依赖词性和句法信息。但这里有个容易忽略的点它们并不是严格意义上必须串联的。实际工程里命名实体识别完全可以跳过显式分词直接在字符序列上做序列标注这一点稍后会展开讲。1.2 为什么这三个任务被认为是核心所谓核心任务是因为大量上层NLP应用都建立在这些基础能力之上。机器翻译需要先分词再对齐词序情感分析需要提取评价对象和情感词这本质上依赖词性和实体识别信息抽取系统更是直接以命名实体识别作为关键一环知识图谱的实体链接、关系抽取也离不开这些底层标注。搜索引擎的Query理解、智能客服的意图识别、法律文书的要素抽取各行各业落地时都会碰到这些基础组件。从这个角度看不是老技术不重要而是这些任务作为整个NLP技术栈的基础设施早已渗透到几乎所有应用场景中。理解它们的原理和实现对做上层应用、排查问题、评估模型都有直接影响。2. 分词看起来简单细节里全是学问2.1 分词难点歧义、未登录词与规范问题分词是中文NLP的第一道工序。相比英文天然用空格分词中文没有边界标记所以分词问题本质上是在连续字符序列中找出最优的词边界组合。实际做分词时会遇到三类主要难点。第一类是交集型歧义比如研究生命科学既可以分成研究/生命/科学也可以被误分成研究生/命/科学。这一类歧义需要依赖上下文甚至外部知识才能消解。第二类是组合型歧义比如中国产品质量里中国产品和产品质量组合关系到底切成中国/产品/质量还是中国/产品质量不同词表和语境下结论不同。第三类是未登录词问题主要指人名、地名、机构名、专有名词和新词网络语比如李狗蛋赛博朋克多巴胺穿搭。这些词不在词表中纯词典方法基本必挂。另外还有个容易被忽视的问题分词规范不统一。同一个句子学术界和工业界常用分词工具结果可能不一致比如重庆市有的工具切成重庆市有的切成重庆/市。这带来一个实际后果下游模型的训练数据如果用了不同规范的分词结果性能会受影响。所以做项目时一定要固定分词工具和词表版本不能今天用A工具、明天用B工具。提示分词结果的一致性在生产环境中比绝对准确率更重要。模型训练和线上推理必须使用完全相同版本的分词器。2.2 主流分词算法从词典匹配到序列标注分词算法大体分三类。第一类是词典匹配法包括正向最大匹配、逆向最大匹配、双向最大匹配和最短路径分词。这类方法速度快、实现简单但依赖词典质量对未登录词基本无能为力。我在早期做搜索词分析时用过基于词典的双向最大匹配处理常规文本问题不大一遇到新词就露馅。第二类是基于统计的序列标注方法把分词建模为BMES四类标签的标注任务B表示词首M表示词中E表示词尾S表示单字成词。然后用条件随机场CRF或者早期的最大熵模型来训练。统计方法能较好处理未登录词因为它不是死板地查词典而是通过字符特征和上下文特征来预测边界。第三类是当前工业界最常用的方案基于预训练模型的序列标注。BERT加一个CRF层做中文分词效果通常远好于传统方法。这类方法把每个字表示成语义丰富的向量再通过神经网络解码对歧义词的消解能力大幅提升。2.3 实操配置以jieba和HanLP为参考工程上我用了很久的轻量方案是Python生态里的jieba但必须说清楚它的优缺点。jieba支持精确模式、全模式和搜索引擎模式内置前缀词典同时基于HMM模型识别未登录词。实际用的时候我一般这么配置# 精确模式适合文本分析场景 import jieba seg_list jieba.cut(武汉市长江大桥欢迎你, cut_allFalse) print(/.join(seg_list)) # 搜索引擎模式适合构建检索用的分词索引 seg_list jieba.cut_for_search(武汉市长江大桥欢迎你) print(/.join(seg_list)) # 自定义词典解决领域术语被错误切分的问题 jieba.load_userdict(domain_words.txt)自定义词典里的每一行格式是词语 词频 词性比如多巴胺穿搭 10 n。这个词频不是随便填的它影响分词时的DAG路径概率计算通常给一个明显高于常见词的数值比如10就能保证优先合并。但需要注意词频设得过高可能导致本不该合并的邻接词被错误合并需要实测调整。如果项目对分词质量要求更高尤其是需要同时输出词性标注和命名实体识别的场景我更推荐用HanLP。HanLP提供的感知机分词、CRF分词和基于BERT的分词在准确率上比jieba高不少代价是模型体积和速度。具体怎么选取决于你的场景是追求吞吐还是追求精度。3. 词性标注给每个词贴上语法身份3.1 词性标注的本质与难点词性标注的任务是给分词后的每个词打上词性标签比如名词、动词、形容词、副词、介词、连词等。这个任务看起来是查词典就能解决实际上远没有这么简单。难点主要在兼类词上一个词在不同上下文里可能呈现完全不同的词性。最经典的例子是利用利用业余时间里是动词合理利用里是名词。再如锁把门锁上和买了一把锁前者是动词、后者是名词。这类词在中文里大量存在仅靠词典查词性根本行不通必须借助上下文信息。词性标注对下游任务直接影响不小。在句法分析中词性序列决定句法树的生成路径在信息抽取中动词和名词的识别有助于判断事件结构和实体属性在情感分析中形容词和副词往往承载情感极性信息。我在做舆情分析项目时就有过切身感受如果形容词被错标成名词情感得分计算会直接出错。3.2 词性标注的主流方法HMM与CRF传统词性标注的主流方法是HMM隐马尔可夫模型和CRF。HMM的核心假设是当前词性只依赖上一个词性转移概率当前词只依赖当前词性发射概率。用维特比算法可以解码出最优词性序列。HMM建模简单、计算高效但因其假设过强对复杂上下文的建模能力有限。CRF则是一个判别式模型不要求独立的生成假设可以直接在观测序列上定义特征函数。比如可以定义特征当前词是的且上一个词性为动词则当前词性倾向于助词。这类特征工程灵活性远高于HMM。在传统方法时代CRF普遍比HMM准确率高出2到3个百分点尤其是在复杂语境和长句子上。到了深度学习时代词性标注通常直接做成序列标注任务。BiLSTM加CRF层是最经典的组合近年来直接使用BERT加上Softmax或CRF解码也成了标配。词性标注实际上已经不需要单独训练模型往往与分词、实体识别联合建模或直接使用大模型处理。3.3 中文词性标注的标注体系问题做词性标注时有一个隐藏的坑标注体系不统一。中文比较常见的词性标注规范有北大词性标注集包含约26个基本词性类别还有计算所词性标注集类别更细包含40多个标签。不同词性标注工具默认使用的标签集合并不一致。举例来说对于小明这个词北大标注集可能标为nr人名而计算所标注集可能细分nr为nrf姓或nrg名。如果你拿两份不同标注规范的数据集混合训练模型会非常困惑因为同样的词在不同数据里的标签不一样。所以实际项目中我强烈建议直接用工具默认的标注体系比如jieba用的是计算所标注集LTP用的是863标注集不要自己混搭。还有一个实战经验如果训练好的词性标注模型在特定领域文本上表现不佳不要急着换模型结构先检查训练语料领域是否匹配。我遇到过把新闻语料训练的模型直接用到法律文书上词性准确率明显下滑的情况后来加入领域语料微调后恢复到了正常水平。领域适配对词性标注这类序列标注任务的影响比很多人想象的要大。4. 命名实体识别从文本里抽取出谁、哪里、什么组织4.1 NER任务定义与标签体系命名实体识别英文简称NER目标是从文本中识别出具有特定意义的实体并标注其类别。常规的实体类别包括人名PER、地名LOC、组织机构名ORG、时间TIME、日期DATE、数字MONEY、PERCENT等更细的还有药物名、疾病名、产品名、法律条款等。NER通常建模为序列标注问题。在标注数据时最常用的标签体系是BIO体系B-PER表示人名的开始I-PER表示人名的中间或结尾O表示非实体。另一种是BIOES体系多了E实体结尾和S单个字符实体标签对实体边界的建模更加精确在传统CRF模型中经常能带来准召率的提升。为什么实体识别比词性标注更复杂因为实体边界和类型同时需要预测。比如北京大学在北京大学举办了校庆中是组织机构在北京大学附近的地铁站里指的可能是地点。这类嵌套和歧义问题在实际业务数据中非常常见。另外中文人名、地名没有形态变化不像英文人名有首字母大写这样的强特征这在很大程度上增加了识别难度。4.2 BiLSTM-CRF经典方案的完整逻辑深度学习时代NER任务最经典的方案是BiLSTM-CRF。它由三部分组成嵌入层得到每个字符或词的语义向量双向LSTM编码上下文信息CRF层负责输出全局最优的标签序列。为什么在序列标注里用CRF做解码而不是直接用Softmax因为Softmax对每个位置的标签独立做决策完全没有考虑标签之间的约束关系。在NER任务里标签之间是有强约束的比如B-PER后面只能跟I-PER或O不可能直接跟B-LOC。CRF层能够学习这些转移约束最终输出全局最优序列。我在实际实验中对比过同样的BiLSTM编码器换成CRF解码后F1值一般能提升2到5个百分点。用简洁的方式理解BiLSTM给每个字打一个感觉上像什么标签的分数CRF再根据相邻标签之间合不合语法做一次整体校正。打个生活中的比方——你和朋友一起出门每个人先选出各自想去的饭店但不一定协调最后讨论一下大家的选择排除掉冲突和时间安排不上的组合才定下整体路线。4.3 基于预训练模型的NER实现要点到了BERT时代NER的主流做法变成预训练模型微调。流程清晰加载BERT模型取每个token的隐层表示接一个线性层对每个token预测标签可选接CRF层。相比BiLSTM-CRFBERT-CRF在大多数评测集上有明显提升尤其对于复杂语义边界的实体。工程上有一个细节值得注意BERT的分词器WordPiece会把一个词拆成多个子词因此标签需要对齐到子词级别。常见做法是让标签只作用在子词的第一个token上其余子词标为X或者在loss中mask掉。这一步做不好训练出来的模型边界预测会非常混乱。另一个工程细节是实体重叠问题。比如文本中同时存在苹果这个PER和组织机构名苹果公司。一般的BIO标注无法表达重叠实体。这时候通常要靠标注策略取舍要么优先保留完整实体标注合并处理要么使用嵌套NER方法把问题升级为多层序列标注或基于span的抽取。我刚做NER时完全没意识到这个坑直到用市面上某一标注工具检查数据时才发现大量重叠实体被直接丢掉了。4.4 中文NER的边界难题与数据标注策略在实际数据处理中中文NER最大的问题不是模型选型而是标注质量和标注一致性。因为NER人工标注的难度比分类任务高很多标注员对于实体边界常常有不同理解。例如北京市朝阳区可以标注为一个整体地名也可以拆成北京市和朝阳区两个地名。不同标注员背景不同标准不同很容易产生标注不一致。这在很大程度上影响模型训练效果。我在组织标注任务的时候一般会要求标注团队先看一份非常详细的标注规范并且先标注100条数据试跑一遍一致性检验计算标注员之间的Kappa系数。如果一致性太低就需要重新对齐标注规范否则后续的模型训练就是垃圾进、垃圾出。数据处理方面的另一个建议是进行弱实体清洗。正则表达式先大体抽取明显的日期、时间、金额、电话等实体把它们漏标的比例降到最低。因为BERT这类模型对噪声标签有一定容忍度但如果大量简单实体都漏标了模型会学到这些模式不是实体的错误信号后续预测自然就会漏掉。5. 三者的协同使用与预训练模型时代的定位5.1 三个任务在真实业务中的典型配合方式在实际业务系统里这三个任务很少孤立运行。一个典型的新闻信息抽取流程大致是先分词再对每个词做词性标注然后根据词性和词边界规则抽取候选实体名词最后用NER模型对候选实体做类型分类和边界修正。这种规则粗筛加模型精排的思路在工业界比较常见既能控制速度又能保证一定精度。另一个典型场景是知识图谱构建。实体识别负责抽取出实体词性标注辅助判断实体在句子中充当的成分比如主语还是宾语而分词质量直接影响实体边界是否完整。我曾参与过一个某领域的知识图谱项目最后发现大量实体错误不是NER模型造成的而是上游分词把实体词组强行切碎了。比如某个地名被切成某省/某市/某县NER模型在字级别上虽然尽力拼回但受限于训练数据的标注规范还是出现大量边界缺失。后来解决方案是在NER之前把不可分割的领域词加入分词自定义词典问题立刻缓解了大半。5.2 现在的BERT时代还需要分词与词性标注吗这个问题几乎每隔一段时间就有人问。我的观点是预训练模型确实让这些任务不再像以前那样必须显式串联成pipeline但并不意味着它们消失了。BERT类模型由于用了WordPiece或字级别的分词其实本质上跳过了中文词边界这个显式步骤直接在字符或子词级别建模。很多情况下直接在字级别做NER效果并不比在词级别做差因为字级别的表示天然回避了上游分词错误传播问题。这也是为什么很多现代的NER系统直接以字为单位运行。但词性标注和分词在几个场景中依然有不可替代的价值。一是规则系统和线上轻量服务不需要跑一个巨大的模型用jieba加规则就能快速完成实时文本清洗。二是低资源场景没有足够算力部署大模型时传统CRF仍然是高效可行的选择。三是对可解释性有要求的场景比如需要明确告诉你这个词为什么被识别为地名词性和边界信息能给出更直观的证据。所以更准确的说法是这些核心任务从必须显式执行的流程步骤变成了一部分被模型隐式完成一部分在特定场景下仍然显式使用。理解了底层逻辑才能针对具体场景做合理的技术选型。6. 常见问题与排查技巧实录6.1 分词结果频繁变动的排查思路有段时间我遇到一个线上bug完全相同的句子分词结果一会儿变、一会儿不变。排查后发现是自定义词典和默认词典存在热更新机制词典文件被后台流程替换了而分词器缓存没有同步失效。这类问题在工程里非常隐蔽。另一个常见问题是多线程环境下分词状态不一致。有些分词工具对象不是线程安全的如果多个线程共用同一个实例且并发调用内部缓存可能被污染导致切分结果异常。排查方式很简单压测时并发调用分词接口对比串行结果是否一致。解决方案是改用线程局部变量或者每线程单独初始化实例。6.2 词性标注错误集中在哪些模式如果词性标注在特定类别上准确率明显偏低通常先检查是不是标注意式不统一。实际项目里最常见的问题是专有名词被标成普通名词。比如公司名某某科技有限公司常被拆成某某/NN 科技/NN 有限/JJ 公司/NN其中有限被标成形容词其实是合理的但如果你希望它作为公司名称整体出现就需要引入实体词典。另一个高频错误是助词的了着等被误标。这类虚词在中文里用法极为灵活尤其是了既可以作为动态助词也可以作为语气词。传统模型特征如果不包含上下文从句信息很容易标错。遇到这类问题比较直接的办法是检查训练数据中这类虚词的标签分布情况必要时人工修正一部分虚词标签后再重训。6.3 NER实体漏召回与边界不完整NER项目上线后最常见的badcase是实体漏召回尤其是长尾实体比如生僻人名、新型机构名、混合中英文实体。漏召回的原因通常是训练数据里这类实体出现的次数太少模型没有学到足够的特征。缓解方法包括收集更多包含这类实体的文本做数据增强、用远程监督方式借助外部知识库自动生成训练数据、或者在模型后接一层词典匹配规则兜底。边界不完整是另一个高频问题。比如清华大学计算机系只识别出清华大学丢掉了计算机系。如果业务中需要完整字段仅仅靠CRF解码很难保证边界完美。经验做法是引入基于规则的后处理模块比如实体后接公司系大学研究院等强后缀词时自动扩展边界。这种方式简单粗暴但在工业项目中非常有效。我把这几年遇到的典型问题和排查思路整理成一张速查表方便实际排查时对照现象可能原因排查方向常用解法新词/专名被切碎词典缺少领域词查看分词DAG结果添加自定义词典词频调高分词结果不稳定词典热更新或线程安全问题检查词典版本、并发压测固定词表版本、隔离实例词性标注在动词/名词上混乱兼类词训练数据不足统计标签混淆矩阵补充领域语料做微调的/了等虚词标签不稳定特征缺少上下文信息分析虚词上下文特征调整标注规范、增加模板特征NER漏召回长尾实体数据中实体覆盖不足统计实体类别频率远程监督、规则兜底实体边界少词/多词标注边界不一致做标注一致性校验明确标注边界规范、后缀扩展规则BERT子词标签错位标签对齐逻辑错误检查tokenizer输出标签对齐到首子词其余mask注意排查序列标注问题时先用简单统计分析定位在哪些标签上出错、哪些上下文条件下出错再决定是改数据、改特征还是改模型结构。不要上来就重训模型那样大概率浪费算力还定位不了问题。结尾做了这么久的NLP底层任务我最大的感受是这些任务看起来入门门槛不高但真正做精做稳非常考验对数据质量、标注细节、误差传播和工程部署的理解。分词分错一个边界词性标注就可能跟着错NER实体自然也就抽不准这种连锁反应在完整pipeline中会被不断放大。最后再分享一个小技巧在搭建任何NLP处理pipeline时先做一个小样本的端到端可视化校对把文本、分词结果、词性标注、NER标签一层层打印出来比对。找一个明白业务的人在excel里过一遍往往能比调模型参数更快地发现系统瓶颈在哪里。工具和模型可以迭代但对数据细节反复打磨这件事任何时代都值得。如果你正在做分词、词性标注或命名实体识别的项目建议从一个小规模的标注集开始把每个环节的badcase记录下来再决定下一步是加数据、调参数还是换模型。这个流程虽然看着朴素却是最稳妥的成长路径。