1. Motivation

文本正则化(Text Normalization,TN)和反正则化(Inverse Text Normalization,ITN)是构建一个完整的语音交互系统不可或缺的部分。前者广泛用于语音合成系统的前端处理,而后者则在语音识别系统的识别文本上屏显示时影响着字幕的观感体验。

当前学术界中被广泛研究的 TN / ITN 系统主要有三种类型:

  • 基于语法规则的 WFST [1]:这种系统由大量特定于语言的语法组成,优点是准确可控,可以快速修 bug ,缺点是对于容易产生歧义的文本不够鲁棒。

  • 基于神经网络的端到端模型 [2]:构建这种模型时,挑战从撰写更精确的语法规则变成了标注和收集覆盖范围更广的数据。端到端模型的一个主要缺点是会产生无法恢复的错误,这时经系统转换后的文字可能在语法上是合理的,但却与原始文本的语义大相径庭。此外,对于 badcase 的修复也不如规则的方式快捷。

  • 同时使用规则语法和神经网络的混合系统 [3]:在混合框架中,只有当系统没有找到匹配的语法规则才会转用神经网络。这种方式比较好地权衡了规则和 NN 的优劣,但是对计算资源提出了更高的要求。

鉴于以上三种系统的优劣,WeTextProcessing 选择实现基于语法规则的WFST 方案。在全球范围内的开源TN/ITN 项目中,目前受众最广泛的是谷歌公司推出的C++ 框架 Sparrowhawk [4] 。该框架的不足之处是它仅仅是一个规则执行引擎,谷歌公司并没有开源相关语言的语法规则。此外,Sparrowhawk 的实现依赖了许多第三方开源库(包括 OpenFst 、Thrax 、re2 、protobuf ),导致整体框架不够简便、轻量化。另一个较为成熟的项目是英伟达公司开源的 nemo_text_processing [5],该项目依旧使用Sparrowhawk 作为生产环境下的部署工具。与谷歌不同的是,该项目还开源了诸如英语、德语、俄语等多种语言的规则语法。在中文 TN / ITN 规则领域,Jiayu 等第三方个人开发者曾开源出一套定制化的中文 TN / ITN 规则库 chinese_text_normalization [6]

站在这些优秀开源项目的肩膀上,WeTextProcessing秉承 简单易用 和Production First & Production Ready 的原则,为中文专门设计和实现一款开源易用的 TN / ITN 工具,它不仅仅包含了包含一套完整的中文 TN / ITN 规则语法,同时也提供了一个可以一键 pip install 使用的 py工具包以及比Sparrowhawk 依赖项更少(生产环境下仅依赖 OpenFst )的整体更轻量化的 C++ 规则处理引擎。

2. 快速上手

一键install,六行代码搞定文本处理!

# installpip install WeTextProcessing
# tn usage>>> from tn.chinese.normalizer import Normalizer>>> normalizer = Normalizer()>>> normalizer.normalize("2.5平方电线")# itn usage>>> from itn.chinese.inverse_normalizer import InverseNormalizer>>> invnormalizer = InverseNormalizer()>>> invnormalizer.normalize("二点五平方电线")

3. 技术细节

TN 和 ITN 的流程都是包含三个部分:Tagger, Reorder 和 Verbalizer。Tagger 负责对输入的文本进行解析,得到结构化的信息。Reorder 负责对结构化信息进行顺序的调整。最终 Verbalizer 负责将重排序之后的结构化信息拼接起来。

3.1 TN 流程

3.2 ITN 流程

3.3 语法规则设计

WeTextProcessing 使用 pynini [7] 来编写和编译规则语法,规则语法可以将一个字符串转换为另一个字符串。规则语法通常可以表示为一个 WFST,pynini 的底层使用了 OpenFst 来实现 WFST 相关的功能。使用 pynini 编写的规则语法示例如下图所示:

