Chapter 4: 文本规范化全家桶:TN / ITN / OpenCC / 混语与混脚本
4.1 开篇:ASR 的隐形天花板
在 ASR 训练中,有一个残酷的现实:如果你的文本处理做得不好,更换再先进的模型(如从 Conformer 换到 Zipformer)带来的提升,可能还不如写好 10 条正则表达式带来的收益大。
文本规范化(Text Normalization)不仅仅是“清洗”,它是定义声学模型学习目标的过程。
- 训练侧(TN):解决“多字同音”和“一字多形”的歧义,让模型只关注声学信号与发音单元的对应。
- 推理侧(ITN):解决“可读性”与“下游应用”的对接,决定了用户看到的最终体。
对于多语种(Multi-lingual)和多模态(MLLM)任务,文本处理更是涉及字符编码、脚本冲突(Script Conflict)和 RAG 检索命中率的核心命门。
4.2 核心流水线与概念定义
在开始写代码之前,我们必须建立两套平行的概念体系:Spoken Form(口语体) 与 Written Form(书写体)。
4.2.1 理想的 ASR 文本数据流
- Written Form (Raw):
2025年,AI技术增长了10%!(用户看到的) - Spoken Form (Normalized):
二零二五年 A I 技术增长了百分之十(模型听到的) - Modeling Unit:
二 零 二 五 年 <space> A I <space> 技 术...(模型学习的 Token)
4.2.2 训练与推理的不对称性
| 阶段 | 任务名称 | 输入示例 | 输出示例 | 目标 |
| 阶段 | 任务名称 | 输入示例 | 输出示例 | 目标 |
|---|---|---|---|---|
| 预处理 | TN (Text Normalization) | ¥50 |
五十元 |
消除歧义,匹配发音 |
| 后处理 | ITN (Inverse TN) | 五十元 |
¥50 |
恢复格式,合阅读习惯 |
| 兼容层 | Tokenization | Hello世界 |
_Hello 世 界 |
划定词表,处理混语 |
4.3 基础地基:Unicode 与字符清洗
这是所有语种通用的“第一步”。不做这一步,后续的规则匹配会因为编码问题全面失效。
4.3.1 Unicode Normalization (NFKC)
Unicode 允许同一个字符有多种编码组合。
- 组合字符:
é可以是U+00E9(单一字符),也可以是e (U+0065)+´ (U+0301)。 - 兼容字符:全角数字
1、罗马数字Ⅱ、带圈数字①、连字fi。
Rule of Thumb: 对所有文本强制执行 NFKC。它会将上述所有变体统一为标准 ASCII 或通用汉字。
fi->fi1->1①->1
4.3.2 易混淆字符 (Confusables)
在 OCR 转换的文本或脏数据中,经常出现“看起来像但编码不同”的字符。
- O 与 0:英文 O 和数字 0。
- l 与 1:小写 L 和数字 1。
- — (Em Dash) 与 - (Hyphen) 与 一 (汉字一):极易混淆。
处理策略:建立一个confusables.map 映射表,在 TN 之前进行替换。
4.4 中文 TN (Text Normalization):训练侧的硬仗
TN 的核心原则是:确定性 (Determinism)。尽量减少模型在同一段音频上看到不同文本的可能性。
4.4.1 数字处理体系
中文数字读法高度依赖上下文,是 TN 中最难的部分。
| 类型 | 文本模式 | 目标 Spoken Form | 判别逻辑 |
| 类型 | 文本模式 | 目标 Spoken Form | 判别逻辑 |
|---|---|---|---|
| 纯数字 (Cardinal) | 100 |
一百 |
默认逻辑 |
| 电话/ID (Digits) | 138... / 110 |
幺三八... / 幺幺零 |
长度>5位,或特定白名单 |
| 年份 | 2023年 |
二零二三年 |
后接“年” |
| 分数 | 1/3 |
三分之一 |
正则 (\d+)/(\d+) |
| 百分比 | 20% |
百分之二十 |
后接 % |
| 范围 | 3-5天 |
三到五天 |
中间是 - 或 ~ |
Gotcha: “102” 读
一百零二还是一百?
- 标准普通话:建议统一为
一百零二。- 口语:如果音频明显读了
一百二,需要由对齐工具(Alignment)或人工修正。如果做不到,一定要统一规范,哪怕与个别音频不符,也比标签混乱要好。
4.4.2 英文与字母 (Mixed Script)
在中文 ASR 中,英文通常作为外来词处理。
-
大小写:强制大写。ASR 声学特征不包含大小写信息,区分大小写只会造成词表膨胀(Word, word, WORD 占三个 ID)。 *
iPhone->IPHONE -
逐字母 vs 逐单词: * Acronyms (缩写):
IBM->I B M(按字母读)。 * Words (单词):APP->APP(按词读 /æp/) 还是A P P? * 实战策略:建立一个常用词白名单(如 WiFi, App, Plus, Pro),名单内的保持单词形式,名单外的默认按字母拆分(或者全按字母拆分,取决于你的业务场景)。
4.4.3 标点符号
- 训练时:通常去除所有标点,或仅保留逗号和句号作为“静音/停顿”的标记。
- 特殊符号:
+(加/plus),#(井号),&(and/和)。必须在 TN 阶段转写为汉字或英文,不能直接丢弃。
4.5 中文 ITN (Inverse TN):推理侧的门面
ITN 负责把 二零二三年 变回 2023年。
4.5.1 WFST vs 神经模型
- WFST (加权有限状态机):
- 基于 Thrax (Kaldi) 或 Pynini (Nemo)。
- 优势:100% 可控。绝对不会把
五百转成5000。 -
劣势:无法处理语义歧义。例:
七一是71还是七月一日(建党节)? -
神经 ITN (Seq2Seq / Tagging):
- 使用 BERT/T5 进行改写。
- 优势:上下文感知,能处理
三点五(3.5) vs三点钟(3:00)。 - 劣势:幻觉风险。可能把用户说的
张三改成李四。
Rule of Thumb (工业界): WFST 兜底 + 神经微调。 对于核心数字(金额、电话、身份证),必须走正则/WFST 管道。于语义相关的格式化(如地址、专有名词),可以使用轻量级模型辅助。
4.6 多语种复杂性:方言与脚本冲突
4.6.1 繁体中文 (Traditional Chinese) 与 OpenCC
繁简转换不是一一对应的,必须分层处理。
-
OpenCC 配置选择: *
s2t.json: 仅字形转换(发 -> 發/髮 不分)。不推荐用于最终输出。 *s2twp.json(Simplified to Traditional Taiwan with Phrases): 强烈推荐。它会处理用词差异(软件->軟體,鼠标->滑鼠)。 -
训练策略: * 将所有繁体语料转为简体进行训练(因为简体数据量大)。 * 如果必须支持繁体输出,在 ITN 阶段挂载 OpenCC 转换模块。
4.6.2 粤语 (Cantonese) 的特殊性
粤语存在严重的书面语(SWC)与口语(Spoken)分离问题。
- 特有字:
嘅(ge3, 的),喺(hai2, 在),冇(mou5, 没)。 - 同形异读:普通的“行”在粤语有 hang4 (走), hong4 (行) 等读音,且分布与普通话不同。
- 混合拼音:很多香港粤语语料包含
Hea,Chur,Jeng等粤拼或英文借词。 - 对齐陷阱:千万不要在 TN 阶段把粤语口语词强制转为书面语(如把音频里的
喺标注改写为在)。这会导致声学模型在听到 /hai2/ 时被强迫学习输出“在”,造成严重错乱。
4.6.3 中日韩 (CJK) 脚本混淆
先生 在中文 (xiān sheng) 和日语 (sensei) 中 Unicode 完全一样。
- 问题:如果不加区分,模型会混淆发音特征。
- 解决方案:
1. LID Token:句子开头加
<ZH>或<JP>。 2. 词表分离 (不推荐):先生_zh,先生_jp。会导致词表爆炸。 3. Prompting (MLLM):在 Prompt 中明确指示 "Transcribe in Japanese"。
4.7 混语 (Code-Switching) 的处理艺术
中英混杂(如“我 check 一下 email”)是当前 ASR 的最大难点之一。
4.7.1 词表与分词 (Tokenization)
这里有一著名的“空格陷阱”。
- Raw:
我check一下email - BPE (SentencePiece) 隐患:如果没有空格,SP 可能会学到
我c,k一这种跨语言的垃圾 Token。 - 最佳实践:
- 在 TN 阶段,强制在中英边界插入空格。
我 check 一下 email- 这样 Tokenizer 能够分别切出中文单字和英文 Subword (
ch,eck),提高泛化能力。
4.7.2 语言标签 (LID Tags)
对于深度的混语(句子内部频繁切换),可以考虑在字符级别加标签(需数据支持):
我<en>check</en>一下<en>email</en>这对由 MLLM 进行流式预测特别有帮助,能提示模型切换声学编码器或语言模型状态。
4.8 面向 MLLM 的新文本观
在大模型时代,RAG (检索增强生成) 对 ASR 的输出格式提出了新要求。
4.8.1 ITN as "Canonicalization" (规范化)
RAG 依赖文本匹配。
- 数据库:
iPhone 15 Pro - ASR Raw:
爱疯十五 pro(检索失败) - ASR ITN:
iPhone 15 Pro(检索成功)
新趋势:ASR 模型的输出不再是终点,而是 LLM 的输入。因此,TN/ITN 的目标从“给人看”转向了“给机器看(检索/API调用)”。这要求 ITN 必须具备实体链接 (Entity Linking) 的能力,即热词纠错。
4.8.2 Instruction Tuning 替代正则
我们可以不再写复杂的日期正则,而是训练模型听懂指令:
Prompt: "转写为简体中文,将所有时间格式化为 HH:MM,将货币转为 ISO 代码。"
这虽然灵活,但在高精度场景(医疗、金融)下,传统的 ITN 依然是防止幻觉的最后一道防线。
4.9 本章小结
- Unicode 清洗是第一定律:NFKC + 全角转半角,不做这一步后续全是无用功。
- 训练求真,输出求美:TN 负责还原发音细节(消除歧义),ITN 负责还原书写规范(符合阅读)。
- 空格是混语的朋友:中英边界必须加空格,辅助 Tokenizer 切分。
- 粤语不要强转书语:保留
喺、嘅等口语字,否则声学模型会崩。 - WFST 不死:在工业级 ITN 中,有限状态机依然比大模型更可靠、更低成本。
4.10 练习题
基础题
- TN 实战:将文本
2023年,增长率是3.5%。转换为标准的口语训练文本(汉字形式)。 - 清洗:给定脏数据
123 ABC(中间含全角空格),经过标准清洗流程后的结果应该是什么? - 混语处理:对于输入
I love AI技术,在送入 SentencePiece 训练前,推荐的预处理格式是什么?
挑战题
- 时间歧义:设计一套规则或逻辑,区分文本中的
12:00应该读作十二点还是十二比零(比分)? - 粤语策略:如果你有一批粤语数据,标注是书面语(如标注为“他在哪里”,但音频读的是“佢喺边度”),你应该如何处理这批数据用于训练?
- ITN 架构:如果要构建一个支持热词更新(如出的手机型号)的 ITN 系统,你会如何结合 WFST 和 神经网络模型?
点击查看参考答案与提示
基础题答案
- 答案:
二零二三年增长率是百分之三点五(注意标点通常去除或映射为静音)。 - 答案:
123 ABC(全角空格转半角,全角字母转半角)。 - 答案:
I love AI 技术(英文和中文之间插入空格)。
挑战题答案
-
思路: * 关键词上下文:检查前后词。如果出现“比赛”、“胜”、“负”、“比分”,则读“比”。如果出现“时间”、“点”、“分”、“凌晨”、“下午”,则读“点”。 * 数值逻辑:时间通常在 0-24 之间,比分无限制。
78:60肯定是比分。 -
思路: * 方案一(最佳):丢弃或重新标注。错误的声学对应是训练毒药。 * 方案二(补救):使用强力的粤语 GMM-HMM 强制对齐工具,允许发音词典中有“他->kui5”的映射,尝试自动修正文本。但如果差异过大(字数都不同),对齐会失败,此时应丢弃。
-
思路: * 架构:Text -> [WFST 热词匹配器] -> [通用 ITN 模型]。 * WFST 层:编译一个包含所有新手机型号、人名的 FST,具有最高优先级。如果匹配成功,直接输出标准写法。 * 神经层:如果 WFST 未匹配,交给模型处理通用的数字、日期格式化。 * 这样既保证了新词(热词)的实时生效,又利用了模型的泛化能力。
4.11 常见陷阱与错误 (Gotchas)
陷阱 1:时间戳漂移 (Timestamp Drift)
- 现象:在做 TN 时,如果你把
100(3个字符) 变成了一百(2个字符),原有的字级别时间戳(如果你有)就会失效或错位。 - 对策:TN 必须在生成对齐/时间戳之前完成。如果是做 Diarization + ASR 联合训练,任何文本长度的改变都必须同步更时间戳映射。
陷阱 2:不小心把 <UNK> 训练进去了
- 现象:清洗代码没写好,把无法识别的特殊符号(如 Emoji 🚀)全部替换成了字符串
<unk>,结果模型真的学会了读“unknown”。 - 对策:清洗时直接删除 Emoji 和乱码,或者在计算 Loss 时 mask 掉这些位置,千万不要作为普通文本训练。
陷阱 3:过度归一化 (Over-Normalization)
- 现象:把所有的“五一”都转成了“5月1日”。结果用户原本想说的是“五一广场”(地名)或“五一劳动节”。
- 对策:ITN 的正则规则不能太贪婪。对于地名、专有名词,需要基于命名实体识别(NER)或词典保护,防止误伤。
陷阱 4:忽略了英文的连字符
- 现象:
Wi-Fi被简单去标点变成WiFi或Wi Fi,导致词表里同时出现Wi和Fi两个罕见词,而不是WiFi这个常见词。 - 对策:在去标点之前,先处理特定的字符词汇。
下一步:搞定了文本,我们的“燃料”就纯净了一半。下一章(Chapter 5),我们将把目光转向音频本身,探讨如何从嘈杂的录音中切分出干净的语音片段 (VAD) 以及处理致命的重叠语音 (Overlap)。