FastSpeech阅读笔记

FastSpeech阅读笔记

近日,浙江大学和微软亚洲研究院联合推出了一篇论文,关于快速的端到端的语音合成系统,论文的链接如下:

FastSpeech: Fast, Robust and Controllable Text to Speecharxiv.org

下面是笔者阅读论文后对论文方法的总结和思考,不当之处欢迎指正。

论文首先指出了端到端自回归(Auto Regressive)的语音合成系统存在的问题:

  1. 推理阶段速度过慢(traditional Transformer虽然训练的速度很快,但是推理阶段仍然需要上一时间步的输出,无法做到真正的并行);
  2. 生成的语音不是鲁棒的,有一些单词会被跳过或者重复地生成(这一点笔者在实验的时候真的是深有体会啊,而造成这一原因主要是因为传统语音合成系统的Alignment是隐式的,在推断的过程中,存在着错误对齐的情况);
  3. 无法做到可控(这里笔者的可控应该主要指的是生成的语速方面,因为在Prosody的层面已经有工作做到了很好的效果)。

于是论文针对上述三个问题,基于Transformer,重新设计了模型。模型的示意图如下:

图一

首先,为了加速推断的速度,论文采用了non auto-regressive的seq-to-seq模型(如图一的(a)),不需要依赖上一个时间步的输入,可以让整个模型真正的并行化。论文中non auto-regressive的seq-to-seq模型的设计方法类似于论文Non-Autoregressive Neural Machine Translation

图二 论文Non-Autoregressive Neural Machine Translation结构图示

text(phoneme)首先经过Encoder得到Encoder Output,由于phoneme的长度往往小于梅尔声谱图的长度,为了适应Decoder的Input的长度,模型在这里有一个Length Regulator,这里,把Encoder Output进行智能化的填充,使之长度等于梅尔声谱图的长度,让填充过的Encoder Output直接作为Decoder的Input输入Decoder。值得注意的是,论文作者用1D Conv代替了Transformer中的全连接网络(如图一(b)),并阐明了原因

The motivation is that the adjacent hidden states are more closely related in the character/phoneme and mel-spectrogram sequence in speech tasks.

随后,论文详细地介绍了Length Regulator的设计方法(如图一(c))。Length Regulator的作用是将Encoder Output智能地填充到与Mel Spectrogram一致的长度,Encoder Output先进入Duration Predictor,Duration Predictor根据Encoder Output输出一组数字,如[2,3,1,2,3],然后Length Regulator将Encoder Output的第一个向量复制1次,第二个向量复制三次,第三个不复制,第四个复制1次,最后一个复制2次,这样,2+3+1+2+3=11等于目标梅尔声谱图的长度。

Duration Predictor(如图一(d))负责根据Encoder Output预测出每个向量对应需要复制的次数。这里,作者为了改变传统seq-to-seq模型隐式的Alignment,加入了显式的Alignment的标签(如图一最右侧),该标签由Transformer-TTS(可参见笔者的另一篇博文基于Transformer的语音合成系统)的Attention部分提供。因为Transformer是Multi-Head,论文作者制定了标准,选择了一个Head用作Alignment,Duration Extractor这一部件用于从此Head的Attention Matrix中提取目标。Duration Predictor的预测结果与目标做MSELoss,在整个训练过程进行反向传播。

这一部分具体地阐述了Duration Predictor和Extractor的设计

至此,论文已经解决了之前提到了两个问题。至于最后一个Controllability,只需要对Duration Predictor的预测结果进行人为干预,即可做到控制合成语音的语速快慢。

论文作者的实验充分验证了上述设计的有效性,首先是合成速度有了巨大地提高:

其次,鲁棒性也有了较大地提升:

总的来说,这篇论文是一个非常好的工作,提出了一种有效地加快合成速度的方法,并提高了合成的准确性,因为模型结构的红利,该模型还可以对合成声音的语速进行控制。但是也存在问题,模型使用了Transformer-TTS的Alignment作为Target,而Transformer-TTS的Alignment是隐式的,也就是说,模型将隐式的Alignment作为显式的Alignment的Target。


今天(2019-5-29)发现百度也出了一篇non auto-regressive TTS的model:

Parallel Neural Text-to-Speecharxiv.org

粗略看了一下论文,整体架构基于DeepVoice3,Decoder Input使用Position Embedding代替,个人觉得这种方式过于人工。模型的整体架构如图:

论文还提出了一个并行化的Vocoder,取名WaveVAE。


复现笔记参见:

星辰漫游者:FastSpeech复现笔记zhuanlan.zhihu.com图标
class FastSpeech(nn.Module):
    """ FastSpeech """

    def __init__(self):
        super(FastSpeech, self).__init__()

        self.encoder = Encoder()
        self.length_regulator = LengthRegulator()
        self.decoder = Decoder()

        self.mel_linear = Linear(hp.decoder_output_size, hp.num_mels)
        self.postnet = PostNet()

    def forward(self, src_seq, src_pos, mel_max_length=None, length_target=None, alpha=1.0):
        encoder_output, encoder_mask = self.encoder(src_seq, src_pos)

        if self.training:
            length_regulator_output, decoder_pos, duration_predictor_output = self.length_regulator(
                encoder_output,
                encoder_mask,
                length_target,
                alpha,
                mel_max_length)
            decoder_output = self.decoder(length_regulator_output, decoder_pos)

            mel_output = self.mel_linear(decoder_output)
            mel_output_postnet = self.postnet(mel_output) + mel_output

            return mel_output, mel_output_postnet, duration_predictor_output
        else:
            length_regulator_output, decoder_pos = self.length_regulator(
                encoder_output, encoder_mask, alpha=alpha)

            decoder_output = self.decoder(length_regulator_output, decoder_pos)

            mel_output = self.mel_linear(decoder_output)
            mel_output_postnet = self.postnet(mel_output) + mel_output

            return mel_output, mel_output_postnet

编辑于 2019-06-04

文章被以下专栏收录