人工智能:现代方法读书笔记(二十四)

第24章 自然语言处理

摘要:本章系统介绍自然语言处理(NLP)的经典符号与统计方法。内容沿"从字符到意义"的处理管线展开:先建立语料、词汇、语法、语义与歧义等核心概念;随后深入讲解 N 元语法语言模型及其平滑技术、基于 HMM 与 Viterbi 的词性标注、PCFG 与 CYK 解析、移进-归约依存解析、语法制导的组合语义、指代消解、信息抽取与机器翻译基础;最后讨论这些经典方法与 LLM 时代深度学习范式的关系。核心立场是:纯符号方法在真实语料上鲁棒性不足,统计学习不可或缺,但语法与语义的结构化视角仍是理解语言的关键抽象。

对应《人工智能:现代方法(第4版)》Chapter 24 — Natural Language Processing
本章是"符号/统计范式"的 NLP 总览,第25章则转向深度学习范式。两章应对照阅读。


1. 章节概述

自然语言处理(Natural Language Processing,NLP)研究如何让计算机理解、生成和使用人类语言。与形式语言(formal language)不同,自然语言具有歧义性(ambiguity)冗余性演化性上下文依赖性,因此不能用编译器式的确定性方法处理,必须引入概率模型学习
本章的组织逻辑是一条"从字符到意义"的处理管线(pipeline):

原始文本
  → 分词 / 词法分析 (tokenization, morphology)
  → 词性标注(POS tagging)
  → 句法分析(parsing: PCFG + CYK / shift-reduce)
  → 语义分析(semantic interpretation,λ-演算 / 语义角色标注)
  → 篇章处理(指代消解 coreference,话语结构)
  → 应用(信息抽取 IE、问答 QA、机器翻译 MT)

本章的三条主线:

  1. 语言模型(language model):用概率刻画"哪些词序列更像自然语言"。N 元语法(N-gram)是最基础的形式,是语音识别、拼写纠错、机器翻译的公共底座。
  2. 语法(grammar):用上下文无关文法(CFG)及其概率扩展 PCFG 刻画句子的层级结构,用 CYK、移进-归约等算法做解析(parsing)。
  3. 意义(meaning):把句法结构映射为逻辑形式或语义角色框架,并解决跨句子的指代问题。

AIMA 第4版的重要立场:纯符号方法(手写文法)在真实语料上覆盖率与鲁棒性不足,统计学习是必需的;但语法与语义的结构化视角依然是理解语言的关键抽象——即使在深度学习时代,它仍然是评测、可解释性与数据构造的基础。


2. 关键概念与定义

2.1 语料与词汇层

概念定义说明
语料库(corpus)大规模真实文本集合统计 NLP 的经验来源,如 Penn Treebank、Brown Corpus
词例 / 词型(token / type)token 是文本中出现的每一个词的实例;type 是不同词的种类“the cat saw the dog” 有 5 tokens、4 types
分词(tokenization / word segmentation)把字符流切分为 token英文靠空格+规则处理标点、缩写;中文/日文无空格,需模型切分
形态学(morphology)研究词的内部结构词干(stem)+ 词缀(affix);屈折(inflection: run/running)与派生(derivation: happy/happiness)
词干提取 / 词形还原(stemming / lemmatization)归一化为词干或词典形stemming 是启发式截断(Porter 算法),lemmatization 依赖词典与词性
子词切分(subword, BPE/WordPiece)把罕见词切为高频子片段解决 OOV(out-of-vocabulary),是第 25 章预训练模型的标配
齐普夫定律(Zipf’s law)词频 fff 与词频排名 rrr 满足 f∝1/rf \propto 1/rf1/r解释了为何总有大量低频词,必须做平滑与子词处理

2.2 语法层

概念定义
词性(Part of Speech, POS)词的语法类别:名词 N、动词 V、形容词 Adj、限定词 Det、介词 P 等;Penn Treebank 用 45 个细粒度标签(NN/NNS/VB/VBD/…)
上下文无关文法(CFG)四元组 G=(V,Σ,R,S)G=(V, \Sigma, R, S)G=(V,Σ,R,S):非终结符集、终结符集、产生式规则集、起始符
概率上下文无关文法(PCFG)每条规则附一个概率,且同一左部规则概率和为 1
短语结构树(constituency tree)句子的层级括号结构,节点是短语(NP/VP/PP)
依存结构(dependency tree)词与词之间的有向"中心词—修饰词"关系,更适合自由语序语言
乔姆斯基范式(CNF)所有规则形如 A→B CA \to B\,CABCA→wA \to wAw,CYK 算法的前提
词汇化(lexicalization)给非终结符附上中心词(head),如 VP(ate),缓解 PCFG 的独立性假设过强问题

2.3 语义与篇章层

概念定义
语义分析(Semantic Interpretation)把句子映射为逻辑形式(logical form),如一阶逻辑或 λ-表达式
组合性原则(Principle of Compositionality)整体意义由部分意义及其组合方式决定;是"语法制导翻译"的理论依据
量化辖域歧义(Quantifier Scope Ambiguity)“Every man loves a woman” 的两种读法
语义角色标注(SRL)标注谓词的论元角色:Agent(施事)、Patient(受事)、Instrument(工具)、Location 等;资源有 PropBank(ARG0/ARG1…)与 FrameNet
指代消解(Coreference Resolution)判定不同提及(mention)是否指向同一实体
照应语(Anaphora)回指前文的表达(代词 he/it/this)
语用学(pragmatics)依赖说话场景的意义:指示语(I/here/now)、言外之意、言语行为(speech act)
信息抽取(IE)从非结构化文本抽出结构化记录:NER、关系抽取、事件抽取

2.4 歧义的层次(本章的核心难点)

层次例子说明
词法歧义“银行”(bank:河岸 / 金融机构)一词多义,需词义消歧(WSD)
词性歧义“book” 可为 N 或 VPOS tagging 要解决
句法歧义“I saw the man with the telescope”PP 附着歧义(PP-attachment)
语义/辖域歧义“Every student read a book”是同一本还是各自一本
指代歧义“The council refused the demonstrators a permit because they feared violence.”they 指 council(Winograd Schema 式挑战)
语用歧义“Can you pass the salt?”字面是能力提问,实际是请求

关键洞察:歧义不是缺陷而是自然语言的效率特征——人类靠上下文与世界知识消歧。因此 NLP 的本质是在语言模型 + 世界知识下做最大后验推断
I^=arg⁡max⁡IP(I∣words)=arg⁡max⁡IP(words∣I) P(I)\hat{I} = \arg\max_{I} P(I \mid \text{words}) = \arg\max_{I} P(\text{words}\mid I)\,P(I)I^=argImaxP(Iwords)=argImaxP(wordsI)P(I)


Python 实战:基于规则的 PP 附着歧义消解

下面用约 30 行代码演示一个简单的规则式消歧器:给定句子 “I saw the man with the telescope”,通过判断介词短语中心词(telescope 是否为可食用/可携带物品)输出两种解析倾向,可直接复制运行:

# 基于规则的 PP 附着歧义消解演示
# 句子: "I saw the man with the telescope"
# 歧义: with the telescope 修饰 saw(用望远镜看)还是修饰 man(带望远镜的男人)?