该规则描述了对数字的转换。其中

  • digits = zero | digit 的 | 操作符表示 WFST 理论中的 union 操作;

  • cross('十', '1') 表示 WFST 理论中弧上的输入是“十”,输出是“1”,WFST 从一个状态转到另一个状态时若经过该弧则说明系统匹配到了“十”并成功将其转换为了“1”;

  • delete('十') 表示弧上的输入是“十”,输出是空,即经过该弧时会删除“十”;

  • digit + delete('十') 中 + 表示WFST理论中的 concat 操作,它将两个fst连起来;

  • accep('兆') 表示弧的输入和输出都是“兆”,此时 WFST 相当于一个 FSA;

  • addzero**2addzero**3 分别表示将 addzero 重复两次和三次;

  • digits.ques 和 digits.plus 则分别表示将 digits 重复零到一次 和 重复一到无穷次

此外还有一些语法特性,比如下图中:

  • add_weight(Char().tagger, 100) 表示为 Char().tagger 这条路径赋予权重(路径长度)为 100。当有多条路径都可以匹配当前输入时,我们取最短路径作为终选结果。例如“一点零五分”最终会被 ITN 成 “1:05” 而不是 “1.05分”。

  • insert(' ') 表示弧上的输入和输出分别是“”和“ ”,即经过该弧时会强制插入一个空格。

  • processor @ tagger.optimize() 中 @ 表示将两个 fst 进行 compose 操作,optimize() 表示对 tagger 进行 epsilon-removal,determinization 以及 minimization [8]

  • '[EOS]' 表示正则表达式中匹配到的 string 的结尾,同理这里没有列出的 '[BOS]' 则表示开头 [9]

更多详尽的说明请参考pynini 的相关文档 [7]。对于本文所构建的所有WFST,我们采用 OpenFst 中默认的热带半环作为其类型,做出这个选择的原因是此类型对求网格图中的最短路径的操作有效率优势,其路径权重的计算仅需对沿路径的所有弧的权重进行简单求和。

4. 进阶用法

  • 4.1 如何快速修 badcase

当遇到 badcase 的时候,我们首先需要确定 badcase 属于什么类型,日期?时间?还是分数等等?是没有转换,还是转换成了其他类型。然后再去相对应的 rules 中进行修复,可能需要改代码,也可能需要改 tsv 文件。

比如若 ITN 系统将 “三心二意” 错误转成了 “3心2意” 则有两种解决方案:

  1. 在 whitelist.tsv 添加相关的映射放弃相关词汇的转换

  2. 将enable_standalone_number设置为False,此时系统对不带单位的数字不会进行转换

值得注意的是,WeTextProcessing 大多数失败案例是由于上下文歧义或特殊案例造成的长尾问题。例如,“三点五分” 可以是时间 “3:05” 也可以是量词 “3.5 分” 表示运动员得分。编写语法时若考虑更多的上下文可以一定程度上缓解这种情况,例如,如果 “三点五分” 前面有单词 “得到” ,则将其检测为运动员得分。当然,这种打补丁的方式并不能适用于所有情况。出于这个原因,如果想要设计一个能够覆盖 100% 场景的系统,语法的数量将不可避免呈指数级增长。其他常见的失败案例是由于定义不完整。例如,如果没有预定义 “千瓦时” 到 “kwh” 的度量缩写转换,系统将无法转换 “两百千瓦时” 为 “200kwh” 。这个问题相对来说容易解决,仅需在已有的量词类中添加所需的转换规则。

  • 4.2 生产环境部署

对于想要自己对规则进行DIY的用户,可以通过以下方式获得自己的规则文件并部署到不同的环境中。

git clone https://github.com/wenet-e2e/WeTextProcessing.gitcd WeTextProcessing# `overwrite_cache` will rebuild all rules according to#   your modifications on tn/chinese/rules/xx.py (itn/chinese/rules/xx.py).#   After rebuild, you can find new far files at `$PWD/tn` and `$PWD/itn`.python normalize.py --text "2.5平方电线" --overwrite_cachepython inverse_normalize.py --text "二点五平方电线" --overwrite_cache

在已经pip安装好的工具包中使用自己的规则:

