第 三 章

词法分析

字落成词,词各有类

一、词法分析三件事

词法分析是 NLP 流水线的第一道工序,它把原始字符串加工成更有结构的语言单位,主要包含三个子任务:

分词
Word Segmentation
把句子切分成词语序列:研究 生命 的 起源。
词性
POS Tagging
为每个词标注名词、动词、形容词等词性。
实体
NER
识别出人名、地名、机构名等命名实体。

英文等印欧语言天然有空格分词,词法处理主要是词干提取(stemming)与词形还原(lemmatization);而中文词与词之间没有显式边界,分词成了中文 NLP 的头号基础任务。

二、中文分词为何难

  • 边界歧义:「结合成分子」可切为「结合/成/分子」或「结婚/成分/子」;「从小学电脑」→「从小/学/电脑」还是「从/小学/电脑」?
  • 未登录词(OOV):新词层出不穷——「绝绝子」「二次元」「特种兵式旅游」,词典永远滞后于语言。
  • 切分歧义与领域相关:同一句话在不同领域的正确切分可能不同,如医疗文本中的「肺炎/支原体」。
分词之难,不在切,而在「何处不该切」。

三、分词方法演进

1. 基于词典:最大匹配法

从句子一端开始,按词典中最长词进行贪婪匹配。正向最大匹配(FMM)从左向右,反向最大匹配(BMM)从右向左。

  1. 取当前位置开始、长度不超过词典最大词长(如 5)的子串;
  2. 查词典:命中则切出该词,指针前移该词长度;
  3. 未命中则切出单字,指针前移一位,循环直至句末。

优点是简单快速;缺点是严重依赖词典、无法处理歧义与新词。本章交互演示实现的就是 FMM。

2. 基于统计:HMM 与 CRF

把分词转化为字的序列标注问题:每个字标注 B(词首)、M(词中)、E(词尾)、S(单字成词)。

自 然 语 言 处 理 很 重 要
B  M  M  E  B  E  S  B  E

HMM(隐马尔可夫模型)用字的转移概率和发射概率做 Viterbi 解码;CRF(条件随机场)进一步加入任意特征、全局归一,是深度学习普及前工业界的王者。jieba 的「搜索引擎模式」之外,其未登录词识别正基于 HMM。

3. 基于深度学习

BiLSTM-CRF 用双向 LSTM 提取上下文特征、CRF 约束标签合法性;如今则普遍使用 BERT 类预训练模型 + 微调,在多个中文分词与 NER 基准上取得最佳成绩。

四、jieba 分词实战

jieba 支持三种分词模式:

  • 精确模式:最精确地切开,适合文本分析;
  • 全模式:把所有可能成词的词语都扫出来,速度快但有冗余;
  • 搜索引擎模式:在精确模式基础上对长词再切分,提高召回率,适合倒排索引。
python · jieba_basic.pyimport jieba

sent = "他来到北京清华大学研究所参观自然语言处理实验室"

print(jieba.lcut(sent, cut_all=True))
# 全模式:['他', '来到', '北京', '清华', '清华大学', '华大', '大学', ...]

print(jieba.lcut(sent, cut_all=False))
# 精确模式:['他', '来到', '北京', '清华大学', '研究所', ...]

print(jieba.lcut_for_search(sent))
# 搜索引擎模式:长词会被二次切分

加载自定义词典,解决领域词

jieba.load_userdict("mydict.txt")
# 词典每行三列:词语 词频 词性,后两列可省略
# 生成式人工智能 100 n
# 大语言模型 100 n

# 也可在代码中动态增删
jieba.add_word("大语言模型")
jieba.del_word("自定义词")
分词结果直接决定后续任务质量。做项目时,先用 jieba 切一批样本人工检查,把切错的领域词整理进自定义词典,往往是性价比最高的优化手段。

五、词性标注

词性标注(Part-of-Speech Tagging)为每个词打上词类标记:名词 n、动词 v、形容词 a、副词 d、数词 m、量词 q……它能帮助过滤停用词(只保留名词、动词)、辅助句法分析。

python · 词性标注import jieba.posseg as pseg

for word, flag in pseg.cut("小明在北京大学学习自然语言处理"):
    print(f"{word}/{flag}", end="  ")
# 小明/nr  在/p  北京大学/nt  学习/v  自然语言处理/l

常用词性标记(jieba 采用兼容 ICTCLAS 的标记集):

标记含义标记含义
n普通名词v动词
nr人名a形容词
ns地名d副词
nt机构团体名m / q数词 / 量词
nz其他专名p / u介词 / 助词

六、命名实体识别

命名实体识别(Named Entity Recognition, NER)抽取文本中的专有名词并归类,最常见的三大类是:

  • PER 人名:小明、屠呦呦;
  • LOC 地名:北京、长江;
  • ORG 机构名:北京大学、联合国;
  • 垂直领域还可扩展时间、日期、货币、药物名、手术名等。

NER 是问答机器人槽位抽取(如「订一张明天去上海的票」中识别时间与目的地)、知识图谱构建的前置技术。用 HanLP 只需几行:

python · HanLP 命名实体识别import hanlp

tagger = hanlp.load(hanlp.pretrained.ner.MSRA_NER_BERT_BASE_ZH)
print(tagger([["小明", "在", "北京", "学习", "人工智能"]]))
# [[('小明', 'PER', 0, 1), ('北京', 'LOC', 2, 3)]]

七、评价指标与交互演示

序列任务通常用精确率 Precision、召回率 Recall 与 F1 值评价(以词为单位统计预测与标准答案的边界是否一致):

Precision = 切对的词数 / 系统切出的词数
Recall    = 切对的词数 / 标准答案中的词数
F1 = 2 × P × R / (P + R)

F1 是精确率与召回率的调和平均,是分词与 NER 的核心指标。

动手一试:正向最大匹配分词

下面演示使用与第三章方法一致的 FMM 算法(内置小型词典)。试试包含词典词的句子,再故意写一个新词,观察未登录词如何退化为单字:

分词实验台FMM · 最大词长 5
注意:标点符号会被单独切出;金色胶囊为词典命中词,红色为未登录单字。真实系统(jieba)还会用 HMM 等统计模型识别新词,效果远优于纯词典法。