📑 本页目录(点开跳转)
19 · 经典 NLP
⏱ 35 分钟 | ⭐⭐ 同一场赌局三个结果:正则赌赢了、文法赌赢了一半、指代消解赌输了
🎯 一句话
经典 NLP 的赌注是「语言有一套能写下来的规则」。⭐⭐ 结算下来:正则表达式完全没过时, 今天仍是文本处理的日常工具;形式文法输掉了句法分析,却在 LLM 的约束解码里换名字复活; 只有指代消解真的输了 —— 它要的是世界知识,不是规则。
和上一章一样按「当年怎么做 → 为什么输 → 哪些今天仍是对的选择」讲。
🌀 一、从头到尾只有一个敌人:歧义
The boy saw a girl with a telescope. 望远镜是男孩用的,还是女孩带的?
Jack forgot his wallet. Sam did too. Sam 忘的是自己的钱包,还是 Jack 的?
I saw two bears. Bill saw some too. Bill 看到的是同样那两只,还是另外一些?
三句话语法全对,歧义都在语法之外。⭐ 下面所有工具都在跟它搏斗,而赢的程度差别巨大。
🔤 二、正则表达式:赌赢的那一半
正则是指定文本串集合的形式语言,也是任何文本处理任务的第一个模型。
| 写法 | 含义 |
|---|---|
[wW]oodchuck · [A-Z] · [0-9] |
方括号内任选一个,可写范围 |
[^Ss] |
方括号内首位的 ^ 表否定 |
groundhog\|woodchuck |
竖线表选择 |
colou?r · oo*h! · o+h! · beg.n |
? 零或一个、* 零或多个、+ 一个或多个、. 任意字符 |
^[A-Z] · \.$ |
方括号外的 ^ 是行首锚点,$ 是行尾 |
⚠️ ^ 有两个完全不同的意思(括号内首位=否定,括号外=行首),这是第一个坑。
手推:把文本里所有的 the 找出来
这个例子是整套 NLP 评测观念的起点。测试文本
The theory of the mother, otherwise; the end. 里真正的 the 有 3 个:
| 正则 | 命中 | 问题 |
|---|---|---|
the |
5 | 漏掉大写 The;theory / mother / otherwise 里的 the 全被算进来 |
[tT]he |
6 | 大写补上了,内嵌的更多了 |
[^a-zA-Z][tT]he[^a-zA-Z] |
2 | 内嵌的排掉了,但行首的 The 前面没有字符,被漏掉 |
(^\|[^a-zA-Z])[tT]he([^a-zA-Z]\|$) |
3 ✅ | 行首行尾都兜住 |
⭐⭐ 这四步在修两类错,它们的名字你在别处会反复见到: 假阳性(不该匹配却匹配了:theory)= Type I,修它是提高精确率; 假阴性(该匹配却没匹配:句首 The)= Type II,修它是提高召回率。 ⚠️ 两者天然对抗:正则收得越紧,误收越少、漏收越多。NLP 里几乎所有指标之争都源于此。
正则还能改:s/colour/color/;圆括号捕获成编号寄存器、用 \1 引用,
s/([0-9]+)/<\1>/ 把 the 35 boxes 变成 the <35> boxes。
ELIZA(1966)那个「心理治疗师」整套就是一叠这样的替换规则:
import re
text = "The theory of the mother, otherwise; the end." # 真正的 the 只有 3 个
for p in [r"the", r"[tT]he", r"[^a-zA-Z][tT]he[^a-zA-Z]",
r"(^|[^a-zA-Z])[tT]he([^a-zA-Z]|$)"]: # ⭐ 四步逐渐收紧
print(len(re.findall(p, text)), p) # 依次 5 → 6 → 2 → 3
print(re.sub(r".* I AM (depressed|sad) .*", # ⭐ ELIZA 的一条真规则
r"WHY DO YOU THINK YOU ARE \1", "well I AM sad today"))
(本机跑过,计数就是 5 / 6 / 2 / 3,末行输出 WHY DO YOU THINK YOU ARE sad。)
📜 三、形式文法:把「合法的句子」写成规则
文法是四元组 $G = \langle V, \Sigma, R, S\rangle$:非终结符集、终结符集、产生式规则集、起始符。
规则形如 <S> ::= a b 或 <S> ::= a <S> b,含义是「S 出现的地方可以被右边替换掉」,
反复替换就生成串:$S \Rightarrow aSb \Rightarrow aaSbb \Rightarrow aaabbb$,生成的正是 $a^n b^n$。
文法按「能生成什么」分四级(Chomsky 层级),差别只在规则形状:
| 层级 | 规则形状 | 能表示 | 表示不了 |
|---|---|---|---|
| 无限制 | 两边随便 | 一切可计算的 | — |
| 上下文相关 | 右边不短于左边 | $a^n b^n c^n$ | — |
| 上下文无关 | 左边只有一个非终结符 | $a^n b^n$ | $a^n b^n c^n$ |
| 正则 | 左边一个非终结符,右边一个终结符 | $a^* b^*$ | $a^n b^n$ |
⭐ 这张表就是正则的能力边界:它在最底层,所以快、可判定、能编成状态机; 也所以它数不了配对的括号 —— 用正则解析嵌套 JSON 从原理上就不成立,不是你写得不够巧。
🌳 四、句法分析树:本章要手推的例子
讲义给了一个英语小子集文法,六条规则:
sentence --> noun_phrase, verb_phrase determiner --> [a] | [the]
noun_phrase --> determiner, noun noun --> [cat] | [mouse]
verb_phrase --> verb, noun_phrase verb --> [scares] | [hates]
最左推导 the cat scares the mouse(每步替换最左边那个非终结符):
sentence
⇒ noun_phrase verb_phrase
⇒ determiner noun verb_phrase
⇒ the noun verb_phrase
⇒ the cat verb_phrase
⇒ the cat verb noun_phrase
⇒ the cat scares noun_phrase
⇒ the cat scares determiner noun
⇒ the cat scares the noun
⇒ the cat scares the mouse
八步推完。把每步的父子关系画出来就是句法分析树:
⭐ 换成最右推导(每步替换最右边那个非终结符),路径完全不同, 但推出来是同一棵树 —— 树记录的是结构,推导顺序只是遍历它的方式。
🍴 五、歧义在文法里长什么样
用讲义里稍大一点的文法(VP → V [NP] [NP] PP*、NP → [Det] Adj* N [PP]*),
John saw Mary with a telescope 能推出两棵合法的树:PP 挂在 VP 上=John 用望远镜看;
挂在 NP 上=Mary 带着望远镜。⚠️ 两棵都严格合法,文法本身选不出哪棵对。
更糟的是数量 —— 介词短语每多一个,树的棵数按卡塔兰数涨:
| 介词短语个数 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|
| 合法句法树棵数 | 2 | 5 | 14 | 42 | 132 |
💀「I saw the man on the hill with the telescope in the park」(4 个 PP)就有 14 棵合法树, 再加两个变成 132 棵。⭐ 这不是文法写得不好,是上下文无关文法的固有性质。
🧵 六、话语结构与指代消解:撞墙的地方
真实对话里指代要跨很多句:
E: 现在把绳子接到发动机顶上。顺便问一下,你今天买汽油了吗?
A: 买了,买割草机轮子时顺手买的。我忘带油桶,所以又买了个新的。
E: 贵吗? A: 不贵,反正我也用得上。
E: 好。那个你接上了没有?
最后那句的「那个」指的是绳子 —— 中间隔着四轮完全无关的对话。
讲义把这叫层次结构:话题开一个分段(SEG),被 by the way 打断进入子分段,讲完再弹回上一层。
所以指代的候选不是「最近提到的名词」,而是「当前活跃分段里的名词」。
⚠️ 讲义原话点破要害:追踪焦点是不够的。你还得知道「割草机被偷 → Jack 缺钱 → 他在找工作」—— 这些是世界知识,不在任何一条文法规则里。
💀 这就是纯规则方法最早、也最彻底崩掉的地方。 句法可以枚举,常识不能。写一千条指代规则,第一千零一个句子照样把你打回原形, 而且每加一条都可能和已有规则冲突 —— 规则集大到某个程度就不再收敛。
📉 七、为什么输了:不是「有没有规则」,是「谁来排序」
- 覆盖率:真实文本永远有文法外的东西 —— 口语碎片、拼写错误、新词、标点乱用
- 鲁棒性:全有或全无 —— 一个词不在词表里,整棵树直接失败,没有「部分正确」
- 排序:上一节那 132 棵树,文法列得出来,却说不出哪棵更可能
⭐⭐ 第三条才是真死因。 统计方法带来的不是更好的规则,是给每种可能配一个概率: 用链式法则展开整句概率,再用马尔可夫假设只看前 $k$ 个词,
$$P(w_1 \ldots w_n) \approx \prod_i P(w_i \mid w_{i-k} \ldots w_{i-1})$$
$k=0$ 是一元模型(生成的句子完全不通),$k=1$ 是二元模型(局部像话了)。 ⚠️ N-gram 也不够 —— 语言有长距离依赖("The computer which I had just put into the machine room on the fifth floor crashed",主语和谓语隔了 14 个词)。这个洞后来由神经方法补上。
🔮 八、两条跨板块对照,和今天还活着的部分
对照一:怎么把字符串切成单位
经典 NLP 按语言学规则切:词形、词干、词元、缩写词典,成天纠结 m.p.h.、AT&T、we're、
New York 各算几个词。今天按统计切(BPE):语料里常一起出现的字节就合成一个 token,
一个词可能被切成三块,而且中英文用的是同一套规则。
⭐ 同一个问题两种答案:经典问「怎么切才对」,BPE 问「怎么切才省」。
对照二:结构放在哪里 ⭐⭐
句法树把结构画在明处(上面那张图),注意力把结构藏在权重里。 Transformer 从不产出一棵树,但注意力头确实会学到「这个介词短语挂在哪个中心词上」这类关系。
⭐⭐ 差别不在「有没有结构」,在于结构是被人声明的还是被模型统计出来的。 声明的结构可以指着讲、可以校验;统计出来的覆盖面大得多,但你指不到具体是哪一条。 这和上一章「核由人写死 vs 由数据学」是同一条分界线。
还活着的部分
| 还活着 | 今天用在哪 |
|---|---|
| 正则表达式 | 日志解析、数据清洗、PII 检测、爬虫抽取 —— ⭐ 依旧是任何文本任务的第一个模型 |
| ⭐⭐ 文法约束解码 | 让 LLM 只输出合法 JSON / SQL 靠的就是它:每步解码时用文法算出「下一个 token 的合法集合」,其余全部屏蔽。这是形式文法今天最赚钱的用法 |
| 最小编辑距离 | 拼写纠错、模糊匹配、diff:D(i,j) 由三个邻格取最小,插入/删除各 +1、替换 +2 |
| 模板抽取 | 法律合同、医疗报告这类必须解释每条结论从哪来的场景,规则仍是主力 |
⚠️ 但要诚实:开放域理解上经典方法输得很彻底。 翻译、问答、摘要、对话, 今天没有一条产品线靠手写文法跑。
🔗 这一章连到哪里
| 去哪 | 为什么 |
|---|---|
| 全景导论 03 · Tokenizer 与上下文 | ⭐ 对照一的另一半。带着「按文法切」去看 BPE,你会明白为什么今天的分词器不认识「词」这个概念 |
| 全景导论 02 · Transformer 原理 | ⭐⭐ 对照二的另一半。带着第四节那棵显式的树去看注意力权重,「结构去哪了」会有答案 |
| Kaggle 07 · 命名实体识别 | 经典方法的工程落点:NER 至今是「规则 + 词典 + 模型」混着上的地方,去看比赛里怎么配比 |
| 18 · 经典计算机视觉 | 同一场故事的视觉版,⭐ 那边的分界线和本章对照二是同一句话 |
✅ 检查点
- 「The boy saw a girl with a telescope」为什么是歧义句?改文法能解决吗?介词短语再多几个,合法树的棵数怎么涨?
- 正则里的
^有哪两个完全不同的意思? - 找
the的四步逼近各命中几个?假阳性和假阴性分别对应哪个指标?为什么天然对抗? - 正则文法连 $a^n b^n$ 都表示不了 —— 这对「用正则解析嵌套 JSON」意味着什么?
the cat scares the mouse的最左推导几步推完?最右推导得到的是同一棵树吗?- 为什么说指代消解是纯规则方法崩得最彻底的地方?
- 经典 NLP 输在哪三条上?哪一条才是真死因?
- 举三块今天仍活着的经典 NLP 技术,哪一块在 LLM 里换名字继续跑?
👀 答案
with a telescope可挂在动词上(John 用望远镜)也可挂在名词上(Mary 带着望远镜),两种结构都严格合法。⚠️ 改文法解决不了 —— 文法列得出所有合法树,却选不出哪棵对。棵数按卡塔兰数涨:2 个 PP → 2 棵,3 → 5,4 → 14,6 → 132,⭐ 这是上下文无关文法的固有性质。- 方括号内首位是否定(
[^Ss]);方括号之外是行首锚点(^[A-Z])。 - 5 → 6 → 2 → 3(第三步漏掉行首那个 The,因为它前面没有字符)。假阳性 = Type I,修它提高精确率;假阴性 = Type II,修它提高召回率。⚠️ 对抗是因为收得越紧误收越少、漏收越多。
- 从原理上不成立,不是写得不够巧 —— 正则在 Chomsky 层级最底层,数不了配对的括号,嵌套 JSON 至少要上下文无关的能力。⭐ 它换来的是快、可判定、能编成状态机。
- 八步。⭐ 最右推导路径完全不同,但得到同一棵树 —— 树记录结构,推导顺序只是遍历它的方式。
- 它要的是世界知识不是规则:例子里「那个」指绳子,中间隔了四轮无关对话;还得知道「割草机被偷 → 缺钱 → 找工作」。⚠️ 讲义原话是追踪焦点不够。💀 句法可以枚举,常识不能。
- 覆盖率、鲁棒性(一个生词整棵树就失败)、排序(列得出 132 棵却说不出哪棵更可能)。⭐⭐ 第三条是真死因:统计给的不是更好的规则,是概率(链式法则 + 马尔可夫假设)。
- 正则(日志/清洗/PII)、最小编辑距离(纠错、模糊匹配、diff)、模板抽取(法律医疗)。⭐⭐ 换名字继续跑的是形式文法 —— 让 LLM 只输出合法 JSON / SQL 的约束解码,本质就是每步用文法算出下一个 token 的合法集合、屏蔽其余。
🛑 可以停在这里
⚡ 走神救援
赌注是「语言有能写下来的规则」,⭐⭐ 结算:正则赢、文法赢一半、指代消解输。敌人只有歧义,而那些句子语法全对。⭐正则是任何文本任务的第一个模型;⚠️ 方括号内首位的
^是否定、括号外的是行首锚点,同一符号两个意思。找 the 四步命中 5 → 6 → 2 → 3(答案 3):前两步补召回、后两步提精确率,⭐⭐ 假阳性=Type I、假阴性=Type II,天然对抗。ELIZA(1966)整套就是一叠s///规则。文法 $G=\langle V,\Sigma,R,S\rangle$,S ⇒ aSb ⇒ aaSbb ⇒ aaabbb生成 $a^nb^n$;Chomsky 四级里上下文无关能 $a^nb^n$ 不能 $a^nb^nc^n$,正则连 $a^nb^n$ 都不能 —— ⭐ 用正则解析嵌套 JSON 原理上就不成立。⭐手推:六条规则把the cat scares the mouse八步推完,最左最右推导路径不同但同一棵树。⚠️John saw Mary with a telescope两棵合法树(PP 挂 VP 还是挂 NP),棵数按卡塔兰数涨:4 个介词短语 14 棵、6 个 132 棵,文法自己选不出哪棵对。💀指代消解崩得最彻底:「那个」指绳子,中间隔了四轮无关对话,还得知道「割草机被偷→缺钱→找工作」这类世界知识(讲义原话「追踪焦点不够」)—— 句法可以枚举,常识不能。⭐⭐ 三条败因覆盖率 / 鲁棒性 / 排序,第三条才是真死因:统计给的不是更好的规则,是概率。⭐⭐ 两条对照:经典问「怎么切才对」、BPE 问「怎么切才省」;句法树把结构画在明处、注意力把结构藏在权重里 —— 差别不在有没有结构,在于结构是被声明的还是被统计出来的。⭐ 还活着:正则、最小编辑距离、模板抽取,以及 ⭐⭐ 文法约束解码(让 LLM 只输出合法 JSON/SQL,每步用文法算出下一个 token 的合法集合再屏蔽其余)。
下一节 👉 20-实战与挑战项目.md
去那里的理由:前面十九章的方法你已经全见过一遍,但看懂和写出来是两回事。 最后一章是菜单式的:搜索、博弈、CSP、视觉、语言各给一个能在一两天内做完、 不需要 GPU 也不需要数据集的项目 —— 这正是本板块相对全站其他板块最大的便宜。