ITN 逆文本规范化:把「二零二五年」变成「2025 年」
ITN(Inverse Text Normalization,逆文本规范化)是语音识别后处理里的一步文本改写,它把识别模型吐出的口语形式转成人习惯阅读的书面形式:「二零二五年」变成「2025 年」,「百分之三十」变成「30%」。
方向很重要,先钉死:ITN 用在 ASR 后端,从口语到书面。后面会讲到还有一个方向相反的兄弟叫 TN,这两个最容易被记混。
ITN 处在整条链路的哪个位置
在语音识别的四个环节里,ITN 属于最后一环——文本后处理。声学模型和解码器的输出是一串”听到什么写什么”的文字,它忠实还原了说话人的发音,但没有把「二零二五」还原成阿拉伯数字的义务,也不知道「块」应该写成「元」还是保持口语。
这一步不能省,因为下游几乎所有用途要的都是书面形式:转写稿给人读,纪要要检索,语音填单要把金额存进数据库。让用户自己把「三千五百二十」心算成 3520,是把工程的活推给了用户。
一张转换类型对照表
ITN 不是一件事,是一堆规则的集合。下面这张表把常见类型摊开,最后一列是每类真正的麻烦所在:
| 原始识别结果 | 期望输出 | 属于哪类规则 | 难点在哪 |
|---|---|---|---|
| 二零二五年八月二十四号 | 2025 年 8 月 24 日 | 日期 | 「号」要不要改成「日」取决于文体;「二零二五」和「两千零二十五」是同一个数不同读法 |
| 下午三点半 | 15:30 / 下午 3:30 | 时间 | 十二小时制还是二十四小时制要看业务;「两点」既可能是时间也可能是数量 |
| 三千五百二十块八 | 3520.8 元 | 金额 | 「块」「毛」「角」是口语单位,末位省略很常见(「八」是八角不是八元) |
| 百分之三十点五 | 30.5% | 百分比 | 「百分之」在前、数字在后,与中文数字的连读边界容易切错 |
| 幺三八幺二三四五六七八 | 13812345678 | 电话号码 | 「幺」等于 1 只在逐位读数时成立;串长和分段格式无统一标准 |
| 订单号 A 幺二三 | 订单号 A123 | 编号 | 字母与数字混排,且编号必须逐位、绝不能合并成「一百二十三」 |
| 一米八 | 1.8 米 / 1 米 8 | 单位 | 中文口语把单位插在整数与小数之间,还原成哪种写法没有唯一答案 |
| 第三十二届 | 第 32 届 | 序数 | 「第一」这类短序数改成阿拉伯数字反而更难读,通常保留汉字 |
这张表可以直接当作测试用例的种子:照着这八类各造几十条真实业务里的说法,比拿公开测试集跑分有用得多。
与 TN 的镜像关系:一对反向操作
语音合成(TTS)的前端有一个步骤叫 TN(Text Normalization,文本规范化),做的事情正好反过来:
| ITN | TN | |
|---|---|---|
| 用在哪 | ASR 后端 | TTS 前端 |
| 方向 | 口语 → 书面 | 书面 → 口语 |
| 例子 | 「二零二五年」→「2025 年」 | 「2025 年」→「二零二五年」 |
| 服务对象 | 要读文字的人和程序 | 要发音的声学模型 |
为什么 TTS 需要反着来?因为声学模型学的是”文字怎么发音”,而阿拉伯数字 2025 没有唯一读法——是年份就读「二零二五」,是数量就读「两千零二十五」,是编号就逐位读。前端必须先替它做决定,把歧义消掉再往下送。这部分的完整展开见 TTS 前端在做什么。
有意思的是:两个方向共享同一批歧义。ITN 要判断「一二三」该不该并成 123,TN 要判断 123 该不该拆成「一二三」——同一个坑,从两侧各踩一次。
两条实现路径
规则 / WFST
用有限状态转换器把”什么形式转成什么形式”写成可组合的转换规则。特点是:
- 可控。改一条规则只影响这一条,不会牵动别的。
- 可解释。出错时能定位到具体哪条规则匹配了,而不是”模型觉得应该这样”。
- 易加规则。业务方今天说金额末位要保留两位小数,加一条就行,不用重训。
代价是覆盖面靠人力堆,长尾说法总会漏,规则多了优先级也会打架。
神经网络
把 ITN 当成一个序列到序列的改写任务来学。覆盖面广,见过的说法变体多,不需要人一条条枚举。
但它有一个规则路径没有的风险:会出意外错误。规则漏掉一条,最坏结果是原样输出;模型出错则可能凭空改掉一个不该改的字,而且很难预判它下次在什么输入上犯病。金额、账号这类错了代价很高的字段上,这种不可预测性尤其难接受。
工业系统常是混合的
实际做法通常是先用规则处理高频且确定的模式(日期、时间、百分比这类形式规整的),剩下的交给模型兜底:既守住高频路径的可控性,又不至于被长尾说法卡死。
核心难点:歧义
上面两条路径的差距,主要就体现在歧义上。
同样是「一二三」,可能是 123,也可能是门牌号或密码的逐位读法。用户报手机号、验证码、房间号时都是逐位读的,这时合并成一个整数就彻底错了。真实的判断依据是上下文:前面有没有”手机号是""房间”这类线索词,这串数字有多长,停顿节奏如何。
类似的例子还有一串:
- 「两点」:是时间(14:00)还是数量(2 个要点)?
- 「一米八」:写成 1.8 米还是 1 米 8?前者更书面,后者更贴近原话,选哪个是产品决定,不是技术决定。
**这类判断纯规则做不到。**规则能看到的只是字符串本身,看不到”这句话在说什么”。这也是为什么神经网络路径在 ITN 里始终有位置——不是因为它更准,而是因为有一部分判断本质上需要语义。
为什么 ITN 经常被低估
用户看到的只有最终那段文本。ITN 错了,用户的反馈是”识别不准”,但声学模型可能一个字都没听错。
这是典型的归因错位。同一段音频,模型正确听出了「三千五百二十块八」,ITN 却写成「3520 块 8」或干脆原样输出,用户体感就是”这玩意儿不行”。团队照着这条反馈去换声学模型、加训练数据,会发现怎么改都没用——问题根本不在那一环。
语音识别的四个环节那篇里有一张故障定位表,其中”数字、日期、金额格式不对”这一行指向的就是 ITN。**遇到格式类抱怨,先看后处理,再动模型。**这个顺序能省掉大量无效工作。
评测的坑:ITN 的错误常被洗掉
这个坑会系统性地让成绩偏好看。
很多评测流程在算分前会做归一化:去掉标点、统一大小写、把数字统一成汉字形式再比对。初衷是让不同系统可比,避免一个写 2025、一个写「二零二五」就被判成全错。
但副作用是:ITN 的错误在这一步被抹掉了。参考文本和识别结果都被拉回汉字形式,ITN 做得好不好完全不影响分数。于是评测报告上的准确率是”声学模型的准确率”,而用户实际用到的是”整条管道的准确率”,两者之间隔着一整个后处理环节。
这属于准确率被高估的常见情况之一。解决办法不复杂:评测时保留一组不做归一化的原始对比,专门盯格式类错误;再配一组只针对上面那八类转换的专项用例。中文按字算错误率的口径见 CER 是怎么回事。
常见问题
问:ITN 能不能交给识别模型自己顺便输出?
可以,确实有模型直接输出带格式的规范文本。但拆成独立一环仍然普遍,原因是可诊断、可替换、可按业务改规则——金融场景要金额精确到分,改一条规则就能满足,重训模型不划算。
问:ITN 和标点恢复是同一件事吗?
不是。标点恢复解决的是”哪里该断句、该用什么标点”,是逐 token 的序列标注任务;ITN 解决的是”这串字该写成什么形式”。两者都在后处理这一环,通常前后脚执行,但模型和评价方式完全不同。详见标点恢复是怎么做的。
问:怎么判断我的问题出在 ITN 而不是识别本身?
把识别结果和真人转写逐条对照,看错的是内容还是形式:字词都对、只有数字和格式不对,那就是 ITN。更直接的办法是拿关掉 ITN 的原始输出对比一下。
问:ITN 出错能不能靠加规则一劳永逸?
形式规整的类型可以,比如百分比、日期。但依赖上下文的那部分不行——「一二三」到底怎么写取决于这句话在说什么,规则再多也补不上语义。务实的做法:高频确定的用规则守住,剩下的接受一定错误率,并在金额、账号这类高代价字段上做格式校验。
相关阅读
- 语音识别是怎么工作的:从声波到文字的四个环节
- 准确率被高估的几种常见情况
- 中文语音识别为什么用 CER 而不是 WER
- 标点恢复:ASR 的句号是怎么补上去的
- TTS 前端在做什么:文本规范化、注音与韵律
本文讲的是语音识别后处理领域的通用原理,不绑定某一个具体实现。 各家系统的 ITN 覆盖范围、默认开关与可配置程度差异很大,请以你所用系统的官方文档为准。 我们没有对文中提到的任何方案做过性能实测,因此不给准确率、速度一类的数字。