跳转至

文本前端

文本前端#

文本前端在语音合成中扮演的角色#

语音合成,顾名思义,是一项将文本转化为语音的技术。以Google的Tacotron系列为代表的端到端语音合成技术大大降低了语音合成的技术门槛。对于表音语言比如英法西德意等语种,甚至可以直接输入文本,让模型自行学习如何将文本转化到语音。但是在实际的生产环境中,直接文本到语音会带来较大的不可控风险,比如"love"/lʌv/读成了/lɪv/,如何快速纠正类似的发音错误;"2kg"如何指定模型读成"两千克",而非"二kg"等。因此在实际的语音合成系统中,通常会为语音合成系统添加文本前端,主要作用是将文本转换为音素,甚至会添加一些韵律标识构成语言学特征(linguistic feature),以便声学模型更好地建立文本到语音的映射。

文本前端的主要组成#

文本前端一般遵循文本,到规范化文本,到音素这3个基本步骤,同时会从文本和规范化文本中预测韵律。音素和韵律标识统称为语言学特征(linguistic feature)。文本前端的输出作为下游声学模型和声码器的输入,如果发生发音错误等问题,大部分情况下直接修正音素序列即可,大大降低了问题解决的难度。一般来说,文本前端可分为以下五个部分:

  1. 文本预处理:主要是解决文本中书写错误、一些语种中同形异码等问题。

  2. 文本归一化:主要解决文本中的特殊符号读法,比如"2kg"转换为"两千克",另外还要处理一些语种比如波兰语、俄语中的性数格变化。

  3. 分词:一些语种比如中文、藏语、日语、泰语、越南语、维吾尔语、朝鲜语等并非以空格作为词边界,通常需要分词以便后续的处理,但世界上大部分语种都以空格为词边界,该步骤可省略。

  4. 文本转音素(G2P):将文本转换为注音,比如"中国"转化为"zhong1 guo2"。

  5. 韵律分析:语音中每个音素的发音时长不同,停顿也不同。将文本转换为音素之后,通常会加入一定的韵律信息,以帮助声学模型提升合成语音的自然度,加入的韵律信息可以分为音素(L0)、单词(L1)、breath break(L3)和句子(L4)四个韵律层级。

Unicode调研和文本预处理#

开展一个新语种的文本前端的开发,首要是调研该语种文字的字形、读音等,了解世界各语种的好去处无疑是Unicode官网和维基百科。Unicode将世界上所有的字符均分配唯一数字标识,同时为了兼容和节省空间,常常采用"统一码转换格式-8"(UTF-8)、"统一码转换格式-16"(UTF-16)等具体实现该编码。具体来说,可以进入Unicode Code Charts查询各个语种的编码。以最广泛使用的拉丁字符为例,Basic Latin (ASCII)文档中,首先是一页版权声明,之后展示了该类字符的Unicode码,最后是各个字符的简短介绍,帮助快速了解该语种。在介绍时,对于每一个字符,比如"!",首先给出它的Unicode编码"0021"(\(\backslash\)u0021),然后是该字符的字形如"!",接下来一般是该字符的简介比如"EXCLAMATION MARK",之后会给出一些补充信息,比如"="表示该字符的其它含义, \(\to\) 表示该字符的相关字符, \(\equiv\) 表示该字符的同形异码。同形异码在多语种的文本前端中尤其需要注意,例如Latin Extended-A中,\(\backslash\)u0100的同形异码为\(\backslash\)u0041\(\backslash\)u0304,这种同形异码的字符需要统一处理为一种字符,用户的输入看起来相同,但在计算机中的表示是完全不同的。

