跳转到内容

Brill-Moore 2000 — 把拼写纠错的编辑操作从单字符扩成任意子串

是什么

Brill-Moore 2000 是一篇让搜索框纠错变聪明的论文。日常类比:旧模型像一个只会改单个字母的小学生(看到 teh 才能改成 the),Brill-Moore 像一个见过世面的编辑——他知道 ph 经常被人错写成 ftion 经常被错写成 shun,可以整段整段地替换

具体来说,论文做了一件事:

把噪声信道里的编辑操作,从「单字符 insert/delete/substitute/transpose」扩成「任意子串 α → β 替换」,并从语料里学每对 α→β 替换发生的概率。

举几个原本做不到、Brill-Moore 能做到的纠错:

  • fysicsphysics(学到了 f → ph
  • nashunnation(学到了 shun → tion
  • recievereceive(学到了 ie → eic 后)

这套思路成了之后 20 年搜索框拼写纠错的算法骨架。

为什么重要

不理解这篇论文,下面这些事你想不通:

  • 为什么 Google 搜索框输入 fysics 也能给你 physics——单字符模型做不到
  • 为什么搜索引擎的 spell suggester 训练时要喂大量 (错词, 正词) 配对日志
  • 为什么 Elasticsearch 的 phrase suggester、Lucene 的 SpellChecker 都用 Viterbi 风格的解码
  • 为什么神经网络拼写纠错(seq2seq)出来之后,这套老方法还活着——它是统计基线,且对短词又快又准

核心要点

论文可以拆成 三步

第一步:噪声信道的复习

噪声信道模型(Kernighan 1990)说:用户脑子里有正确词 w,键盘是个噪声通道,输出错误词 t。我们要找:

argmax_w P(w | t) = argmax_w P(t | w) × P(w)
  • P(w) 是语言模型(这个词在英语里多常见)
  • P(t | w) 是错误模型(用户想打 w 却打成 t 的概率)

旧模型 P(t | w) 只考虑单字符编辑。Brill-Moore 改的就是这个错误模型。

第二步:多字符替换

旧版:P(insert(c))P(delete(c))P(sub(c1, c2))P(trans(c1, c2)),参数总数大约 字母表^2

Brill-Moore 版:P(α → β),其中 αβ任意长度的子串。比如:

αβ含义
phf用户把 ph 写成 f
ouldould这部分没动(带位置信息)
e用户多打了一个 e
eiie字母颠倒(不止单 trans)

这等于把字符级的编辑距离,升级成子串级的对齐距离

第三步:怎么学这些权重

需要一份 (typo, correction) 配对语料(论文用约 1 万对)。流程:

  1. 对每对 (t, w),先用单字符 Levenshtein 对齐,得到字符级编辑路径
  2. 把相邻的编辑合并成多字符替换,得到候选 α→β 列表
  3. 数频率得到 P(α | β) = count(α→β) / count(β)
  4. 解码时用 Viterbi 风格的动态规划,在词典所有候选里找最大化 P(t|w) × P(w)w

效果:相比 Kernighan 单字符模型,Top-1 准确率从约 75% 提到约 88%。

实践案例

案例 1:fysics → physics 的解码过程

输入:fysics,词典里有 physics

旧模型:要从 fysics 变到 physics 需要 1 个 insert(p)+ 1 个 substitute(f→h)= 编辑距离 2,概率被压得很低。

Brill-Moore:直接学到了 f → ph 这个替换,概率较高。所以:

P(fysics | physics) ≈ P(f | ph) × P(ysics | ysics)
≈ 0.001 × 1.0

而正确的 physics 在语言模型里又常见,乘起来就压过了其他候选。

案例 2:现代搜索框背后的同款骨架

Elasticsearch 的 phrase suggester 流程:

{
"suggest": {
"text": "fysics teh latest",
"phrase_suggester": {
"field": "body",
"max_errors": 2,
"direct_generator": [{
"field": "body",
"suggest_mode": "always"
}]
}
}
}

底层就是:候选生成(编辑距离 ≤ 2 的词)+ 噪声信道打分(错误模型 × 语言模型)+ Viterbi 选最优。这套架构直接来自 Brill-Moore。

案例 3:DIY 一个小型纠错器

# 极简伪代码:用 Brill-Moore 思想纠错
edit_probs = {
("ph", "f"): 0.001,
("tion", "shun"): 0.0005,
("ie", "ei"): 0.0002,
# ... 从语料里学
}
lm_probs = {"physics": 0.0001, "fissics": 1e-9, ...}
def score(typo, word):
# 用 DP 找 typo 和 word 的最佳子串对齐
align = best_alignment(typo, word, edit_probs)
return align.prob * lm_probs[word]
def correct(typo, dictionary):
return max(dictionary, key=lambda w: score(typo, w))

真实工程里 dictionary 用 trie 加剪枝,best_alignment 用 Viterbi 写。

踩过的坑

  1. 训练数据稀缺:拿不到大量 (typo, correction) 配对就学不出权重。早期工业界靠用户「点击搜索结果」的隐式日志挖(用户先搜 fysics 没结果,又搜 physics 点了结果——推断这是一对)。

  2. α→β 组合爆炸:不剪枝的话,子串对长度 5 就有 26^5 × 26^5 量级。论文限制 |α|, |β| ≤ 5 并要求最少出现 2 次。

  3. 上下文无关的硬伤:单词级模型分不出 their/there/they'reits/it's。这种要句子级模型,Brill-Moore 解决不了。后来 Toutanova-Moore 2002 加发音、神经 seq2seq 加上下文都是为了补这一刀。

  4. 不适合中日韩等无空格语言:算法假设词是离散单元,中文 自然语言处理 没法直接套,要先分词。

适用 vs 不适用场景

适用

  • 英文等空格分词语言的搜索框拼写纠错
  • 短查询(1-5 个词)的实时纠错——比神经模型快 100 倍
  • OCR 后处理——把 OCR 错误当噪声信道
  • 想要可解释的 baseline——每个修正都有概率链可追

不适用

  • 长文本/语法纠错(GEC)——要句子级语言模型,用 Transformer
  • 上下文相关的同音/形近词——their/thereform/from 这种
  • 中日韩无空格语言——要先分词,且形态学复杂
  • 极低资源语言——拿不到训练对就退化成 Levenshtein

历史小故事(可跳过)

  • 1990 年:Kernighan、Church、Gale 在 AT&T Bell Labs 提出单字符噪声信道。AT&T 把它装进电话目录查询系统。
  • 2000 年:Brill 和 Moore 在 Microsoft Research 把它扩到多字符,论文 8 页。
  • 2002 年:Toutanova 和 Moore 加入发音模型(soundex 风格),处理 nite/night 这种。
  • 2010 年代:seq2seq 神经模型出现,但工业界很多搜索框依然用 Brill-Moore 风格的统计基线兜底——快、可解释、易热更。

学到什么

  1. 把”操作的粒度”提一级,错误率能掉一半——这是统计 NLP 里反复出现的模式(n-gram、subword、phrase-based MT 都是这套)
  2. 噪声信道是个万能框架——把任何”输入被破坏,要恢复原始”的问题都可以这么建模:拼写、OCR、机器翻译、ASR
  3. 统计模型 + Viterbi 解码 是从 1980 年代到神经网络兴起前 20 年里 NLP 的主旋律
  4. 一份小但干净的训练对(1 万对配对)就能撑起一个工业系统——数据质量大于数量

延伸阅读

关联

  • anh-moffat-2005 —— 倒排索引压缩,与拼写纠错同属经典 IR 工具箱
  • anserini-2017 —— 学术 IR 基线,里面的 spell suggester 用的就是 Brill-Moore 思想
  • hindley-milner —— 同属”动态规划 + 推理”家族,但目标完全不同(类型 vs 字符串对齐)