9.4 KiB
g2p 字典设计
本文主要讲语音合成的 g2p (grapheme to phoneme) 部分。
代码: generate_lexicon.py (代码可能与此处的描述有些许出入,以代码为准,生成的带 tone 带儿化的 pinyin 字典参考 simple.lexicon)
ARPAbet
对于英文 TTS,常用的 g2p 是通过查询 CMUDict 来实现,而 CMUDict 注音使用的系统是 ARPAbet,具体含义参见 CMU 发音词典。
它包含 39 个 phoneme, 不包含音词汇重音的变体:
Phoneme | Example | Translation |
---|---|---|
AA | odd | AA D |
AE | at | AE T |
AH | hut | HH AH T |
AO | ought | AO T |
AW | cow | K AW |
AY | hide | HH AY D |
B | be | B IY |
CH | cheese | CH IY Z |
D | dee | D IY |
DH | thee | DH IY |
EH | Ed | EH D |
ER | hurt | HH ER T |
EY | ate | EY T |
F | fee | F IY |
G | green | G R IY N |
HH | he | HH IY |
IH | it | IH T |
IY | eat | IY T |
JH | gee | JH IY |
K | key | K IY |
L | lee | L IY |
M | me | M IY |
N | knee | N IY |
NG | ping | P IH NG |
OW | oat | OW T |
OY | toy | T OY |
P | pee | P IY |
R | read | R IY D |
S | sea | S IY |
SH | she | SH IY |
T | tea | T IY |
TH | theta | TH EY T AH |
UH | hood | HH UH D |
UW | two | T UW |
V | vee | V IY |
W | we | W IY |
Y | yield | Y IY L D |
Z | zee | Z IY |
ZH | seizure | S IY ZH ER |
另外还包含三个重音标记,
0 — No stress 1 — Primary stress 2 — Secondary stress
其中重音标记附在元音后面。当只需要音标而不需要重音标记的时候也可以直接省略。
CMUDict 只是一个词典,当出现了不在词典中的词时(OOV),可以求助其他工具可以根据拼写得到对应的发音,如:
中文注音系统
中文普通话的注音系统存在许多套,比如汉语拼音 (pinyin), 注音符号 (bopomofo), 国语注音符第二式, 威妥玛拼音等。而且有一些并非注音方案,是拉丁化方案,因此为了符号系统的经济性,会做一些互补符号的简并,比如汉语拼音中的 i
的代表了三个音位, e
代表了两个音位(单用的情况很少, 单用时写作 ê
);也有一些简写,比如 bpmf
后的 o
是 uo
的简写, ui
是 uei
的简写, iu
是 iou
的简写, un
是 uen
的简写, ao
是为了书写避免形近而改掉的 au
, y
和 w
是为了连续书写时作为分隔而产生的零声母, ü
在 j
、 q
、 x
后面省略两点(中国大陆使用美式键盘打字的时候,一般只有在“女”、 “律”、“略”和“虐”这一类的字里面用 v
代替 ü
,而在 j
、 q
、 x
后面的时候则仍用 u
),有鼻韵母 uang
而没有 ueng
,但是又有 weng
这个音节之类的问题, 有 ong
韵母但是又没有单用的情形。其实这些都是汉语拼音作为拉丁化方案而做的一系列的修改。
另外,汉语的声调是用了特殊符号来标调型,用字母记录的时候常用 12345
或者 1234
、轻音不标等手段。
另外还有两个比较突出的问题是儿化和变调(参考 zh_text_frontend)。对于具体的数据集,也可能有不同的标注方案。一般我们为汉字标音是标字调而不标变调,但是标贝数据集是标变调的(但是也没有把所有的变调都正确标出来)。儿化在汉语书写和拼音中也是一个比较麻烦的事情,虽然正字法中说到可以用小字号的儿表示儿化,但是这种发音由字号这种排版要素来表达的手法未免过于崎岖,所以鲜见有人真的这么排版,只有在某些书籍中,强调此事的时候见过。另外,在儿化的标音方式上,鼻韵母需要去掉韵尾然后换成 r,这么一来,如果直接抽取拼音的字符串表示,那么可能出现的音节就会超过 1400, 甚至进入一种含糊的状态,不清楚一共有多少个有效音节,即使是韵母,也会因此扩展近一倍。
因为存在这样的情形,再考虑到不同的数据集自带的拼音 transcription 的风格可能不同,所以需要考虑进行转换,在内部转成统一的表示。既然这个过程是必要的,那么我们可以大胆设计一个内部方案。
这里设计的原则是:
-
有效符号集仅切分为声母和韵母,不作声母,介音,韵腹,韵尾的切分;
-
尽可能把不同的音用不同的符号表示,比如
i
的e
会被拆分为 3 和 2 个符号,u
和ü
开头的韵母分开,这是为了 TTS 系统的建议性考虑的,我们选择尽量反映语音的现实情况,而不把注音系统里面的奇怪规则留给模型去学习; -
不包含零声母
y
,w
之类的形式上的符号,因为如果这些符号不发声或者发声极短,那么可以不加入音符序列中,以期待 attention 更对角; -
声调和韵母不结合为一个符号,而是分开,这样可以减少词汇量,使得符号的 embedding 得到更充分的训练,也更能反映声调语言的特点(数据集少时推荐这么做);
-
儿化的标音方式采用拆分的方式处理, 但是增设一个特殊符号
&r
来表示儿化的r
,它和一般的er
不同,以区分实际读音的区别。 -
更加贴近注音符号,把
in
写作ien
,ing
写作ieng
,un
写作uen
,ong
写作ueng
,iong
写作üeng
。其中in
和ing
的转写纯属偏好,无论用什么符号写,都可以被转为一个 index, 只要它们的使用情况不发声变化就可以。而ong
写作ueng
则是有实际差别的,如果ong
作为一个韵母,那么weng
经过修改之后会变成ueng
, 就会同时有ueng
和ong
。而如果不细究音值上的微妙差异,ong
就是ung
的一种奇怪表示, 在注意符号中, 它就记作ㄨㄥ
。而iong
则是ㄩㄥ
。 -
ui
,iu
都展开为uei
和iou
, 纯属偏好,对实际结果没有影响。bpmf
后的o
展开为uo
,这个则是为了和单独的o
区分开(哦, 和波里面的韵母的发音其实不同)。 -
所有的
ü
都有v
代替,无论是单独作韵母, 还是复韵母和鼻韵母。 -
把停顿以
#1
等方式纳入其中, 把<pad>
<unk>
<s>
</s>
这些为了处理符号系列的特殊符号也加入其中,多一些特殊词汇并不会对 Embedding 产生什么影响。
于是我们可以的通过一套规则系统,把标贝的拼音标注转换成我们需要的形式。(当然,如果是别的数据集的实际标注不同,那么转换规则也要作一些修改)
在实际使用中文数据集时,我们仅使用其提供的拼音标注,而不使用音素标注(PhoneLabel),因为不同的数据集有不同的标注规则,而且有的数据集是没有音素标注的(如,aishell3)
我们的做法和维基百科上的汉语拼音音节列表更接近 汉语拼音音节列表
转换之后,符号列表是:
声母基本没有什么争议,共 21 个:
声母 |
---|
b |
p |
m |
f |
d |
t |
n |
l |
g |
k |
h |
j |
q |
x |
zh |
ch |
sh |
r |
z |
c |
s |
韵母和儿化韵尾(共 41个)
韵母 | 解释 |
---|---|
ii | zi ,ci , si 里面的韵母 i |
iii | zhi , chi , shi , ri 里面的韵母 i |
a | 啊,卡 |
o | 哦 |
e | 恶,个 |
ea | ê |
ai | 爱,在 |
ei | 诶,薇 |
ao | 奥,脑 |
ou | 欧,勾 |
an | 安,单 |
en | 恩,痕 |
ang | 盎,刚 |
eng | 嗯,更 |
er | 儿 |
i | 一 |
ia | 鸦,家 |
io | 哟 |
ie | 叶,界 |
iai | 崖(台语发音) |
iao | 要,教 |
iou | 有,久 |
ian | 言,眠 |
ien | 因,新 |
iang | 样,降 |
ieng | 英,晶 |
u | 无,卢 |
ua | 哇,瓜 |
uo | 我,波 |
uai | 外,怪 |
uei | 位,贵 |
uan | 万,乱 |
uen | 问,论 |
uang | 网,光 |
ueng | 翁,共 |
v | 玉,曲,ü |
ve | 月,却 |
van | 源,倦 |
ven | 韵,君 |
veng | 永,炯 |
&r | 儿化韵尾 |