文本前端中的文本预处理模块主要是处理非法输入、同形异码的替换等。文本前端收到输入之后,可以限制一些边界条件,比如防止用户将音视频输入文本前端,限制输入的字符串长度和种类等;之后就进入包括同形异码替换的文本清理模块。首先是确定输入文本的语种(可要求用户提供或者限制本语音合成系统的主要输入语种);之后是通用处理规则,比如删除"\(\backslash\)u200B"、"\(\backslash\)u200C"等不可见字符,统一标点符号,全角转半角,一些特殊数字如\(\backslash\)u00BD替换为"½"等等;然后是本语系的处理规则,此时主要对同形异码进行替换;然后是本语种的处理规则,主要是处理本语种的外来字符,比如在意大利语中,将奇形怪状的外来字符"Á"、"Ã"、"Ä"、"Å"统一替换为"A",连接词"Æ"替换为"AE";最后是针对不同语种定制的后处理规则。逐级处理的好处是代码、层次清晰,当然为了方便,可以统一进行处理和替换。

相关的参考资料:

  1. Unicdoe搜索

  2. Unicode官网

  3. Unicode术语表(中英互译)

  4. Unicode实用工具

文本规范化#

归一化目前是文本前端中的难点,学术界和工业界最普遍和精确的方法还是靠人肉堆规则,当然也逐渐出现了规则和模型混合的归一化系统,比如A Hybrid Text Normalization System Using Multi-Head Self-Attention For MandarinCold-Start and Interpretability: Turning Regular Expressions into Trainable Recurrent Neural Networks

一个基础的归一化模块至少应覆盖以下几类规则:物理量、货币、缩略语、常用机构名或专有名词、数字(分数/百分数/科学计数法/小数点/基数词/序数词/数字串)、算术表达式、标点符号、日期(月份/星期)的各种表示、时间、比分、网络用语或外来词等。

相关的参考资料:

  1. ICASSP 2020中的语音合成

  2. A Hybrid Text Normalization System Using Multi-Head Self-Attention For Mandarin

  3. Cold-Start and Interpretability: Turning Regular Expressions into Trainable Recurrent Neural Networks

分词#

对于世界上大部分的语种来说,空格是天然的单词边界,因此分词并非一个常见任务,仅有中日韩、泰语、越南语等语种需要分词。"最大最长匹配"是简单且常见的分词算法,该算法需要准备一个词典,在对文本进行切分时,根据切分方向的不同,还可分为前向、后向、前后向最长匹配算法。以"前向最长匹配算法"为例,该方法首先设定一个词的最大长度,将待切分文本开始到词最大长度内的字符作为"候选词",每次扫描时,将该"候选词"和词典中的词进行匹配,如果没有找到,就缩短"候选词"的长度继续寻找,直到匹配到字典中的词或者"候选词"成为单字,然后继续切分剩余文本。为了降低"候选词"和词典匹配的算法复杂度,可以先将词典构建为Trie(称前缀树或字典树),对文本从前到后切分时,每次尝试加入待切分文本的一个字符,并查询当前节点的所有子节点,如果待加入字符存在于子节点中,则沿着该节点继续查询,否则退出该字符,并将之前节点的字符作为切分后的单词,以该字符为起始点作为剩余待切分文本。

为了提高分词的准确率,条件随机场、神经网络等方法也应用到了分词领域并取得了不错的效果。可参考:

  1. NLP分词算法深度综述

  2. 中文分词算法简介

  3. 五款中文分词工具在线PK: Jieba, SnowNLP, PkuSeg,THULAC, HanLP

对于日语来说,也有一些流行的开源词典,比如UniDicmecab-ipadic-neologd,同时也有一些开源分词器比如MeCabKuromojijumanppSudachi等。参见:日语分词器的介绍和比较

对于泰语来说,音节、单词和句子都需要切分。ssg使用条件随机场对泰语文本切分音节,CRF-Cut同样利用条件随机场对文本进行分句。泰语的分词算法同样也有很多,可参见AttaCut-Benchmark了解常用泰语分词算法的评测。

文本转音素#