# tn usage>>> from tn.chinese.normalizer import Normalizer>>> normalizer = Normalizer(cache_dir="PATH_TO_GIT_CLONED_WETEXTPROCESSING/tn")>>> normalizer.normalize("2.5平方电线")# itn usage>>> from itn.chinese.inverse_normalizer import InverseNormalizer>>> invnormalizer = InverseNormalizer(cache_dir="PATH_TO_GIT_CLONED_WETEXTPROCESSING/itn")>>> invnormalizer.normalize("二点五平方电线")

在C++中使用自己的规则:

cmake -B build -S runtime -DCMAKE_BUILD_TYPE=Releasecmake --build build# tn usage./build/bin/processor_main --far PATH_TO_GIT_CLONED_WETEXTPROCESSING/tn/zh_tn_normalizer.far --text "2.5平方电线"# itn usage./build/bin/processor_main --far PATH_TO_GIT_CLONED_WETEXTPROCESSING/itn/zh_itn_normalizer.far --text "二点五平方电线"

5. 总结和展望

未来,WeTextProcessing 的工作将聚焦在对 Corner Case 的规则修补:相比于规则撰写,设计一套合理的测试集是一件更为困难的事情,这是因为实际生产过程中总会遇到数不清的 corner case 。WeTextProcessing 中虽然提供了一个简单的单元测试和示例测试,但其覆盖场景仍未能达到 100% 。在未来,WeTextProcessing 的重点方向之一就是越来越多地投入部署到真实的线上环境中,以身试错,case by case 分析当前规则存在的可能漏洞并加以弥补。

参考资料

[1] Peter Ebden and Richard Sproat, “The kestrel TTS text normalization system,” Nat. Lang. Eng., vol. 21, no. 3, pp. 333–353, 2015.

[2] Courtney Mansfield, Ming Sun, Yuzong Liu, Ankur Gandhe, and Björn Hoffmeister, “Neural text normalization with subword units,” in Proceedings of the 2019 Conference of the North American Chapter of the Association for Computational Linguistics: Human Language Technologies, NAACL-HLT 2019, Minneapolis, MN, USA, June 2-7, 2019, Volume 2 (Industry Papers), Anastassia Loukina, Michelle Morales, and Rohit Kumar, Eds. 2019, pp. 190–196, Association for Computational Linguistics.

[3] Richard Sproat and Navdeep Jaitly, “An RNN model of text normalization,” in Interspeech 2017, 18th Annual Conference of the International Speech Communication Association, Stockholm, Sweden, August 20-24, 2017, Francisco Lacerda, Ed. 2017, pp. 754–758, ISCA.

[4] Peter Ebden and Richar Sproat, “Sparrowhawk,” 2022, https://github.com/google/sparrowhawk.

[5] Yang Zhang, “nemo_text_processing,” 2022, https://github.com/NVIDIA/NeMo/tree/main/nemo_text_processing.

[6] Jiayu Du, “chinese_text_normalization,” 2022, https://github.com/speechio/chinese_text_normalization.

[7] K. Gorman. 2016. Pynini: A Python library for weighted finite-state grammar compilation. In Proceedings of the ACL Workshop on Statistical NLP and Weighted Automata, pages 75-80.

[8] https://www.opengrm.org/twiki/bin/view/GRM/PyniniOptimizeDoc

[9] https://www.openfst.org/twiki/bin/view/GRM/ThraxQuickTour