def resolve_pp_attachment(sentence, pp_head):
    """
    简单规则:根据介词短语中心词 pp_head 的语义类别判断附着倾向。
    返回 (倾向, 理由)。
    """
    # 可食用物品 → 更可能修饰宾语(NP 附着,如 "eat pizza with anchovies")
    edible = {"anchovies", "cheese", "pepperoni", "mushrooms", "sauce"}
    # 可携带/工具类物品 → 更可能修饰动词(VP 附着,如 "see with a telescope")
    portable_tool = {"telescope", "binoculars", "camera", "umbrella", "hammer"}

    if pp_head in edible:
        return "NP 附着(修饰宾语)", f"'{pp_head}' 是可食用物品,倾向修饰宾语"
    elif pp_head in portable_tool:
        return "VP 附着(修饰动词)", f"'{pp_head}' 是工具/可携带物品,倾向修饰动词"
    else:
        return "无法判定", f"'{pp_head}' 不在规则词表中,需借助统计/概率模型"

# 测试
sentence = "I saw the man with the telescope"
for head in ["telescope", "anchovies", "camera", "book"]:
    tendency, reason = resolve_pp_attachment(sentence, head)
    print(f"with the {head:12s} -> {tendency:12s} | {reason}")

# 运行结果示例:
# with the telescope   -> VP 附着(修饰动词) | 'telescope' 是工具/可携带物品,倾向修饰动词
# with the anchovies  -> NP 附着(修饰宾语) | 'anchovies' 是可食用物品,倾向修饰宾语
# with the camera     -> VP 附着(修饰动词) | 'camera' 是工具/可携带物品,倾向修饰动词
# with the book       -> 无法判定            | 'book' 不在规则词表中,需借助统计/概率模型

要点解读

  • 规则方法的本质:用人工归纳的语义类别(可食用/可携带工具)直接映射到附着倾向,无需训练数据,解释性强、可快速上线,但词表覆盖有限——遇到 “book” 这类未收录词就失效。
  • 与 PCFG 概率消歧的差异:PCFG 通过 VP -> VP PPNP -> NP PP 两条规则的概率在解析时竞争,概率从树库统计得到,能自动覆盖未见词并给出全局最优树;而本规则方法只做局部语义判断,不建模句法结构,也无法处理 “eat pizza with a fork”(fork 是工具却修饰 pizza)这类反例——这正是 §3.3 所述 PCFG 缺乏词汇敏感性、需词汇化扩展的原因。

3. 核心理论与算法

3.1 N 元语法语言模型(N-gram Language Model)

原理:语言模型给词序列赋概率。用链式法则展开:
P(w1:n)=∏i=1nP(wi∣w1:i−1)P(w_{1:n}) = \prod_{i=1}^{n} P(w_i \mid w_{1:i-1})P(w1:n)=i=1nP(wiw1:i1) 上下文 w1:i−1w_{1:i-1}w1:i1 无法穷举,故引入 马尔可夫假设:只依赖前 N−1N-1N1 个词。
P(w1:n)≈∏i=1nP(wi∣wi−N+1:i−1)P(w_{1:n}) \approx \prod_{i=1}^{n} P(w_i \mid w_{i-N+1:i-1})P(w1:n)i=1nP(wiwiN+1:i1)

  • unigram:P(wi)P(w_i)P(wi)
  • bigram:P(wi∣wi−1)P(w_i \mid w_{i-1})P(wiwi1)
  • trigram:P(wi∣wi−2,wi−1)P(w_i \mid w_{i-2}, w_{i-1})P(wiwi2,wi1)

参数估计(MLE)
PMLE(wi∣wi−1)=C(wi−1,wi)C(wi−1)P_{\text{MLE}}(w_i \mid w_{i-1}) = \frac{C(w_{i-1}, w_i)}{C(w_{i-1})}PMLE(wiwi1)=C(wi1)C(wi1,wi)

问题:数据稀疏(sparsity)。未出现的 N-gram 概率为 0,导致整句概率为 0。必须平滑(smoothing)

平滑方法

  1. 加一/加 k 平滑(Laplace / Lidstone)
    P(wi∣wi−1)=C(wi−1,wi)+kC(wi−1)+k∣V∣P(w_i\mid w_{i-1}) = \frac{C(w_{i-1},w_i)+k}{C(w_{i-1}) + k|V|}P(wiwi1)=C(wi1)+kVC(wi1,wi)+k
    简单但对大词表效果差(把过多概率质量分给未见事件)。

  2. 线性插值(interpolation)
    P^(wi∣wi−2,wi−1)=λ3P(wi∣wi−2,wi−1)+λ2P(wi∣wi−1)+λ1P(wi)\hat{P}(w_i\mid w_{i-2},w_{i-1}) = \lambda_3 P(w_i\mid w_{i-2},w_{i-1}) + \lambda_2 P(w_i \mid w_{i-1}) + \lambda_1 P(w_i)P^(wiwi2,wi1)=λ3P(wiwi2,wi1)+λ2P(wiwi1)+λ1P(wi) 其中 ∑λi=1\sum \lambda_i = 1λi=1λ\lambdaλ 在留出集(held-out set)上用 EM 或网格搜索确定。

  3. 回退(backoff,Katz):高阶 N-gram 有计数就用它,否则打折后回退到低阶。

  4. Kneser–Ney 平滑:最强的经典平滑。核心思想是低阶分布不应用“出现频次”而应用“上下文多样性”(该词能跟在多少种不同的前文之后)。例如 “Francisco” 频次高但几乎只跟在 “San” 后,作为 unigram 回退项应该被压低。
    PKN(wi∣wi−1)=max⁡(C(wi−1,wi)−d, 0)C(wi−1)+λ(wi−1) Pcont(wi)P_{KN}(w_i\mid w_{i-1}) = \frac{\max(C(w_{i-1},w_i)-d,\,0)}{C(w_{i-1})} + \lambda(w_{i-1})\,P_{\text{cont}}(w_i)PKN(wiwi1)=C(wi1)max(C(wi1,wi)d,0)+λ(wi1)Pcont(wi)
    Pcont(wi)=∣{v:C(v,wi)>0}∣∣{(v,w):C(v,w)>0}∣P_{\text{cont}}(w_i)=\frac{|\{v: C(v,w_i)>0\}|}{|\{(v,w): C(v,w)>0\}|}Pcont(wi)={(v,w):C(v,w)>0}{v:C(v,wi)>0}

评价指标:困惑度(perplexity)。在测试集上
PP(W)=P(w1:n)−1/n=2H(W),H(W)=−1nlog⁡2P(w1:n)\text{PP}(W) = P(w_{1:n})^{-1/n} = 2^{H(W)},\quad H(W)=-\frac1n\log_2 P(w_{1:n})PP(W)=P(w1:n)1/n=2H(W),H(W)=n1log2P(w1:n)
困惑度可理解为"平均分支因子":模型在每一步平均在多少个等可能候选中犹豫。越低越好。

字符级 N-gram:无需分词,对语言识别(language identification)、拼写纠错、作者归属特别有效,且天然处理 OOV。