文本转音素(G2P/LTS)是将文本转换为注音表示的过程。最简单直白的文本转音素方法无疑是查词典,经过预处理和分词模块之后,文本被切分为一个个单词,利用词典查询单词对应的发音序列。但是对于带有缩略词、外来词的文本来说,情况略微复杂,因为查询缩略词、本语种和外来词词典的优先级不同,输出的音素序列有时也会有所不同。一个较好的处理逻辑是,最特殊、最有可能的单词优先处理。首先处理缩略词的发音,如果存在于缩略词词典中或者单词全大写时,则认为是缩略词,如果缩略词词典中有该词,直接输出音素序列,否则按照规则,比如按照每个字母的发音逐个给出发音;之后处理本土词的发音,如果存在于本土词词典中,则认为是本土词,直接从词典中给出音素序列;接下来处理英语单词,如果是英语收录词,则可以直接从词典中取出该英语词的音素序列,获得英语词的音素序列之后,注意要将英语音素转换为本土音素。当然,词典很难覆盖所有词,特别是语种构建的初期,大部分词都是集外词,需要利用一些规则或模型给出单词的发音。构建文本转音素规则的一般步骤是:1. 调研公开资料,了解该语种是否有重音和声调,并制定字符到音素的转换规则,注意音素要抓对立而非音变,比如cat[k]和fat[f]中的[k/f]就是一组对立,不同发音会导致意思发生改变,而tell[l]和telling[l]中的[l]虽然发音也不同,但是属于音变,发音不同并不会改变单词含义;2. 迭代,文本转音素规则,乃至音素体系都是一个迭代的过程,需要结合给定音素与实际模型合成的发音情况,不断完善音素规则。

利用一个基础的词典,可以训练出一个G2P模型,给出任意一个单词的发音序列。同样有一些开源的G2P模型比如

  1. MfaTrainG2p,MfaG2p甚至给出了一些预训练模型

  2. cmusphinx: g2p-seq2seq,基于TensorFlow的Tensor2Tensor库,准确率较高。

当然,可以直接使用一些序列建模方法或者上面的工具,比如Fairseq,类似机器翻译,构建一个G2P模型,以便在语种构建初期,迅速扩充词典。相关的参考资料如下:

  1. The Festvox Indic Frontend for Grapheme-to-Phoneme Conversion

  2. A study on rule based approach for Grapheme to Phoneme conversion of Assamese letters in Festival framework

在产生音素序列之后,有时候还需要按照规则切分音节,并且给重音。特别是多个连续辅音(Consonant)的情形,不同的语种在切分音节时有不同的规则,比如三辅音情形下,如何分配这些辅音所属音节。重音情形也类似,需要根据语种确定重音规则。这些多个连续辅音分配音节,根据规则给定重音实际都需要配合后端模型进行实验,特别是目前端到端声学模型流行的情形下,一些音节的划分、重音的给定位置也许对声学模型并没有影响,而一些语种就有一定的优劣之分。

韵律分析#

韵律分析同样是文本前端的难点之一,一个好的韵律信息可大大提升最终合成语音的自然度。一个简单的韵律规则是,加入单词边界作为L1,句子中标点处作为L3,句末作为L4,但这种规则通常并不是最优的。韵律分析中L3的预测尤为重要,可借助一些简单模型,比如决策树、CRF等,构造L3或者韵律相关的特征,如:前一个单词(L1)内的L0个数、前一个单词(L1)的词性、前前L1内的字符个数、前L1内的字符个数、后L1内的字符个数、后后L1内的字符个数、本字符的ID和前一个空格离本字符的字符距离等。当然也可以使用更为复杂的模型比如LSTM甚至BERT参与韵律分析,将问题转换为对每个字符的二分类(加或不加L3)或者多分类任务(L0/L1/L3)。

文本前端的工程实现#

由于文本前端较为依赖资源,比如文本预处理规则文件、文本归一化规则文件、分词和文本转音素常用到的词典、用于韵律分析的模型等,特别是文本前端常常需要没有代码经验的语种专家参与进来,因此要将资源和代码分离开来,便于工程实现和维护。使用正则表达式作为文本归一化规则的具体实现,在大型的文本前端中缺陷凸现明显:难以阅读和维护,并且规则冲突严重。一个折中的做法是自定义规则文件,将一条条规则以优先级、匹配条件和输出的形式呈现。


最后更新: 2022-04-25

评论

回到页面顶部