Generating diverse and natural TTS samples using a quantized fine-grained VAE and auto-reregressive

  • Guangzhi Sun & 2020icassp
  • Cambridge & Google brain
  • demo page

abstract

  • motivation:使用VAE生成fine-grained prosody embedding,合成的语音在token之间的韵律变化不自然。
  • method:使用VQ将latent features离散化,对于结果再单独训练一个自回归模型。

introduction

使用VAE提取的fine-grained latent features是对每个phn单独建模的,彼此之间具有独立性,因此在音节之间的长时停顿和能量以及基频上的陡增都会产生合成语音的不连续和不自然。——解决方法在于生成过程中缩小不自然的样本中标准分布的方差(VAE输出的是【0,1】高斯分布),因为这样可以降低采样离群值的可能性,但是这样只是限制了分布来的多样性,并没有根本解决问题。

Tacotron+QFVAE(quantized fine-grained VAE) reference encoder,将连续的样本离散成指定类,改善了合成语音的自然度。

methods

ref 【13】Robust and fine-grained prosody control of end-to-end speech synthesis

  • 根据ref[13],从梅尔谱中对齐phn,然后和encoder计算latent embedding z z z(连续域)
    在这里插入图片描述
  • 使用VQVAE将连续域的 z z z离散化处理,同时限制【0,1】高斯分布。

在这里插入图片描述

  • 其中, z n z_n zn是reference encoder编码的信息, e n e_n en是VQ量化之后的结果,VQVAE的ELBO如上公式。 s g sg sg是stop gradient operator
  • ∣ ∣ z n − s g [ e n ] ∣ ∣ 2 || z_n - sg[e_n] ||^2 ∣∣znsg[en]2:固定quantized,让连续域的latent embedding接近量化数值,同时避免向量空间过度膨胀
  • ∣ ∣ s g [ z n ] − e n ∣ ∣ 2 || sg[z_n] - e_n||^2 ∣∣sg[zn]en2:固定连续域的latent embedding,更新code-book,最小化量化引入的误差

VQ部分的代码实现


class VectorQuantizer(nn.Module):
    def __init__(self, num_embeddings, embedding_dim, commitment_cost):
        super(VectorQuantizer, self).__init__()
        
        self._embedding_dim = embedding_dim
        self._num_embeddings = num_embeddings
        
        self._embedding = nn.Embedding(self._num_embeddings, self._embedding_dim)
        self._embedding.weight.data.uniform_(-1/self._num_embeddings, 1/self._num_embeddings)
        self._commitment_cost = commitment_cost

    def forward(self, inputs):
        # convert inputs from BCHW -> BHWC
        inputs = inputs.permute(0, 2, 3, 1).contiguous()
        input_shape = inputs.shape
        
        # Flatten input
        flat_input = inputs.view(-1, self._embedding_dim)
        
        # Calculate distances
        distances = (torch.sum(flat_input**2, dim=1, keepdim=True) 
                    + torch.sum(self._embedding.weight**2, dim=1)
                    - 2 * torch.matmul(flat_input, self._embedding.weight.t()))
            
        # Encoding,argmin求结果最小时的取值
        encoding_indices = torch.argmin(distances, dim=1).unsqueeze(1)
        encodings = torch.zeros(encoding_indices.shape[0], self._num_embeddings, device=inputs.device)
        encodings.scatter_(1, encoding_indices, 1)
        
        # Quantize and unflatten
        # 重新去code-book找到对应的权重数值
        quantized = torch.matmul(encodings, self._embedding.weight).view(input_shape)
        
        # Loss
        # e_latent_loss:固定quantized,让连续域的latent embedding接近量化数值,同时避免向量空间过度膨胀
      	# q_latent_loss:固定连续域的latent embedding,更新code-book,最小化量化引入的误差
        e_latent_loss = F.mse_loss(quantized.detach(), inputs)
        q_latent_loss = F.mse_loss(quantized, inputs.detach())
        loss = q_latent_loss + self._commitment_cost * e_latent_loss
        
        # quantized送给后续层,要实现梯度反传前层,就要和input结合起来
        # perplexity 作为参考向量,看vq-codebook emb有多少被用到,数量设置是否合理
        quantized = inputs + (quantized - inputs).detach()
        avg_probs = torch.mean(encodings, dim=0)
        perplexity = torch.exp(-torch.sum(avg_probs * torch.log(avg_probs + 1e-10)))
        
        # convert quantized from BHWC -> BCHW
        return loss, quantized.permute(0, 3, 1, 2).contiguous(), perplexity, encodings

AR prosody prior

训练时候,reference encoder基于mel-spec预测phn level prosody latent embedding,但是inference的时候没有target spec,额外训练一个AR prosody prior model,模型基于encoder embeddings预测phn level prosody latent embedding,是自回归的预测方式。
预测有两种:

  • 离散型AR:直接预测量化后的 e n e_n en
  • 连续型AR:预测连续向量 z n z_n zn

experiments

  • datastes:LibriTTS ,585 hours
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值