最近发现 ASR/VC/TTS 三个不同的项目中都会有所涉及中文不同发音单元所造成的影响,这篇笔记总结一下相关经验。
中文里不同的发音单元
举个简单的例子:text:集火那个剑魔,
几个不同粒度的发音单元如下。可以看出从 mode0~3, 发音单元逐渐变细。
mode0: 集 火 那 个 剑 魔
mode1: ji2 huo3 na4 ge5 jian4 mo2
mode2: j i2 h uo3 n a4 g e5 j ian4 m o2
mode3: j i2 h u o3 n a4 g e5 j i a n4 m o2
对于识别任务,seq2seq method 倾向于用 mode0 ,直接对字进行建模(实验验证,该方案字错误率最低) 对于基于Kaldi-hybrid model,因为涉及到一些三音素聚类等trick和wfst解码,使用了类似 mode2 的粒度。
下面重点介绍下在几个不同的领域上对这个问题对探索。
不同发音单元 在ASR(wenet)上的表现。
训练代码均为wenet官方代码,训练数据 3770 hours。
m0实验结果
test-set | cer |
---|---|
swk | 20.76% |
zhiling | 8.01% |
m3实验结果
initial:不带音调的音素(包括声母和双/三韵母中非最后一个),tone:带音调的音素 测试集tone和非tone出现数目占比,initial : tone ~= 57 : 35
cer: Overall/initial/tone
method | 12epoch | 22epoch |
---|---|---|
swk | 9.24/4.12/17.52 | 8.81/3.87/16.81 |
zhiling | 4.73/0.97/11.04 | 4.44/0.80/10.57 |
结论:CTC对带音调字符的预测准确率不够。(和songxiang结论吻合。)
不同发音单元在 VC 上的表现
对于VC来说,ASR-based ppg几乎已经成为了主流方案。论文中不提,但几乎所有 vc 系统都会面临的两个问题:
- 发错字音的问题,特别是音调。某个字二声发成了四声,可懂度直线下降。
- 语速过快情况下漏字的问题。正常语速(播报等场景)下完美的系统,快语速下 badcase 飞速上升。特别是某些音发虚之类的情况频繁发生。
无论是基于 ctc 一类的方案还是 ce 一类的方案,以上两个问题都会频繁发生。但我自己在把 vc 系统做上线的过程中,会显著发现 m3 比 m0效果要好。 当时做了大量实验以及理论分析,后续会单独写一篇文章来介绍下 ppg extractor 的相关细节以及怎样规避如上两个问题。这里先暂时不展开。
不同发音单元 在 TTS 上的表现。
在 TTS 任务中, 我们统一使用 mode3 进行建模。该方案有两个好处。
- 音素粒度较细,使得总音素数量较少。在数据量不够时,覆盖程度更广。
- 每个音素对应时长大致相等,有助于后续模型学习。(并没有被严格的证明)
M2VOC 比赛回顾
在 m2voc 比赛中, 我们对比了 mode2 和 mode3 两种方案,对应下文的 tradition 和 ours。
例句:
建议你可以先确定首付的数额。(mst_male_000001.txt)
tradition: j ian4 ii i4 n i3 k e3 ii i3 x ian1 q ve4 d ing4 sh ou3 f u4 d e5 sh u4 ee e2
Ours: j i a n4 i4 n i3 k e2 i3 x i a n1 q v e4 d i ng4 sh o u3 f u4 d e5 sh u4 e2
两种方案音素个数统计 tradition:182 ours:84
测试集的音素覆盖情况。统计测试集中从来没出现的音素个数及百分比如下:
method | chat | game | story | s3 | s4 | s5 |
---|---|---|---|---|---|---|
Tranditional | 20/0.11 | 16/0.09 | 7/0.04 | 116/0.64 | 121/0.66 | 75/0.41 |
Ours | 3/0.04 | 3/0.04 | 2/0.02 | 32/0.38 | 31/0.37 | 17/0.20 |
更多比赛相关细节,可以参考对应论文。
结论表明,某些情况下,m3 确实比 m2 更有优越性
另: TTS 中文前端的几个处理要点
怎样处理儿化音
对于儿化音,我们使用了一种新的发音单元来进行标注(不同于普通的儿)。
几个例子,注意儿字在第二个和第三个case中不同的表现。
text: 一会儿干了就好
token: i2 h u er4 g a n4 l e5 j i o u4 h a o3
text: 唱个儿歌
token:ch a ng4 g e4 er2 g e1 累了可以>
text: 来这儿听会儿歌
token:l e i4 l e5 k e2 i3 l a i2 zh er4 t i ng1 h u e i4 er2 g e1
语流变调
现代汉语中,当某个字受到前一个字或后一个字影响从而音调发生改变,我们称这种现象为语流音变。(sandhi or coarticulate) 语流音变是汉语中独特的语言现象, 比较常见的情况有以下几种
- 33->23(当连续两个三声叠加时,第一个三声变为2声。例如,单词老虎,老字拼音标注为3声,实际多发为2声)
- 333-> 323
- “一”。当作量词的时候,四声之前变二声,一二三声之前变四声。eg:一个(24),一种(43),一锅(41),一拳(42)等。
- “不”。 四声之前变二声,一二三声之前变四声。
注意,基于规则的变调处理和分词结果密切相关。
常见的有以下几种方案:
- 不处理。模型自行学到变调规则。
- 使用真实发音(变调后的发音)代替前端预测发音,保证数据之间的强对应关系。
- 使用一个额外的发音音调(6声)来表示该音调经过了语流音变。
实际中经验证,方案一可能会带来少量额外的badcase,方案二和三可以比较好的解决变调问题,实现上各有优劣。
轻声的处理
TTS中轻声也是很关键一环。处理逻辑与其他现象类似。我们可以采用人工标注训练数据+模型预测推理数据的方法进行处理。 实际线上环境下,维护一个轻声词表也是一个不错的选择。
其他
TTS前端问题涉及到很多语言学的知识。之前在知乎看到了大神的文章,从中学到了不少。文章链接
相对来说,数据驱动+深度学习可以大幅降低对语言学知识的依赖,也进一步降低了 TTS 的门槛。