本文解读 CMU “Subword Modeling” (Spring 2026) 第16讲:G2P and P2G。
前两节课讲了「14 为什么光靠文字不够,需要 IPA」以及「15 文字和 IPA 的关系」。这节课进入实操层面:怎么把文字自动转成 IPA,也就是 G2P (Grapheme-to-Phoneme)。内容涵盖基于规则的方法和数据驱动的方法,以及两者各自的适用场景。
1. G2P 和 P2G 分别是什么
G2P是 Grapheme-to-Phoneme 的缩写,把文字转成音素序列。P2G是反过来,把音素序列转回文字。
G2P 曾经是语音识别 ASR 和语音合成 TTS 系统里的核心组件。在端到端模型兴起之后,G2P 在语音领域的使用频率下降了,但它的应用场景反而变得更广泛:
- 低资源 TTS:训练数据不够的时候,把文字转成 IPA 再做合成,比直接从文字学更可靠
- 语料语音学研究:低资源语言有录音但没有 IPA 标注,用 G2P 生成转写后可以跟录音做对齐,用于语音学分析
- NLP 任务的预处理:命名实体识别、实体链接、问答、自然语言推理等任务,语音表示可以提供额外信号
- 计算语言学中涉及音韵学的研究:输入数据是正字法,但研究对象是音韵系统,G2P 是必经之路
P2G 的用途更窄,但有一种典型场景:先把文字 G2P 成音素,在音素层面做某种处理,再 P2G 回文字。或者用语音识别模型输出音素序列,再转成文字或词。
2. G2P 的三个核心挑战
做 G2P 并不容易,主要难在三点:
数据稀缺且昂贵。标注发音数据需要语音学训练,成本很高。可用的数据源之一是 Wiktionary——WikiPron 这个工具可以从 Wiktionary 上爬取大量语言的「拼写-发音」对,但质量参差不齐,有些语言的数据量也很小。
数据通常是孤立词,而不是连续文本。发音词典给的是单个词的标注,但很多语音现象——比如连读、弱化、语境依赖的变调——只有在连续语流中才会出现。
从文字到音素的映射在很多语言里是不确定的。上节课已经详细讨论过这个问题:同一个拼写在不同语境下可能对应不同的发音。
3. 基于规则的 G2P:Epitran 的三段式流水线
3.1 从 Unitran 到 Epitran
最早的大规模多语言 G2P 系统叫 Unitran,思路很暴力:遍历整个 Unicode 标准,给每个字符分配一个 IPA 对应。拉丁字母因为歧义太大被直接排除了。这个系统对文字系统的理解过于天真,但它是大规模多语言 G2P 的一个重要起步。
Epitran 是在 Unitran 基础上的改进。它目前支持几十种语言,核心架构是一个三段式流水线:
输入文字 → [预处理器] → [映射表] → [后处理器] → 输出 IPA3.2 用德语走一遍流水线
Mortensen 用德语单词 “Stecker” 做了一个完整的演示:
第一步:预处理器。用正则表达式做字符串替换,把输入变成映射表能处理的形式。比如德语里 s 在 t 前面要读成 ʃ,但映射表只知道 sch → ʃ,所以预处理器先把 “Stecker” 变成 “schtecker”。
规则写法:
% s 在词首 p/t 前变成 sch s -> sch / # _ (p|t)#表示词边界,_表示当前位置,(p|t)是正则表达式的析取。
第二步:映射表。一个简单的 CSV 文件,每行是一个「字素→音素」的对应。比如 sch → ʃ、e → ɛ、ck → k 等等。映射是从左到右贪心匹配的——优先匹配更长的字素序列。
经过映射表,“schtecker” 变成了 ʃtɛkəʀ。
第三步:后处理器。再用一组正则表达式做音韵层面的调整。比如标准德语里词尾的 əʀ 会变成 ɐ,这条规则写成:
əʀ -> ɐ / _ #最终输出:ʃtɛkɐ。
3.3 为什么要拆成三段?
一个自然的问题是:预处理、映射、后处理这三个功能,理论上一个正则表达式级联就能搞定,为什么要拆开?
Mortensen 的回答很务实:为了降低开发门槛。对于大多数语言来说,只需要写映射表就够了——一个 CSV 文件,在电子表格里就能编辑。一般情况用映射表处理,特殊情况用预处理器调整输入或用后处理器调整输出。这样大部分工作量落在最简单的组件上。
映射表里还可以使用非 IPA 符号作为中间表示。比如德语模块里用一个通用的 C 代表辅音,后处理器再根据 C 触发相应的规则。这种分层设计让每一层的逻辑保持简单。
3.4 Epitran 2
Epitran 的下一个版本正在用 Rust 重写,底层使用 WFST。好处有三个:速度更快;可以更好地处理例外词;所有 G2P 模块都可以自动反转成 P2G 模块。同时也会支持规则和数据驱动方法的混合使用。
4. 规则方法的天花板
基于规则的 G2P 在文字到音素映射是确定性的时候表现非常好。事实上,如果规则是正确的,数据驱动方法不可能在确定性映射上超越正确的规则系统。
但问题是:很多语言的映射不是确定性的。
英语是一个经典案例。教学上把元音分成「长元音」和「短元音」:
| 字母 | 短元音 | 长元音 |
|---|---|---|
| i | /ɪ/ 如 bit | /aj/ 如 bite |
| u | /ʌ/ 如 butt | /u/ 如 rude |
| e | /ɛ/ 如 bet | /i/ 如 reflex |
| o | /ɔ/ 如 dot | /ow/ 如 dote |
| a | /æ/ 如 pant | /ej/ 如 date |
长短元音的分布背后有一个历史规律:在开音节里元音被延长,在闭音节里保持短。比如 “mat” /mat/ 和 “mate”——后者原来是 /matə/,元音在开音节里被拉长成 /maːtə/,然后词尾的 /ə/ 脱落了,留下 /maːt/,再经过「元音大推移」变成了今天的 /mejt/。
所以 “recess” 里第一个 e 是「长音」/i/——因为它在开音节里;第二个 e 是「短音」/ɛ/——因为它在闭音节里。
这个规律到今天仍然大致成立,但已经被外来词借入和拼写变异搞得面目全非。比如 “chai” 里的 ai 发 /aj/,而在本土英语词里 ai 永远发 /ej/——像 pain、Paige、fail。这是因为 “chai” 是外来词,不遵守英语本土的拼写-发音对应规则。
这种「大致有规律但例外很多」的情况,正是数据驱动方法的用武之地。
5. 数据驱动的 G2P
5.1 Paired-ngram 模型
最早成功的数据驱动 G2P 模型基于 WFST。核心思路是:字素 n-gram 和音素 n-gram 之间存在对应关系。
比如英语里 gh 有三种读法:
- 在 ghost、ghetto 里发 /ɡ/
- 在 enough、tough、cough 里发 /f/
- 在 knight、right、night 里不发音
看起来很复杂,但一旦放到更大的 n-gram 里就有规律了:ough 通常对应 /ʌf/,ight 基本总是对应 /ajt/。Paired-ngram 模型在发音词典上训练,学习这些字素序列和音素序列之间的统计关联。做 G2P 的过程就是一个 HMM 解码问题——观测是字素,隐状态是音素。
5.2 LSTM 系统
LSTM 模型通常用 encoder-decoder 架构,有时加上注意力机制。在性能上一般优于 paired-ngram 模型,但训练更复杂、计算成本更高。训练数据同样来自发音词典。
5.3 Transformer 系统
Transformer 在数据充足的时候性能最好。用的通常是小型 Transformer——少量的 encoder 和 decoder 层。计算成本比 LSTM 和 WFST 高得多,但性能优势可能值得这个开销。
6. 规则 vs 数据驱动:不是替代关系
这节课传达的一个关键信息是:规则方法和数据驱动方法不是互相替代的,而是互补的。
| 维度 | 规则方法 | 数据驱动方法 |
|---|---|---|
| 适用场景 | 确定性映射的语言 | 非确定性映射的语言 |
| 数据需求 | 需要语言学专家编写规则 | 需要发音词典或标注数据 |
| 性能上界 | 规则正确时无法被超越 | 可以捕捉规则难以编码的概率性模式 |
| 开发成本 | 按语言逐个编写 | 训练成本高,但可跨语言复用架构 |
| 可解释性 | 高——每条规则都可以审查 | 低——模型是黑箱 |
对于拼写比较透明的语言——比如西班牙语、芬兰语、土耳其语——规则方法就够了,而且更可靠。对于拼写混乱的语言——比如英语、法语——数据驱动方法是必要的。对于文字系统丢失大量语音信息的语言——比如阿拉伯语——则需要数据驱动方法配合语言模型来做上下文推断。
Epitran 2 的设计方向也印证了这一点:它计划把规则方法和数据驱动方法整合到同一个框架里。
7. 总结
| 方法 | 核心思路 | 代表系统 |
|---|---|---|
| 基于 Unicode 查表 | 给每个字符分配 IPA | Unitran |
| 基于规则的三段流水线 | 预处理 → 映射 → 后处理 | Epitran |
| Paired-ngram + WFST | 学习字素和音素 n-gram 的统计对应 | Phonetisaurus 等 |
| LSTM encoder-decoder | seq2seq 架构学习映射 | 多种实现 |
| Transformer | 小型 Transformer 做 seq2seq | 多种实现 |
核心 takeaway:
G2P 的本质问题是:文字到语音的映射在不同语言里有不同程度的不确定性。确定性高的部分用规则解决,不确定性高的部分用数据驱动方法解决。好的 G2P 系统应该把两者结合起来,而不是只选一边。
从系列文章的脉络来看,前两节课建立了「为什么需要 IPA」的认知,这节课回答了「怎么自动得到 IPA」。下一步自然是:有了 IPA 表示之后,怎么用它来提升 NLP 任务的性能。