适用场景:拼写纠错、语音识别的重打分、输入法、机器翻译解码、快速基线。
局限性

  • 上下文窗口固定且短,无法建模长程依赖(“The keys to the cabinet … are on the table”)。
  • 参数量随 ∣V∣N|V|^NVN 爆炸。
  • 无泛化能力:训练中见过 “eat a peach” 不能帮助估计 “eat an apricot”(词之间无相似度概念)。这正是第 25 章词嵌入要解决的问题。

Python 实战:训练 bigram 模型并计算困惑度(含加一平滑)

下面用一个微型语料训练 bigram 语言模型,实现 MLE 估计、加一平滑(Laplace)与困惑度计算,可直接复制运行:

import math
from collections import defaultdict

# 小型训练语料(已分词,用 <s> 标记句首、</s> 标记句尾)
corpus = [
    ["<s>", "the", "cat", "sat", "on", "the", "mat", "</s>"],
    ["<s>", "the", "dog", "sat", "on", "the", "mat", "</s>"],
    ["<s>", "a", "cat", "sat", "on", "the", "mat", "</s>"],
    ["<s>", "the", "dog", "chased", "the", "cat", "</s>"],
]

# 测试句子(含训练中未见过的 bigram "a dog")
test_sentence = ["<s>", "a", "dog", "sat", "on", "the", "mat", "</s>"]


def train_bigram(corpus, k=1.0):
    """训练 bigram 模型,返回 (bigram_counts, unigram_counts, vocab_size)"""
    bigram_counts = defaultdict(int)
    unigram_counts = defaultdict(int)

    for sent in corpus:
        for i in range(len(sent) - 1):
            w_prev, w_curr = sent[i], sent[i + 1]
            bigram_counts[(w_prev, w_curr)] += 1
            unigram_counts[w_prev] += 1
        unigram_counts[sent[-1]] += 1  # 句尾词 </s> 也计入 unigram

    vocab_size = len(unigram_counts)
    return bigram_counts, unigram_counts, vocab_size


def bigram_prob(w_curr, w_prev, bigram_counts, unigram_counts, vocab_size, k=1.0):
    """加一平滑的 bigram 概率 P(w_curr | w_prev) = (C(w_prev,w_curr)+k) / (C(w_prev)+k*|V|)"""
    c_bigram = bigram_counts.get((w_prev, w_curr), 0)
    c_unigram = unigram_counts.get(w_prev, 0)
    return (c_bigram + k) / (c_unigram + k * vocab_size)


def perplexity(sentence, bigram_counts, unigram_counts, vocab_size, k=1.0):
    """计算句子困惑度 PP = P(w_1..w_n)^(-1/n)"""
    log_prob = 0.0
    n = 0
    for i in range(len(sentence) - 1):
        p = bigram_prob(sentence[i + 1], sentence[i],
                        bigram_counts, unigram_counts, vocab_size, k)
        log_prob += math.log2(p)
        n += 1
    return 2 ** (-log_prob / n)


# 训练
bigram_counts, unigram_counts, vocab_size = train_bigram(corpus, k=1.0)

# 查看几个概率
print("P(cat | the) =", round(bigram_prob("cat", "the", bigram_counts,
                                           unigram_counts, vocab_size), 4))
print("P(dog | a)   =", round(bigram_prob("dog", "a", bigram_counts,
                                           unigram_counts, vocab_size), 4))

# 计算测试句困惑度
pp = perplexity(test_sentence, bigram_counts, unigram_counts, vocab_size)
print("测试句困惑度 PP =", round(pp, 2))

# 对比:不加平滑(k=0)时,未见过的 bigram 概率为 0 → 困惑度无穷大
try:
    pp_raw = perplexity(test_sentence, bigram_counts, unigram_counts, vocab_size, k=0.0)
    print("不加平滑 PP =", round(pp_raw, 2))
except ZeroDivisionError:
    print("不加平滑 PP = inf(log2(0) 未定义,整句概率为 0)")

# 运行结果示例:
# P(cat | the) = 0.25
# P(dog | a)   = 0.125
# 测试句困惑度 PP = 8.0
# 不加平滑 PP = inf(log2(0) 未定义,整句概率为 0)

要点解读

  • 加一平滑P(w_i | w_{i-1}) = (C(w_{i-1}, w_i) + k) / (C(w_{i-1}) + k|V|),其中 ∣V∣|V|V 是词表大小。分母加 k∣V∣k|V|kV 保证所有候选词的概率之和仍为 1。
  • 困惑度PP = 2^(-(1/n) Σ log₂ P(w_i | w_{i-1})),即几何平均概率的倒数。本例中测试句含未见过的 bigram "a dog",若不平滑则整句概率为 0、困惑度为无穷大;加一平滑后得到有限值 8.0,直观体现了平滑的必要性。
  • 实现细节:用 <s>/</s> 标记句首句尾,使模型能学习"句子如何开始/结束";实际工程中常用 log 概率累加避免浮点下溢。

3.2 词性标注(POS Tagging)—— HMM + Viterbi

建模:给定词序列 w1:nw_{1:n}w1:n,求最优标签序列:
t^1:n=arg⁡max⁡t1:nP(t1:n∣w1:n)=arg⁡max⁡t1:nP(w1:n∣t1:n)P(t1:n)\hat{t}_{1:n} = \arg\max_{t_{1:n}} P(t_{1:n}\mid w_{1:n}) = \arg\max_{t_{1:n}} P(w_{1:n}\mid t_{1:n})P(t_{1:n})t^1:n=argt1:nmaxP(t1:nw1:n)=argt1:nmaxP(w1:nt1:n)P(t1:n)
HMM 的两个独立性假设:

  • 发射(emission)P(w1:n∣t1:n)≈∏iP(wi∣ti)P(w_{1:n}\mid t_{1:n}) \approx \prod_i P(w_i \mid t_i)P(w1:nt1:n)iP(witi)
  • 转移(transition)P(t1:n)≈∏iP(ti∣ti−1)P(t_{1:n}) \approx \prod_i P(t_i \mid t_{i-1})P(t1:n)iP(titi1)(bigram HMM)

t^1:n=arg⁡max⁡t1:n∏i=1nP(wi∣ti) P(ti∣ti−1)\hat{t}_{1:n} = \arg\max_{t_{1:n}} \prod_{i=1}^{n} P(w_i\mid t_i)\,P(t_i \mid t_{i-1})t^1:n=argt1:nmaxi=1nP(witi)P(titi1)

Viterbi 动态规划伪代码