WeNet 丨 WeTextProcessing相关推荐

  1. 2020 中国移动的流量套餐

    微信图片_20200902180442.jpg 查看全文 http://www.taodudu.cc/news/show-6041095.html 相关文章: 竞争压力下,运营商终于开打价格战了,中国 ...

  2. 如何解决 Iterative 半监督训练 在 ASR 训练中难以落地的问题丨RTC Dev Meetup

    前言 「语音处理」是实时互动领域中非常重要的一个场景,在声网发起的「RTC Dev Meetup丨语音处理在实时互动领域的技术实践和应用」活动中,来自微软亚洲研究院.声网.数美科技的技术专家,围绕该话 ...

  3. SH-CST 2022丨SpeechHome 语音技术研讨会

    第二届SpeechHome语音技术研讨会将于11月13日线上举行,同时举行开源语音技术交流会即第七届Kaldi技术交流会. 本届研讨会内容覆盖音视频多模态.构音障碍人群的语音研究.前端信号处.跨语种语 ...

  4. VLOG丨树莓派Raspberry Pi 3安装PLEX并挂载USB硬盘打造最牛的微型家庭影音服务器2018...

    视频介绍 树莓派3安装目前最流行的PLEX服务器,实现既能最大限度降低功耗,也能随时随地观看分享影片. 一.在树莓派下安装PLEX媒体服务器 1.在终端,将你的树莓派更新至最新 sudo apt up ...

  5. 换了路由器电脑都连不上网了_技术丨电脑连不上网,我要如何冲浪?

    身为互联网一级冲浪选手 稳定不断的网络连接可谓是生活必备 但,遇见无法上网的情况时 除了重启路由器,还可以怎么办? 在实际生活工作中,常会遇到无法上网的情况,原因较多.解决方案也同样众多,本文筛选了最 ...

  6. 切割图形_模型教程丨切割机使用——结合实例

    点击这里查看上一期教程哦~ 半平米工坊:模型教程丨切割机操作手册​zhuanlan.zhihu.com 不知道大家看了上期的切割教程有没有去实际操作呢~有没有发现一些切割时不知道该如何处理的小问题~ ...

  7. 什么是条件组合覆盖_物史政组合分析,新高考最终受益者丨选科17期

    导读 ,规划 物理历史政治是新高考3+3模式下存在的选科组合,为了给马上面临选科问题的高一.高二考生提供有效帮助,自主选拔在线选科模型解读第17期就来分析一下该组合的学科特性.适合人群.优势劣势.专业 ...

  8. 计算机笔试图形推理题,【笔记】教资笔试丨4分钟掌握信息处理以及逻辑判断!...

    原标题:[笔记]教资笔试丨4分钟掌握信息处理以及逻辑判断! 模块五 基本能力 第十四章 信息处理能力 核心原则 1:便民原则 计算机操作目的是方便快捷,如违背此原则可快速排除: 核心原则 2:英语思维 ...

  9. ACL 2022丨香港大学华为诺亚方舟新工作:生成式预训练语言模型的量化压缩

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 近日,香港大学与华为诺亚方舟实验室在 ACL 2022 上联合发表了 ...

最新文章

  1. CentOS5.5环境下布署LVS+keepalived
  2. Qt中的QBoxLayout
  3. 【推导】Codeforces Round #364 (Div. 2) D. As Fast As Possible
  4. 【Qt】2D绘图之双缓冲绘图
  5. 【渝粤教育】国家开放大学2018年春季 0025-22T数据结构 参考试题
  6. python 的笔记
  7. pip install mysqlclient 报错:error: Microsoft Visual C++ 14.0 is required.
  8. Rust: 亿元估值AI网红代码的不同版本
  9. 亚洲前沿科技展望:人工智能与区块链的融合发展
  10. 2018.3.4 st
  11. Tupper‘s Self-Referential Formula 塔珀自指公式
  12. 修复IE默认主页——注册表篇
  13. 多维数组存储的两种方式
  14. 数据分析京东笔记本电脑
  15. Appium+python+夜神模拟器微信公众号 记录第一次写用例所踩的坑
  16. python 开源cms内容管理系统_30 个很棒的 PHP 开源 CMS 内容管理系统
  17. Android面试问答题
  18. 利用VBA代码解决Excel下拉菜单跳过空单元格的问题
  19. 俞敏洪:不要为眼前的得失而抓狂
  20. .set_global_opts(title_opts) 设置标题

热门文章

  1. android蓝牙键盘光标,如何将Android手机连接到无线蓝牙鼠标?
  2. CI框架去掉index.php以及解决No input file specified问题
  3. 拽一个贵人出来给你当炮架子
  4. 企业生产中,APS系统有哪些具体应用场景?
  5. 【读书联动】认知觉醒:开启自我改变的原动力
  6. 深圳东部公交WIFI试用体验
  7. 三流Java撸代码,二流Java搞框架,一流Java…
  8. CS224n笔记——Subword Model(十二)
  9. JavaScript 美术馆(改进2)
  10. 三菱FX系列PLC以太网连接力控ForceControl