function VITERBI-POS(words w[1..n], tagset T, A, B) returns best tag sequence
  # A[t'][t] = P(t | t')  转移概率
  # B[t][w]  = P(w | t)   发射概率
  for each tag t in T:
      V[1][t]  <- A[<START>][t] * B[t][w[1]]
      back[1][t] <- <START>

  for i = 2 to n:
      for each tag t in T:
          V[i][t]    <- max over t' in T of ( V[i-1][t'] * A[t'][t] * B[t][w[i]] )
          back[i][t] <- argmax over t' in T of ( V[i-1][t'] * A[t'][t] )

  best <- argmax over t of V[n][t]
  return 沿 back 回溯得到的标签序列

复杂度:时间 O(n ∣T∣2)O(n\,|T|^2)O(nT2),空间 O(n ∣T∣)O(n\,|T|)O(nT)。实现时用 log 概率求和 防止下溢。

未登录词处理:用后缀特征(-ing → VBG,-ly → RB)、首字母大写(→ NNP)、含数字(→ CD)来估计 P(w∣t)P(w\mid t)P(wt)

局限性:HMM 是生成式模型,难以加入丰富的重叠特征(前后缀、词形、上下文词)。改进方向是判别式模型:最大熵马尔可夫模型(MEMM)条件随机场(CRF)。CRF 直接建模
P(t1:n∣w1:n)=1Z(w)exp⁡(∑i∑kθkfk(ti−1,ti,w1:n,i))P(t_{1:n}\mid w_{1:n}) = \frac{1}{Z(w)}\exp\Big(\sum_i \sum_k \theta_k f_k(t_{i-1},t_i,w_{1:n},i)\Big)P(t1:nw1:n)=Z(w)1exp(ikθkfk(ti1,ti,w1:n,i))
它避免了 MEMM 的标签偏置问题(label bias),是深度学习之前的 SOTA(英文 POS 准确率约 97%,接近人类一致性上限)。


3.3 上下文无关文法与 PCFG

一个玩具英语文法 E0\mathcal{E}_0E0(AIMA 风格)

S    -> NP VP        [0.90]      NP -> Pronoun     [0.30]
S    -> S Conj S     [0.10]      NP -> Name        [0.10]
VP   -> Verb         [0.40]      NP -> Noun        [0.20]
VP   -> VP NP        [0.35]      NP -> Det Noun    [0.30]
VP   -> VP PP        [0.15]      NP -> NP PP       [0.10]
VP   -> VP Adverb    [0.10]      PP -> Prep NP     [1.00]

PCFG 的定义:每条规则 A→βA\to\betaAβ 有概率 P(A→β)P(A\to\beta)P(Aβ),满足 ∑βP(A→β)=1\sum_{\beta} P(A\to\beta)=1βP(Aβ)=1。一棵解析树 TTT 的概率是其所用规则概率之积(假设规则选择相互独立):
P(T)=∏(A→β)∈TP(A→β)P(T) = \prod_{(A\to\beta)\in T} P(A\to\beta)P(T)=(Aβ)TP(Aβ) 句子概率是所有解析树概率之和:P(s)=∑T: yield(T)=sP(T)P(s) = \sum_{T:\,\text{yield}(T)=s} P(T)P(s)=T:yield(T)=sP(T)

三个基本问题

  1. 解析(parsing)arg⁡max⁡TP(T∣s)\arg\max_T P(T\mid s)argmaxTP(Ts) → CYK / Viterbi-CYK
  2. 求句子概率:inside 算法
  3. 学习规则概率:树库有标注则用相对频次;无标注用 inside-outside 算法(EM 的实例)

PCFG 的建模缺陷

  • 结构独立性假设过强:规则展开与上下文无关,无法表达“代词更常作主语而非宾语”。→ 父节点标注(parent annotation):把 NP 细分为 NP^SNP^VP
  • 缺乏词汇敏感性:无法区分 “eat pizza with a fork”(VP 附着)与 “eat pizza with anchovies”(NP 附着),因为两者用的规则集相同。→ 词汇化 PCFG(Collins/Charniak parser),规则变成 VP(ate)→VP(ate) NP(pizza)VP(\text{ate}) \to VP(\text{ate})\ NP(\text{pizza})VP(ate)VP(ate) NP(pizza),并对参数做回退平滑。

3.4 CYK 算法(Cocke–Younger–Kasami)

前提:文法为乔姆斯基范式(CNF):A→B CA\to B\,CABCA→wA\to wAw。任何 CFG 都可转为等价 CNF。

思想:自底向上的动态规划。用 P[A][i][len] 记录“非终结符 AAA 覆盖从位置 iii 起长度为 lenlenlen 的子串”的最大概率。任何长度 >1>1>1 的成分必然可切成左右两半。

function CYK-PARSE(words, grammar) returns 概率表 P 与回溯表 back
  n ← LENGTH(words)
  P ← 全 0 的三维表 [非终结符 × 起点 i × 长度 len]
  back ← 空表

  # 基础情形:长度为 1 的词
  for i = 1 to n:
      for each 词法规则 (A → words[i]) with prob p:
          P[A, i, 1] <- p

  # 归纳:长度从 2 到 n
  for len = 2 to n:
      for i = 1 to n - len + 1:
          for split = 1 to len - 1:                 # 切分点
              for each 规则 (A -> B C) with prob p:
                  prob <- p * P[B, i, split] * P[C, i+split, len-split]
                  if prob > P[A, i, len]:
                      P[A, i, len]    <- prob
                      back[A, i, len] <- (split, B, C)

  return P, back      # 最优树概率 = P[S, 1, n],从 back 回溯建树

复杂度:时间 O(n3∣G∣)O(n^3 |G|)O(n3G),空间 O(n2∣N∣)O(n^2 |N|)O(n2N)。其中 ∣G∣|G|G 为规则数、nnn 为句长。
优点:保证找到全局最优解析树,覆盖指数级的树空间(Catalan 数量级)。
局限

  • 三次方复杂度对长文档昂贵;需要剪枝(beam / coarse-to-fine)
  • 要求 CNF,转换会引入人造节点,破坏可读性。
  • 依赖高质量树库;跨领域(out-of-domain)性能显著下降。
  • 只输出句法结构,不解决语义。

相关变体

  • Earley 算法:无需 CNF,最坏 O(n3)O(n^3)O(n3),无歧义文法 O(n2)O(n^2)O(n2),右线性 O(n)O(n)O(n);采用"预测-扫描-完成"三操作的图表解析(chart parsing)。
  • Inside 算法:把 CYK 的 max 换成 sum,得到句子总概率。

3.5 移进-归约解析(Shift-Reduce Parsing)

思想:把解析视为一个状态转移的搜索与分类问题。维护一个栈(stack)和一个输入缓冲(buffer),每一步在若干动作中选一个。
基于转移的依存解析(arc-standard 系统)动作集

  • SHIFT:把 buffer 首词压入 stack
  • LEFT-ARC(l):栈顶两元素 s2←s1s_2 \leftarrow s_1s2s1,建立 s1s_1s1 为中心词、s2s_2s2 为依存词的标签 lll 弧,弹出 s2s_2s2
  • RIGHT-ARC(l)s2→s1s_2 \rightarrow s_1s2s1,弹出 s1s_1s1
function `SHIFT-REDUCE-PARSE`(words, classifier) returns dependency tree
  stack  <- [ROOT]
  buffer <- words
  arcs   <- {}
  while not (buffer 为空 and |stack| == 1):
      features <- `EXTRACT-FEATURES`(stack, buffer, arcs)
      action   <- classifier.`PREDICT`(features)   # 贪心,或用 beam search
      case action of
          SHIFT      : stack.push(buffer.pop_front())
          LEFT-ARC(l): arcs.add( (stack[-1], l, stack[-2]) ); stack.remove(stack[-2])
          RIGHT-ARC(l): arcs.add( (stack[-2], l, stack[-1]) ); stack.pop()
  return arcs

训练:用"oracle"从金标树推导出唯一的动作序列,把解析变成多分类的监督学习问题(分类器可以是感知机、SVM,或神经网络——Chen & Manning 2014 的神经依存解析器)。

优缺点对比

CYK(图表解析)移进-归约(转移解析)
复杂度O(n3)O(n^3)O(n3)贪心 O(n)O(n)O(n),线性时间
最优性全局最优贪心易受**错误传播(error propagation)**影响;beam search 缓解
特征受文法结构约束可任意使用栈/缓冲上的丰富特征
适用精度优先、离线分析大规模、在线、低延迟

局限性:贪心解码一步错步步错;标准 arc-standard 系统只能产生投射树(projective tree),处理交叉依存需 arc-eager + swap 或伪投射变换。


3.6 语义分析:语法制导的组合语义

做法:给每条句法规则附一条语义规则(augmented grammar),自底向上组合 λ 表达式。

S(sem)   -> NP(sem_np) VP(sem_vp)      { sem = sem_vp(sem_np) }
VP(sem)  -> Verb(sem_v) NP(sem_np)     { sem = sem_v(sem_np) }
Verb(λy λx Loves(x,y)) -> "loves"
NP(John) -> "John"
NP(Mary) -> "Mary"

解析 “John loves Mary”:
λy λx Loves(x,y) (Mary)⇒λx Loves(x,Mary)⇒Loves(John,Mary)\lambda y\,\lambda x\,Loves(x,y)\ (\text{Mary}) \Rightarrow \lambda x\,Loves(x,\text{Mary}) \Rightarrow Loves(\text{John},\text{Mary})λyλxLoves(x,y) (Mary)λxLoves(x,Mary)Loves(John,Mary)

量化与辖域:“Every student loves a course” 的两个逻辑形式:
∀x (Student(x)⇒∃y (Course(y)∧Loves(x,y)))\forall x\,(Student(x) \Rightarrow \exists y\,(Course(y)\wedge Loves(x,y)))x(Student(x)y(Course(y)Loves(x,y)))
∃y (Course(y)∧∀x (Student(x)⇒Loves(x,y)))\exists y\,(Course(y)\wedge \forall x\,(Student(x)\Rightarrow Loves(x,y)))y(Course(y)x(Student(x)Loves(x,y)))
句法结构相同却有两种语义 → 需要**准逻辑形式(quasi-logical form)**先保留辖域不定,再由语用/常识决定。

语义角色标注(SRL):一种“浅层语义”,不追求完整逻辑形式,只标注“谁对谁做了什么,何时何地”。

[ARG0 The chef] [PRED cooked] [ARG1 the meal] [ARGM-LOC in the kitchen] [ARGM-TMP yesterday].

流程:谓词识别 → 论元识别(argument identification)→ 论元分类。经典特征:谓词词元、短语类型、路径(path,如 NP↑S↓VP↓VBD)、位置(谓词前/后)、语态(主动/被动)。
价值:SRL 提供近似“意义”的结构化表示,是 QA、IE、摘要的中间层;且比完整逻辑形式更鲁棒、更可标注


3.7 指代消解(Coreference Resolution)

任务:把文本中的所有提及(mention)聚成指向同一实体的簇(cluster)。

三类方法

  1. Hobbs 算法(句法启发式):在解析树上按特定顺序(先当前句从左到右广度优先向上搜索,再回溯前文句子)寻找满足性数一致(number/gender agreement)的先行词。简单但依赖高质量解析。

  2. 提及对模型(mention-pair model):对每一对 (mi,mj)(m_i, m_j)(mi,mj) 训练二分类器 P(coref∣mi,mj)P(\text{coref}\mid m_i,m_j)P(corefmi,mj),再用聚类(如“最近先行词”或“最佳先行词”)合并。
    典型特征:距离(句数/提及数)、字符串匹配、性别/单复数一致、命名实体类型一致、句法角色、是否被同一谓词支配。

  3. 提及排序 / 端到端神经模型:对每个提及在其所有候选先行词(含“无先行词” ε)上做 softmax 排序,端到端联合学习提及检测与消解。

难点:需要世界知识(Winograd Schema Challenge):

The trophy doesn’t fit in the suitcase because it is too big. → it = trophy
The trophy doesn’t fit in the suitcase because it is too small. → it = suitcase

仅凭句法/表层特征无法区分;这类例子是“语言理解需要常识”的经典论据,也是评测大模型推理能力的重要基准。

局限性:跨文档指代、桥接指代(bridging:提到 “a car” 后说 “the engine”)、零指代(中文/日文常省略主语)仍是开放难题。


Python 实战:基于启发式规则的 Winograd Schema 消解演示

下面用约 40 行代码实现一个简单的规则式消解器:针对 “The trophy doesn’t fit in the suitcase because it is too big/small” 两个句子,通过判断形容词 big/small 与候选先行词(trophy/suitcase)的语义属性(体积大小)来输出指代消解结果,可直接复制运行:

# 基于启发式规则的 Winograd Schema 消解演示
# 句子: "The trophy doesn't fit in the suitcase because it is too big/small"
# 歧义: it 指 trophy(奖杯)还是 suitcase(手提箱)?

def extract_candidates(sentence):
    """简单提取候选先行词:去掉冠词与标点后,取两个名词短语中心词。"""
    import re
    # 去掉标点,按空格分词
    tokens = re.findall(r"\b\w+\b", sentence.lower())
    # 候选先行词:trophy 与 suitcase(此处用固定词表,实际可结合 POS 标注)
    candidates = [t for t in tokens if t in {"trophy", "suitcase"}]
    return candidates


def resolve_pronoun(sentence, adjective):
    """
    启发式规则:根据形容词的语义倾向选择先行词。
    - big   → 体积大的物体更可能是"放不进去"的原因 → trophy
    - small → 体积小的物体更可能是"放不进去"的原因 → suitcase
    """
    # 语义属性字典:记录每个候选物体的体积倾向(1=大,0=小)
    size_attr = {
        "trophy": 1,    # 奖杯通常体积较大
        "suitcase": 0,  # 手提箱通常体积较小(相对奖杯而言)
    }
    # 形容词 → 期望的体积倾向
    adj_tendency = {
        "big": 1,
        "small": 0,
    }

    candidates = extract_candidates(sentence)
    if len(candidates) < 2:
        return None, "候选先行词不足,无法消解"

    target = adj_tendency.get(adjective)
    if target is None:
        return None, f"形容词 '{adjective}' 不在规则词表中"

    # 选择体积倾向与形容词一致的候选
    for cand in candidates:
        if size_attr.get(cand) == target:
            return cand, f"'{adjective}' 与 '{cand}' 的体积属性匹配"

    return None, "无匹配候选"


# 测试两个 Winograd 句子
s1 = "The trophy doesn't fit in the suitcase because it is too big."
s2 = "The trophy doesn't fit in the suitcase because it is too small."

for sent, adj in [(s1, "big"), (s2, "small")]:
    referent, reason = resolve_pronoun(sent, adj)
    print(f"it is too {adj:5s} -> it = {referent:8s} | {reason}")

# 运行结果示例:
# it is too big   -> it = trophy   | 'big' 与 'trophy' 的体积属性匹配
# it is too small -> it = suitcase | 'small' 与 'suitcase' 的体积属性匹配

要点解读

  • 候选先行词提取:这里用固定词表简化;真实系统中通常用 POS 标注 + 句法分析找出名词短语中心词,再按性数一致过滤。
  • 语义属性字典size_attr 编码了"奖杯大、手提箱小"的物理常识——这正是 Winograd Schema 的难点所在:仅凭句法/表层特征无法区分,必须引入世界知识
  • 启发式规则的局限:词表覆盖有限、属性刻画粗糙,遇到 “The trophy doesn’t fit in the box because it is too big”(box 与 trophy 谁大?)这类需要更细粒度常识的变体就会失效。这也是 §3.7 所述"指代消解需要世界知识"的直观体现,以及大模型在此类基准上仍具挑战的原因。

3.8 信息抽取(Information Extraction, IE)

目标:把文本转成结构化数据库记录。

层次结构

  1. 命名实体识别(NER):识别 PER/ORG/LOC/DATE/MONEY 等。通常建模为序列标注,用 BIO/BIOES 标注方案
    Barack/B-PER Obama/I-PER visited/O Beijing/B-LOC
    模型演进:规则/词典 → HMM → CRF(+ 手工特征)→ BiLSTM-CRF → BERT-CRF。
  2. 关系抽取:判定实体对之间的关系,如 Founded(Jobs, Apple)
  • 有监督分类;
  • 远程监督(distant supervision):若知识库中有三元组 (e1,r,e2)(e_1, r, e_2)(e1,r,e2),则把所有同时含 e1,e2e_1, e_2e1,e2 的句子标为 rrr 的正例。省标注但噪声大。
  • 自举法(bootstrapping / DIPRE / Snowball):少量种子三元组 → 抽取模板 → 抽新三元组 → 迭代。风险是语义漂移(semantic drift)
  1. 事件抽取与模板填充(template filling):识别事件触发词与各论元槽位。
  2. 有限状态自动机级联(cascaded FSA):AIMA 强调的经典工程范式——分词 FSA → 短语 FSA → 模板匹配 FSA → 合并去重,简单、快、可控,是垂直领域(如医疗报告、财报)至今仍有效的方案。

局限性:模板/规则脆弱、领域迁移差;远程监督引入噪声;开放域关系(OpenIE)抽出的谓词短语难以规范化。


3.9 机器翻译基础(Machine Translation, MT)

噪声信道模型(IBM 模型的基础):把翻译看作“英语句子 eee 经过噪声信道变成外语句子 fff”,求
e^=arg⁡max⁡eP(e∣f)=arg⁡max⁡eP(f∣e)⏟翻译模型 P(e)⏟语言模型\hat{e} = \arg\max_e P(e\mid f) = \arg\max_e \underbrace{P(f\mid e)}_{\text{翻译模型}}\ \underbrace{P(e)}_{\text{语言模型}}e^=argemaxP(ef)=argemax翻译模型P(fe) 语言模型P(e)

  • 翻译模型 P(f∣e)P(f\mid e)P(fe) 保证“忠实度(adequacy)”,从平行语料学习;
  • 语言模型 P(e)P(e)P(e) 保证“流利度(fluency)”,从单语语料学习(数据远多于平行语料,这是该分解的实际优势)。

统计机器翻译(SMT)关键组件

  • 词对齐(word alignment):IBM Model 1–5,用 EM 迭代估计对齐与翻译概率。Model 1 只有词汇翻译概率,Model 2 加位置,Model 3 加繁衍度(fertility),Model 4/5 加扭曲(distortion)与重叠修正。
  • 短语表(phrase table):从对齐中抽取一致的短语对,比逐词翻译更能处理习语与局部语序。
  • 解码(decoding):在指数级候选空间中做 beam search,用 future cost 估计做栈式剪枝(stack decoding)。
  • 调序模型(reordering / distortion model):处理 SVO ↔ SOV 等语序差异。
  • 对数线性模型:现代 SMT 用 e^=arg⁡max⁡e∑kλkhk(e,f)\hat e=\arg\max_e \sum_k \lambda_k h_k(e,f)e^=argmaxekλkhk(e,f) 融合多个特征,λ\lambdaλ 用 MERT 在开发集上按 BLEU 调优。

评价:BLEU(Bilingual Evaluation Understudy)
BLEU=BP⋅exp⁡(∑n=14wnlog⁡pn),BP={1c>re1−r/cc≤r\text{BLEU} = BP \cdot \exp\Big(\sum_{n=1}^{4} w_n \log p_n\Big),\quad BP=\begin{cases}1 & c>r\\ e^{1-r/c} & c\le r\end{cases}BLEU=BPexp(n=14wnlogpn),BP={1e1r/cc>rcr 其中 pnp_npn 是修正的 n-gram 准确率(clipped precision,防止重复词刷分),BPBPBP 是简短惩罚(brevity penalty,防止只输出高置信短句),ccc 为译文长度、rrr 为参考译文长度。
BLEU 的局限:不考虑同义改写与语义等价,与人工评分相关性在高质量系统区间下降;后续有 METEOR、chrF、COMET、BERTScore 等改进。

SMT 的局限性 → 通向第 25 章:短语表稀疏、长距离调序困难、组件割裂(对齐/短语/语言模型/调序各自训练,误差不可端到端优化)。神经机器翻译(NMT,seq2seq + attention)用一个可微模型统一了全部组件,是第 25 章的核心内容。


Python 实战:实现 BLEU 指标的核心计算

下面用约 60 行代码实现 BLEU 的核心计算:修正 n-gram 准确率(clipped precision,n=1,2,3,4)、简短惩罚(brevity penalty)与最终 BLEU 分数,并用一个候选译文与两个参考译文展示完整计算过程,可直接复制运行:

from collections import Counter
import math


def extract_ngrams(tokens, n):
    """从 token 序列中提取所有 n-gram(用元组表示)。"""
    return [tuple(tokens[i:i + n]) for i in range(len(tokens) - n + 1)]


def clipped_precision(candidate, references, n):
    """
    修正 n-gram 准确率(clipped precision):
    对候选中的每个 n-gram,其计数被裁剪为不超过它在任一参考译文中出现的最大次数,
    防止系统通过重复常见词刷分。
    """
    cand_ngrams = extract_ngrams(candidate, n)
    if not cand_ngrams:
        return 0.0

    # 统计候选 n-gram 计数
    cand_counts = Counter(cand_ngrams)

    # 对每个候选 n-gram,取它在所有参考译文中的最大出现次数(clip 上限)
    max_ref_counts = {}
    for ref in references:
        ref_counts = Counter(extract_ngrams(ref, n))
        for gram in cand_counts:
            max_ref_counts[gram] = max(max_ref_counts.get(gram, 0), ref_counts.get(gram, 0))

    # 裁剪:候选计数不能超过参考中的最大计数
    clipped_total = sum(min(count, max_ref_counts.get(gram, 0))
                        for gram, count in cand_counts.items())
    return clipped_total / len(cand_ngrams)


def brevity_penalty(candidate_len, reference_lens):
    """
    简短惩罚(brevity penalty):
    若候选译文比参考译文短,则按指数衰减惩罚,防止系统只输出高置信的短句。
    r 取与候选长度最接近的参考长度(此处简化为最短参考长度,便于演示)。
    """
    r = min(reference_lens)  # 演示用:取最短参考长度;标准实现取最接近的参考长度
    c = candidate_len
    if c > r:
        return 1.0
    return math.exp(1 - r / c)


def bleu(candidate, references, max_n=4, weights=None):
    """
    计算 BLEU 分数:
    BLEU = BP * exp( Σ_{n=1..4} w_n * log p_n )
    其中 p_n 是修正 n-gram 准确率,w_n 通常取 1/4。
    """
    if weights is None:
        weights = [1.0 / max_n] * max_n

    # 1. 计算各阶修正 n-gram 准确率
    precisions = []
    for n in range(1, max_n + 1):
        p = clipped_precision(candidate, references, n)
        precisions.append(p)

    # 2. 几何平均(在 log 域求和):若某阶 p_n = 0,则整个 BLEU 为 0
    if any(p == 0 for p in precisions):
        log_geo_mean = float("-inf")
    else:
        log_geo_mean = sum(w * math.log(p) for w, p in zip(weights, precisions))

    # 3. 简短惩罚
    bp = brevity_penalty(len(candidate), [len(ref) for ref in references])

    # 4. 最终 BLEU
    score = bp * math.exp(log_geo_mean) if log_geo_mean != float("-inf") else 0.0
    return score, precisions, bp


# ---- 示例:一个候选译文 + 两个参考译文 ----
candidate = "the cat sat on the mat".split()
references = [
    "the cat is on the mat".split(),      # 参考 1
    "there is a cat on the mat".split(),  # 参考 2
]

score, precisions, bp = bleu(candidate, references)

# 输出各阶 n-gram 精确率
for n, p in enumerate(precisions, start=1):
    print(f"p_{n} (clipped precision) = {p:.4f}")

print(f"BP (brevity penalty)     = {bp:.4f}")
print(f"BLEU                      = {score:.4f}")

# 运行结果示例:
# p_1 (clipped precision) = 0.8333
# p_2 (clipped precision) = 0.6000
# p_3 (clipped precision) = 0.4000
# p_4 (clipped precision) = 0.0000
# BP (brevity penalty)     = 1.0000
# BLEU                      = 0.0000

要点解读

  • 修正 n-gram 准确率:候选 "the cat sat on the mat"the 出现 2 次,但任一参考中 the 最多出现 1 次,故裁剪后只计 1 次,防止重复词刷分。本例中 4-gram 无一命中参考,p_4 = 0,导致最终 BLEU 为 0——这正是 BLEU 对 n-gram 完全未命中时的“零容忍”特性。
  • 简短惩罚:候选长度 6 大于最短参考长度 5,c > r,故 BP = 1,不惩罚。若候选过短(如只输出 "the mat"),BP 会按 e1−r/ce^{1-r/c}e1r/c 指数衰减。
  • 实现细节:标准 BLEU 的参考长度 rrr 取与候选长度最接近的参考长度(而非最短);工程实现(如 sacrebleu)还会对 n-gram 匹配做平滑(如 add-1 平滑)以避免 p_n = 0 时整分归零。这里为清晰演示保留了最朴素的版本。

4. 关键图示 / 表格说明

4.1 NLP 处理管线图(Pipeline)

  文本  ──► 分词 ──► POS 标注 ──► 句法解析 ──► 语义解释 ──► 篇章/指代 ──► 应用
   │         │          │             │             │              │
 语料统计  形态学    HMM/CRF      PCFG+CYK      λ-演算/SRL     共指簇      IE/MT/QA

要点:管线式架构清晰、每层可单独评测,但存在误差累积(Error Cascading)——分词错 → 词性错 → 句法错。第25章的端到端神经模型正是要绕开这一问题。理解这一点是对比两章的关键。

4.2 解析树 vs 依存树

对句子 “The girl saw the boy with a telescope”:

短语结构树(歧义读法一:PP 修饰 VP,用望远镜看)

        S
     ┌──┴───┐
    NP      VP
  ┌─┴─┐  ┌──┴────┐
 Det Noun VP      PP
 The girl ┌┴──┐ ┌─┴──┐
       Verb NP Prep  NP
       saw the boy with a telescope

依存树(读法一)

saw ──nsubj──► girl ──det──► The
    ──dobj───► boy  ──det──► the
    ──prep───► with ──pobj──► telescope

说明:两种表示可互转(通过 head rules)。短语结构强调“成分”,依存结构强调“关系”,后者对语义角色抽取更直接、对中文/俄语等语序灵活的语言更友好。PP 附着歧义在两种表示中都体现为 with 挂到 saw 还是挂到 boy

4.3 CYK 解析表(chart)示意

对 3 词句子,表格为上三角,行 = 长度、列 = 起点:

len\i123
3S(0.0012)
2NP(0.03)VP(0.02)
1Det(0.6)Noun(0.1)Verb(0.4)

读法:每个单元格存“能覆盖该跨度的所有非终结符及其最优概率”。填 len=3, i=1 时枚举切分点 split=1(左 span 1 + 右 span 2)与 split=2(左 span 2 + 右 span 1),取最大值。左下角到右上角的填表顺序体现了“子问题先于父问题”的 DP 特性。

4.4 平滑方法对比表

方法核心思想优点缺点
Add-k均匀加计数极简大词表下严重高估未见事件
Good–Turing用出现 r+1r+1r+1 次的事件数估计出现 rrr 次事件的真实频率理论优雅高频区不稳定,需拟合
Interpolation各阶线性加权稳定、易实现λ\lambdaλ 需调参
Katz backoff有则用高阶,无则打折回退保留高阶信息折扣量需估计
Kneser–Ney低阶用"上下文多样性"而非频次经典 SOTA实现较复杂

4.5 歧义类型速查表

见 §2.4 表格。复习提示:能对每一层歧义各举一例、并说出对应的消解技术(WSD / POS tagging / PCFG 概率 / 辖域推理 / 共指模型 / 语用推断),是本章考核重点。


5. 与其他章节的关联

关联章节关联内容
第 12–13 章 概率与贝叶斯网络N-gram、PCFG、HMM 都是概率图模型;噪声信道模型是贝叶斯规则的直接应用
第 14 章 时序概率模型(HMM/滤波)POS 标注的 Viterbi 与机器人定位的滤波是同一算法在不同领域的实例(第27章粒子滤波同源)
第 7–9 章 逻辑与一阶逻辑语义分析把句子映射为一阶逻辑;组合语义依赖 λ-演算与合一(unification)
第 3 章 搜索CYK 是 DP,移进-归约的 beam search 是启发式搜索;MT 解码是带剪枝的最优路径搜索
第 10 章 知识表示 / 本体词义、语义角色、事件框架需要本体支撑;IE 的输出即知识图谱的输入
第19–22章 机器学习POS/NER/SRL/共指均为监督学习任务;EM 用于 inside-outside 与 IBM 对齐模型
第25章 NLP 深度学习直接后继:词嵌入替代离散计数、RNN/Transformer 替代 N-gram、NMT 替代 SMT 管线
第26章 计算机视觉图像描述(captioning)、VQA 是两章的交叉;卷积/注意力机制在两模态间通用
第27章 机器人学自然语言指令理解(“把红色杯子放到桌上”)是语言接地(grounding)问题,连接语义与位形空间中的动作

5.1 与第25章的衔接

本章的经典方法在第25章深度学习范式中都有直接对应物:N-gram → 词嵌入(离散计数被分布式表示取代,解决数据稀疏与泛化问题)、HMM/CRF → BiLSTM-CRF(判别式序列标注的延续)、PCFG → TreeRNN(树结构建模由递归神经网络承接)、SMT → NMT(组件割裂的管线被端到端 seq2seq + attention 统一)。值得注意的是,若干经典思想在 LLM 时代依然保留:注意力机制与词对齐在概念上一脉相承——attention 权重可视作软化的对齐;困惑度(perplexity) 至今仍是评估语言模型的核心指标,只是从 N-gram 平滑后的计数概率换成了神经网络的输出分布。理解这些对应关系,是把握 NLP 从符号/统计范式走向深度学习范式这条主线的最佳切入点。

6. 延伸思考

思考一:LLM 时代,句法与语义的显式结构还有价值吗?

大语言模型(LLM)不显式建模 PCFG、不做 SRL,却在下游任务上全面超越管线式系统。这是否意味着本章内容已被淘汰?

反方论据(结构仍重要)

  1. 探针(probing)研究表明,BERT/GPT 的中间层隐式编码了依存关系、成分边界与语义角色——结构没有消失,只是从"显式符号"变成了"分布式表示"。理解 §3.3–3.7 的结构概念,正是设计探针实验与解释模型行为的前提。
  2. 评测与数据构造:Winograd Schema、辖域歧义、否定作用域等测试集,都是用语言学结构精心构造的。没有这些理论,我们甚至无法系统性地发现 LLM 的失败模式。
  3. 可控生成与形式约束:需要严格结构输出(SQL、JSON、逻辑形式)时,语法约束解码(grammar-constrained decoding)直接复用 CFG,效果与效率远超"祈祷模型输出格式正确"。
  4. 低资源语言:形态丰富、语料稀缺的语言仍依赖形态分析与语法知识注入。

开放问题:能否设计一种"神经-符号"混合架构,让 LLM 在需要精确推理(如量化辖域、指代链)时显式调用结构化解析器,而在常规生成时保持端到端效率?当前的工具调用(tool use)范式算是雏形,但结构解析器的输出如何可微地反馈给模型,仍未解决。

思考二:歧义、接地与对齐——语言理解的三重难题

本章反复出现的主题是“歧义只能靠上下文与世界知识消解”。这一命题在多模态与 AI 对齐语境下有新的意义:

  • 多模态接地(grounding):Winograd 式歧义(trophy/suitcase 的大小关系)本质上是物理常识问题。纯文本模型只能从"人们如何谈论物体"间接习得,而多模态模型(视觉 + 语言)原则上可从视觉经验直接习得空间与物理关系。这提出一个可检验的问题:多模态预训练是否能在指代消解、空间语义等任务上带来纯文本模型无法达到的提升? 目前证据混杂——多模态模型在视觉相关的常识上确有优势,但在抽象推理上未见系统性收益,说明"接地"可能不是充分条件。

  • 歧义与对齐(alignment):AI 对齐的核心困难之一,正是人类指令本身是歧义的。“帮我把这封邮件写得更有说服力”中,说服的边界在哪里?§2.4 的语用歧义在此升级为价值歧义。经典 NLP 用“最大后验”消解歧义,即选择最可能的解释;但对齐场景下我们可能需要最安全最符合用户真实意图的解释——这两者并不等价。

开放问题:当系统面对高风险指令的歧义时,应当 (a) 按先验概率选最可能解释,(b) 主动澄清提问,还是 © 选择后果最保守的解释?这需要把语言学的歧义消解与决策论的效用最大化(第 16 章)结合起来——即把 arg⁡max⁡IP(I∣w)\arg\max_I P(I\mid w)argmaxIP(Iw) 换成 arg⁡max⁡a∑IP(I∣w) U(a,I)\arg\max_a \sum_I P(I \mid w)\,U(a, I)argmaxaIP(Iw)U(a,I),在解释的不确定性上对行动做期望效用最大化。这或许是"语言学 + 决策论 + 对齐"最有前景的交汇点。


7. 本章小结

本章沿"从字符到意义"的经典管线,系统介绍了符号与统计范式的 NLP 核心方法,可归纳为以下要点:

  1. NLP 处理管线:从原始文本出发,依次经过分词/词法分析、词性标注、句法解析、语义解释、篇章/指代处理,最终落到信息抽取、问答、机器翻译等应用。管线式架构清晰、每层可独立评测,但存在误差累积问题——分词错会逐级传导到词性与句法。

  2. N-gram 语言模型与平滑:用马尔可夫假设把词序列概率分解为局部条件概率,是语音识别、拼写纠错、机器翻译的公共底座。数据稀疏是核心难题,需借助加一/加 k 平滑、线性插值、Katz 回退与 Kneser–Ney 平滑;困惑度(perplexity) 是评价语言模型的核心指标,至今仍是 LLM 评测的重要参考。

  3. HMM 词性标注:把 POS 标注建模为隐马尔可夫模型,用 Viterbi 动态规划在 O(n∣T∣2)O(n|T|^2)O(nT2) 时间内求最优标签序列。HMM 是生成式模型,难以加入重叠特征,后续被判别式的 MEMM、CRF 超越,而 CRF 又是深度学习时代 BiLSTM-CRF 的直接前身。

  4. PCFG 与 CYK 解析:PCFG 为每条文法规则赋予概率,用 CYK 算法在 O(n3∣G∣)O(n^3|G|)O(n3G) 内求全局最优解析树。其结构独立性假设过强、缺乏词汇敏感性,需父节点标注与词汇化扩展——这些缺陷正是第 25 章 TreeRNN 等神经结构建模要解决的问题。

  5. 移进-归约依存解析:把解析视为状态转移的分类问题,用 SHIFT/LEFT-ARC/RIGHT-ARC 动作贪心构建依存树,线性时间、适合大规模在线场景,但易受错误传播影响,且标准系统只能产生投射树。

  6. 组合语义与指代消解:语法制导翻译把句法结构映射为 λ-表达式,实现组合语义;指代消解把提及聚成实体簇,Hobbs 启发式、提及对模型与端到端神经模型层层递进。Winograd Schema 表明指代消解需要世界知识,这是语言理解的核心难点。

  7. 信息抽取:把非结构化文本转为结构化记录,涵盖 NER、关系抽取与事件抽取。模型从规则/词典演进到 HMM、CRF,再到 BiLSTM-CRF 与 BERT-CRF;有限状态自动机级联在垂直领域至今仍有效。

  8. 与 LLM 深度学习范式的关系:本章经典方法在第 25 章都有直接对应物——N-gram → 词嵌入HMM/CRF → BiLSTM-CRFPCFG → TreeRNNSMT → NMT。但若干思想在 LLM 时代依然保留:注意力权重可视作软化的词对齐,困惑度仍是核心评测指标,语法约束解码直接复用 CFG。理解这些对应关系,是把握 NLP 从符号/统计走向深度学习这条主线的最佳切入点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是慎独

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值