VITS 模型详解与公式推导:基于条件变分自编码器和对抗学习的端到端语音合成模型

参考文献:

[1] Kim J, Kong J, Son J. Conditional variational autoencoder with adversarial learning for end-to-end text-to-speech[C]//International Conference on Machine Learning. PMLR, 2021: 5530-5540.

[2] Su J, Wu G. f-VAEs: Improve VAEs with conditional flows[J]. arXiv preprint arXiv:1809.05861, 2018.

[3] Kim, J., Kim, S., Kong, J., and Y oon, S. Glow-TTS: A Generative Flow for Text-to-Speech via Monotonic Alignment Search. Advances in Neural Information Processing Systems, 33, 2020.

[4] Theis L, Oord A, Bethge M. A note on the evaluation of generative models[J]. arXiv preprint arXiv:1511.01844, 2015.

[5] Ho J, Chen X, Srinivas A, et al. Flow++: Improving flow-based generative models with variational dequantization and architecture design[C]//International Conference on Machine Learning. PMLR, 2019: 2722-2730.

[6] Kong J, Kim J, Bae J. Hifi-gan: Generative adversarial networks for efficient and high fidelity speech synthesis[J]. Advances in Neural Information Processing Systems, 2020, 33: 17022-17033.

[7] 变分自编码器(一):原来是这么一回事 - 科学空间|Scientific Spaces

[8] 细水长flow之f-VAEs:Glow与VAEs的联姻 - 科学空间|Scientific Spaces

[9] 细读经典:VITS,用于语音合成带有对抗学习的条件变分自编码器 - 知乎 (zhihu.com)

[10] 论文分享 | VITS:基于条件变分自编码器和对抗学习的端到端语音合成模型 (careerengine.us)

[11] VITS 语音合成完全端到端TTS的里程碑-CSDN博客

文章目录

  • 导语
  • 变分推断部分(Variational Inference)
    • 条件变分自编码器(cVAE)
    • 重构损失(Reconstruction Loss)
    • KL 散度(KL-Divergence)
    • 流模型 Flow 的介入
  • 对齐估计部分(Alignment Estimation)
    • 单调对齐搜索(Monotonic Alignment Search)
    • 从文本中预测时长(Duration Prediction from Text)
  • 对抗学习部分(Adversarial Training)
  • 损失函数总结
  • 模型架构介绍
    • 后验编码器(Posterior Encoder)【仅用于训练】
    • 先验编码器(Prior Encoder)
    • 解码器(Decoder)
    • 判别器(Discriminator)【仅用于训练】
    • 随机持续时间预测器(Stochastic Duration Predictor)
    • 推理阶段架构

导语

在学习 VITS 前,请首先去了解 VAE 和 Flow,本篇文章将基于这两篇我的博客,欢迎大家前往查看。

  • 变分自编码器 VAE 超详解,从简单公式推导到模型结构到模型理解-CSDN博客
  • 流模型 Flow 超详解,基于 Flow 的生成式模型,从思路到基础到公式推导到模型理解与应用(Flow-based Generative Model)-CSDN博客

变分推断部分(Variational Inference)

条件变分自编码器(cVAE)

  • 首先,上来就是条件VAE(cVAE)的核心公式:
    log ⁡ p θ ( x ∣ c ) ≥ E z ∼ q ϕ ( z ∣ x ) [ log ⁡ p ( x ∣ z ) ] − D K L [ q ϕ ( z ∣ x ) ∣ ∣ p θ ( z ∣ c ) ] = E z ∼ q ϕ ( z ∣ x ) [ log ⁡ p ( x ∣ z ) − log ⁡ q ϕ ( z ∣ x ) p θ ( z ∣ c ) ] \begin{aligned} \log{p_\theta(x|c)} &\ge \mathbb{E}_{z\sim q_\phi(z|x)}[\log{p(x|z)}] - D_{KL}[q_\phi(z|x)||p_\theta(z|c)] \\ &= \mathbb{E}_{z\sim q_\phi(z|x)}[\log{p(x|z)} - \log\frac{q_\phi(z|x)}{p_\theta(z|c)}] \end{aligned} logpθ(xc)Ezqϕ(zx)[logp(xz)]DKL[qϕ(zx)∣∣pθ(zc)]=Ezqϕ(zx)[logp(xz)logpθ(zc)qϕ(zx)]

    • 右式就是所谓的变分下界(Variational Lower Bound,又称为 Evidence Lower Bound,ELBO)。相较于常规的 VAE,这里的条件 VAE 就是多加了个引导性质的条件 c,类似于标签信息,用于引导生成的样本,在 语音合成(Text To Speech,TTS) 任务中自然就相当于提供的文本信息(Text)。

    • 加入的条件为 c,那么自然的,z 的先验分布就变成了 p(z|c),边缘似然也加了条件 c,变成了 p(x|c)

    • q 就是我们熟知的近似后验分布(Approximate Posterior Distribution)

    • 而等式右边,我们之前也介绍过,可以分为重构项(第一项)和正则项(第二项)。

    • 简单的条件 VAE 的结构图如下,看不太懂也没关系,后面继续讲,图源自变分自编码器(一):原来是这么一回事 - 科学空间|Scientific Spaces:

  • 和 VAE 的目标一样,我们也需要将这个 ELBO 最大化,因此这个公式就是我们的目标函数的一部分。由此我们就可以得到部分的训练损失函数,也就是 ELBO 取反。一为重构损失:
    L r e c o n = − E z ∼ q ϕ ( z ∣ x ) [ log ⁡ p ( x ∣ z ) ] \mathcal{L}_{recon} = -\mathbb{E}_{z\sim q_\phi(z|x)}[\log{p(x|z)}] Lrecon=Ezqϕ(zx)[logp(xz)]
    二为正则损失(KL 散度,KL-Divergence)
    L k l = D K L [ q ϕ ( z ∣ x ) ∣ ∣ p θ ( z ∣ c ) ] \mathcal{L}_{kl} = D_{KL}[q_\phi(z|x)||p_\theta(z|c)] Lkl=DKL[qϕ(zx)∣∣pθ(zc)]

重构损失(Reconstruction Loss)

  • 首先是重构损失。在 VAE 中我们介绍过,重构损失就是比较真实样本与生成样本的差距。而论文中并没有直接比较二者的原始波形,而是选取了真实样本与生成样本的梅尔频谱图(Mel-spectrogram)进行比较,因此重构损失的式子可以表示为:
    L r e c o n = ∥ x m e l − x ^ m e l ∥ 1 \mathcal{L}_{recon} = \parallel{x_{mel} - \hat{x}_{mel}}\parallel_1 Lrecon=∥xmelx^mel1
    注意,想要从原始波形得到其梅尔频谱图是不需要通过神经网络的,换言之这个变换过程不需要参与训练。并且,这个也只会出现在训练过程中,而不会出现在推理过程中。此外,从潜在空间采样出潜在变量 z 后,我们也不是将整个 z 都喂给 decoder,而是选
    取其中的部分序列
    作为 decoder 的输入,论文中这项技术被称为 Windowed Generator Trainning,可以翻译成窗口生成器训练。

    在训练时只对潜在变量 z 的一部分进行采样,而不是对整个序列进行采样。这个部分通常是一个固定大小的窗口,包含潜在变量序列的一部分。

    这样做的原因可能是为了提高训练效率,减少计算成本,并且更好地处理长序列。在文本到语音合成等任务中,输入序列可能非常长,完全采样整个序列可能会变得非常昂贵。通过使用部分序列,可以更有效地进行训练,并更好地处理长序列的上下文信息。

KL 散度(KL-Divergence)

  • 其次是 KL 散度。在这一项 KL 散度中,我们需要比较 z 的后验分布与它的先验分布之间的差距,防止过拟合等等,当然,这里的后验分布是近似后验分布(q)。我们分别讨论:

    • **z 的后验分布 q(z|x):在这里,我们并没有使用样本 x 的梅尔频谱图来计算近似后验分布,而是使用 x 的线性频谱图(linear-scale spectrogram)**来作为后验编码器的输入,用于计算 z 的后验分布,记为 x_lin,原因可以参考下方:

      1. 高分辨率信息提供:在语音合成任务中,高分辨率的频谱信息对于捕捉语音信号的细节和清晰度至关重要。梅尔频谱图在频域上对声音信息进行了压缩,因此可能会丢失一些高频细节。使用线性频谱图能够为后验编码器提供更多的高分辨率信息,有助于模型更准确地学习和生成语音。
      2. 后验编码器设计:后验编码器的任务是将输入语音的频谱信息映射到潜在变量 z 的分布。使用线性频谱图作为输入有助于后验编码器更好地建模输入语音的频谱特征。对于 VITS,这个设计选择是为了提供更多的信息以改善潜在变量的建模。
      3. 变分推断属性:虽然输入从梅尔频谱图变为线性频谱图,但这并不违反变分推断的属性。变分推断的目标是在给定观测数据的条件下,找到一个潜在变量的分布,使得该分布与真实的后验分布尽可能接近。选择不同的输入特征并不会违反这一属性,只要模型能够在学习过程中适应这些变化。

      因此,z 的后验分布我们记为:
      q ϕ ( z ∣ x l i n ) q_\phi(z|x_{lin}) qϕ(zxlin)

    • z 的先验分布 p(z|c):在 VAE 中,我们说过,z 的先验分布就是标准正态分布 N(0, I),也就是 p(z),而在条件 VAE 中,由于有了先验条件,因此 z 的先验分布也需要改变,即变为了 p(z|c),因此 z 的先验分布也需要进行计算。在 cVAE 中,我们额外使用一个编码器去计算 z 的先验分布,我们称其为先验编码器(Prior Encoder),记为 c。而在 VITS 中,先验编码器的输入主要有:

      • 从输入文本中提取出来的音素序列(phonemes sequence),记为c_text
      • 音素和潜在变量之间的对齐矩阵(Alignment between phonemes and latent variables),记为 A

      值得一提的是,对齐矩阵 A 是一个硬性单调的,|c_text|×|z| 维度的注意力矩阵(hard monotonic attention matrix ),目的在于去表示每个音素需要扩展为多长的时间来与目标语音时间进行对齐,相当于去寻找哪些文本对应语音的哪些部分,即语音和文本的对应关系。这样可以确保在合成的过程中,生成的声学特征与输入的文本之间的对齐关系是单调递增的,即随着时间的推移,声学特征的生成应该与文本中的语音单元相对应,而不会出现跳跃或错位。注意力机制在我讲解 Transformer 的博客中有详细介绍Transformer模型详解,可以前往了解一下,这里用处不大,仅仅需要知道大概概念即可。

      综合音素序列和对齐矩阵这两个先验编码器的输入,z 的先验分布我们也可以写出:
      p θ ( z ∣ c t e x t , A ) p_\theta(z|c_{text}, A) pθ(zctext,A)

  • 所以损失函数的第二项,也就是 KL散度项就是:
    L k l = log ⁡ q ϕ ( z ∣ x l i n ) − log ⁡ p θ ( z ∣ c t e x t , A ) \mathcal{L}_{kl} = \log q_\phi(z|x_{lin}) - \log p_\theta(z|c_{text}, A) Lkl=logqϕ(zxlin)logpθ(zctext,A)
    其中,z 的后验分布展开后为:
    z ∼ q ϕ ( z ∣ x l i n ) = N ( z ; μ ϕ ( x l i n ) , σ ϕ ( x l i n ) ) z \sim q_\phi(z|x_{lin}) = N(z; \mu_\phi(x_{lin}), \sigma_\phi(x_{lin})) zqϕ(zxlin)=N(z;μϕ(xlin),σϕ(xlin))

流模型 Flow 的介入

  • 不过,到这边为止,似乎都是有关 cVAE 的内容,那么 VITS 的创新点在哪里呢?就在于先验分布和后验分布上!实际上,VITS 的设计针对的就是 VAE 身上的一些问题。人们发现,在使用 VAE 生成样本,比如图片的时候,生成出的样本往往都会很模糊,质量并不是很高。问题出在哪里?

    • 有人认为是 mse 误差的问题,也有人认为是KL散度的固有性质。但留意到一点是:即使去掉隐变量的 KL 散度那一项,变成普通的自编码器,重构出来的图像通常也是模糊的。这表明,VAEs图像模糊可能是低维重构原始图像的固有问题。
    • 既然是从低维重构原始图像不太行,那如果将隐变量维度取输入维度一样大小呢?似乎还不够,因为标准的 VAE 将后验分布也假设为高斯分布,这限制了模型的表达能力。事实上,人们猜测,由于高斯分布簇只是众多可能的后验分布中极小的一部分,如果后验分布的性质与高斯分布差很远,那么拟合效果就会很糟糕。
  • 因此,人们想到了另一个模型:Flow。流模型通过一系列耦合层,可以将复杂的输入分布转化为高斯分布,这样的过程可逆,雅可比矩阵行列式也容易计算,那么我们就可以使用流模型,将原本过于简单的高斯分布变为更加复杂的分布,从而提高其表达能力

  • 事实上,流模型诸如 Glow 也有一定的问题。我们在上一篇介绍流模型的文章流模型 Flow 超详解中曾经讲过,诸多对于变换过程的限制导致一层耦合层只能带来非常弱的拟合能力(非线性能力),所以一般还需要足够多的耦合层才能累积为强非线性变换,因此Glow模型通常比较庞大,训练时间较长。

  • 回归 VITS 模型本身。在 VITS 中,就是在先验分布上使用了标准化流(normalizing flow)的技术,通过对简单的先验分布进行可逆变换,将其转化为了更加复杂的分布,从而使得先验分布的表达能力提高,更能够捕捉真实样本的分布特征。我们使用 f_θ 表示标准化流,根据变量变换定理,VITS 的先验分布可以重写为:
    p θ ( z ∣ c ) = N ( f θ ( z ) ; μ θ ( c ) , σ θ ( c ) ) ∣ det ⁡ ∂ f θ ( z ) ∂ z ∣ p_\theta(z|c) = N(f_\theta(z);\mu_\theta(c), \sigma_\theta(c))\left| \det\frac{\partial f_\theta(z)}{\partial z} \right| pθ(zc)=N(fθ(z);μθ(c),σθ(c)) detzfθ(z)
    而其中,这里的 c 就是先验编码器。根据 c 的输入,c 可以表示为:
    c = [ c t e x t , A ] c = [c_{text}, A] c=[ctext,A]

注意,这里的先验分布 p_θ(z|c) 推导利用的变量变换定理在上一篇文章流模型 Flow 超详解的**变量变换定理(Change of Variables Theorem)**一节中进行了详细介绍,可供参考。这里利用结论作简单推导:

  • 我们的目的是让 z 的先验分布变得复杂,而不是简单的参数化高斯分布。因此我们首先假设 z 的先验分布空间非常复杂,在 z 通过一个标准化流 f_θ 后,可以变成一个简单的参数化的高斯分布,这个高斯分布为:
    p ( f θ ( z ) ∣ c ) = N ( f θ ( z ) ; μ θ ( c ) , σ θ ( c ) ) p(f_\theta(z)|c) = N(f_\theta(z); \mu_\theta(c), \sigma_\theta(c)) p(fθ(z)c)=N(fθ(z);μθ(c),σθ(c))
    其中,由于受到条件 c(即 c_text 和对齐矩阵 A)的影响,因此其均值和方差需要加上 c。

  • 我们需要求取的是复杂空间 z 的先验分布,而 z 和 f_θ(z) 的关系为:
    z = f θ − 1 ( f θ ( z ) ) z = f_\theta^{-1}(f_\theta(z)) z=fθ1(fθ(z))

  • 由上面两个式子,通过变量变换定理,我们可以知道:
    p ( z ∣ c ) = p ( f θ ( z ) ∣ c ) ∣ det ⁡ ( J f − 1 ) ∣ = p ( f θ ( z ) ∣ c ) ∣ det ⁡ ( J ( f θ − 1 ) − 1 ) ∣ = p ( f θ ( z ) ∣ c ) ∣ det ⁡ ( J f θ ) ∣ = N ( f θ ( z ) ; μ θ ( c ) , σ θ ( c ) ) ∣ det ⁡ ∂ f θ ( z ) ∂ z ∣ \begin{aligned} p(z|c) &= p(f_\theta(z)|c)\left| \det(J_{f^{-1}})\right| \\ &= p(f_\theta(z)|c)\left| \det(J_{(f_\theta^{-1})^{-1}})\right| \\ &= p(f_\theta(z)|c)\left| \det(J_{f_\theta})\right| \\ &= N(f_\theta(z); \mu_\theta(c), \sigma_\theta(c))\left| \det\frac{\partial f_\theta(z)}{\partial z} \right| \end{aligned} p(zc)=p(fθ(z)c) det(Jf1) =p(fθ(z)c) det(J(fθ1)1) =p(fθ(z)c)det(Jfθ)=N(fθ(z);μθ(c),σθ(c)) detzfθ(z)

  • 结论得证。

对齐估计部分(Alignment Estimation)

我们曾经说过,对于先验编码器来说,它的输入有音素序列 c_text 和对齐矩阵 A。然而,音素序列有办法直接进行转化,但对齐矩阵 A 可不是凭空就来的。不过很可惜的是,我们并没有对齐矩阵的真实标签,因此我们必须在每次训练迭代的时候进行对齐估计。下面就来介绍这一部分。

单调对齐搜索(Monotonic Alignment Search)

  • 单调对齐搜索,顾名思义,就是去找一个单调对齐矩阵,而这个矩阵就是最好的单调对齐矩阵。怎么算是最好的单调对齐矩阵呢?那当然是能提高找到样本的概率,也就是提高目标函数的单调对齐矩阵最好啊!因此,很自然的,我们可以得到 MAS 的核心目标公式:
    A = arg ⁡ max ⁡ A ^ log ⁡ p ( x ∣ c t e x t , A ^ ) A = \arg \max_{\hat A} \log p(x|c_{text}, \hat{A}) A=argA^maxlogp(xctext,A^)
    由于我们在 VITS 中使用了标准化流 f,经过 f 后,分布将会变成一个简单的高斯分布,因此这个公式可以变化为:
    A = arg ⁡ max ⁡ A ^ log ⁡ p ( x ∣ c t e x t , A ^ ) = arg ⁡ max ⁡ A ^ log ⁡ [ N ( f ( x ) ; μ ( c t e x t , A ^ ) , σ ( c t e x t , A ^ ) ) ∣ det ⁡ ∂ f ( x ) ∂ x ∣ ] = arg ⁡ max ⁡ A ^ log ⁡ N ( f ( x ) ; μ ( c t e x t , A ^ ) , σ ( c t e x t , A ^ ) ) \begin{aligned} A &= \arg \max_{\hat A} \log p(x|c_{text}, {\hat A}) \\ &= \arg \max_{\hat A} \log [N(f(x); \mu(c_{text}, \hat{A}), \sigma(c_{text}, \hat{A}))\left| \det\frac{\partial f(x)}{\partial x}\right|] \\ &= \arg \max_{\hat A} \log N(f(x); \mu(c_{text}, \hat{A}), \sigma(c_{text}, \hat{A})) \end{aligned} A=argA^maxlogp(xctext,A^)=argA^maxlog[N(f(x);μ(ctext,A^),σ(ctext,A^)) detxf(x) ]=argA^maxlogN(f(x);μ(ctext,A^),σ(ctext,A^))

  • 然而,这对于我们来说,直接计算 log p 有点太麻烦了,毕竟我们前面都在讨论怎么最大化 ELBO,而不是最大化 log p。因此我们不妨改改这个 MAS 核心公式,将目标切换成让 ELBO 最大的对齐矩阵 A,即:
    A = arg ⁡ max ⁡ A ^ log ⁡ p ( x ∣ c t e x t , A ^ ) = arg ⁡ max ⁡ A ^ E z ∼ q ϕ ( z ∣ x ) [ log ⁡ p ( x ∣ z ) − log ⁡ q ϕ ( z ∣ x ) p θ ( z ∣ c t e x t , A ^ ) ] = arg ⁡ max ⁡ A ^ ( − log ⁡ q ϕ ( z ∣ x ) p θ ( z ∣ c t e x t , A ^ ) ) = arg ⁡ max ⁡ A ^ log ⁡ p θ ( z ∣ c t e x t , A ^ ) q ϕ ( z ∣ x ) = arg ⁡ max ⁡ A ^ log ⁡ p θ ( z ∣ c t e x t , A ^ ) \begin{aligned} A &= \arg \max_{\hat A} \log p(x|c_{text}, \hat{A}) \\ &= \arg \max_{\hat A} \mathbb{E}_{z\sim q_\phi(z|x)}[\log{p(x|z)} - \log\frac{q_\phi(z|x)}{p_\theta(z|c_{text}, \hat{A})}] \\ &= \arg \max_{\hat A} (- \log\frac{q_\phi(z|x)}{p_\theta(z|c_{text}, \hat{A})}) \\ &= \arg \max_{\hat A} \log\frac{p_\theta(z|c_{text}, \hat{A})}{q_\phi(z|x)} \\ &= \arg \max_{\hat A} \log p_\theta(z|c_{text}, \hat{A}) \\ \end{aligned} A=argA^maxlogp(xctext,A^)=argA^maxEzqϕ(zx)[logp(xz)logpθ(zctext,A^)qϕ(zx)]=argA^max(logpθ(zctext,A^)qϕ(zx))=argA^maxlogqϕ(zx)pθ(zctext,A^)=argA^maxlogpθ(zctext,A^)
    使用之前提供的公式,我们将 z 的先验分布进行变换:
    A = arg ⁡ max ⁡ A ^ log ⁡ p θ ( z ∣ c t e x t , A ^ ) = arg ⁡ max ⁡ A ^ log ⁡ N ( f θ ( z ) ; μ θ ( c t e x t , A ^ ) , σ θ ( c t e x t , A ^ ) ) \begin{aligned} A &= \arg \max_{\hat A} \log p_\theta(z|c_{text}, \hat{A}) \\ &= \arg \max_{\hat A}\log N(f_\theta(z); \mu_\theta(c_{text}, \hat{A}), \sigma_\theta(c_{text}, \hat{A})) \end{aligned} A=argA^maxlogpθ(zctext,A^)=argA^maxlogN(fθ(z);μθ(ctext,A^),σθ(ctext,A^))

  • 哦?这个公式是不是和之前我们提供的核心公式很相似?因此论文的作者偷了个懒,既然变换后的公式相似,我们就直接使用原始的 MAS 就行了,直接站在巨人的肩膀上。对于原始的 MAS,请参考论文Glow-TTS: A Generative Flow for Text-to-Speech via Monotonic Alignment Search

从文本中预测时长(Duration Prediction from Text)

  • 训练时可以通过样本语音、c_text,使用 MAS 来生成单调对齐矩阵,但在推理阶段我们没有语音,因此我们就需要额外再训练一个音素时长预测器(Phonemes Duration Predictor),去预测每个音素的发音时长,用于推理的对齐矩阵生成中。

  • 传统的时长预测可以通过将对齐矩阵 A 的每一行所有列求和来计算每个音素的持续时间,但是这样无法表现出韵律节奏变化多样性。为了反映真实的语音韵律多样性,论文设计了随机时长预测器(Stochastic Duration Predictor)。它是基于流模型的生成式模型,以最大化似然估计的方式进行训练。但是直接训练的话有两个问题:

    • 音素时长是一个离散的整数,需要使用连续标准流模型进行**去量化(Dequantization)**操作;
    • 音素时长是一个标量(scalar),难以实现高维变换。
  • 为了解决这两个问题,我们使用变分去量化(variational dequantization)和变分数据规整(variational data augmentation)两个策略,我们用 d 来表示持续时间序列(duration sequence):

    • 变分去量化:引入随机变量 u,和持续时间序列 d 有着相同的时间尺度(分辨率)和维度。由于音素长度是非零正整数,因此我们限定 u 的范围为 [0, 1),因此 d - u 就变成了一个正实数序列。
    • 变分数据规整:引入随机变量 v,和持续时间序列 d 有着相同的时间尺度(分辨率)和维度。我们将 v 的每一个通道都对应上 d 的每一个通道,将二者级联起来,共同组成一个更高维度的潜在表达。
  • 有了这两个变量,我们就可以着手去求我们的目标函数,也就是最大化持续时间序列的对数似然(log-likelihood)了。在这里,我们不去直接求取对数似然,而是去选取它的变分下界。在此之前,我们先根据刚刚的两个随机变量 u、v,引入一个后验分布:
    q ϕ ( u , v ∣ d , c t e x t ) q_\phi(u,v|d, c_{text}) qϕ(u,vd,ctext)

  • 因此,对数似然的变分下界就为:
    log ⁡ p θ ( d ∣ c t e x t ) ≥ E q ϕ ( u , v ∣ d , c t e x t ) [ log ⁡ p θ ( d − u , v ∣ c t e x t ) q ϕ ( u , v ∣ d , c t e x t ) ] \log p_\theta(d|c_{text}) \ge \mathbb{E}_{q_\phi(u,v|d, c_{text})}[\log\frac{p_\theta(d-u, v|c_{text})}{q_\phi(u,v|d,c_{text})}] logpθ(dctext)Eqϕ(u,vd,ctext)[logqϕ(u,vd,ctext)pθ(du,vctext)]
    简单的推导过程在后面。

  • 训练损失我们使用 L_dur 来表示,则训练损失就是变分下界的负项:
    L d u r = − E q ϕ ( u , v ∣ d , c t e x t ) [ log ⁡ p θ ( d − u , v ∣ c t e x t ) q ϕ ( u , v ∣ d , c t e x t ) ] \mathcal{L}_{dur} = -\mathbb{E}_{q_\phi(u,v|d, c_{text})}[\log\frac{p_\theta(d-u, v|c_{text})}{q_\phi(u,v|d,c_{text})}] Ldur=Eqϕ(u,vd,ctext)[logqϕ(u,vd,ctext)pθ(du,vctext)]

  • 与此同时,在训练时将会断开随机时长预测器的梯度反传,防止对该部分的训练时产生的梯度影响到其它模块。采样的过程就比较简单了,音素持续时间是通过随机持续时间预测器的逆变换从随机噪声中采样的,然后将其转换为整数即可,论文是采取了向上取整。

    下面简单说明一下持续时间序列的对数似然的变分下界的推导过程。过程参考论文:

    [1] Theis L, Oord A, Bethge M. A note on the evaluation of generative models[J]. arXiv preprint arXiv:1511.01844, 2015.

    [2] Ho J, Chen X, Srinivas A, et al. Flow++: Improving flow-based generative models with variational dequantization and architecture design[C]//International Conference on Machine Learning. PMLR, 2019: 2722-2730.

    • 我们遇到的持续时长 d 的各部分值是离散的正整数,因此持续时长预测是个离散概率模型,这个模型我们使用 P_model 来表示,持续时长序列 d 的维度我们用 D 来表示。直接训练这个离散模型很困难,不过论文[1]中指出,实际上,训练一个对 y=d-u, u∈[0,1)^D 建模的连续概率模型 p_θ,就相当于是在给 P_model 的对数似然下界进行训练。P_model 我们很容易可以通过这样的方式来表示:
      P m o d e l : = ∫ [ 0 , 1 ] D p θ ( d − u ) d u P_{model} := \int_{[0,1]^D} p_{\theta}(d-u){\rm d}u Pmodel:=[0,1]Dpθ(du)du

    • 而这里的 u 我们称之为去量化噪声(Dequantization Noise),在使用中是需要通过训练产生的,因此我们只能使用后验分布去表示 u 的分布。这里我们使用 q(u|d) 来表示 u 的近似后验分布。我们用 P_data 来表示真实离散数据 d 的分布,P_model 我们刚刚说过了就是我们期待训练的 d 的离散概率模型,因此我们的目标函数可以这样变化:
      E d ∼ P d a t a [ log ⁡ P m o d e l ( d ) ] = E d ∼ P d a t a [ log ⁡ ∫ [ 0 , 1 ] D p θ ( d − u ) d u ] = E d ∼ P d a t a [ log ⁡ ∫ [ 0 , 1 ] D q ( u ∣ d ) p θ ( d − u ) q ( u ∣ d ) d u ] \begin{aligned} \mathbb{E}_{d\sim P_{data}}[\log P_{model}(d)] &= \mathbb{E}_{d\sim P_{data}}[\log \int_{[0,1]^D} p_{\theta}(d-u){\rm d}u] \\ &= \mathbb{E}_{d\sim P_{data}}[\log \int_{[0,1]^D} q(u|d)\frac{p_{\theta}(d-u)}{q(u|d)}{\rm d}u] \end{aligned} EdPdata[logPmodel(d)]=EdPdata[log[0,1]Dpθ(du)du]=EdPdata[log[0,1]Dq(ud)q(ud)pθ(du)du]
      由 Jensen 不等式,可得:
      E d ∼ P d a t a [ log ⁡ P m o d e l ( d ) ] = E d ∼ P d a t a [ log ⁡ ∫ [ 0 , 1 ] D q ( u ∣ d ) p θ ( d − u ) q ( u ∣ d ) d u ] ≥ E d ∼ P d a t a [ ∫ [ 0 , 1 ] D q ( u ∣ d ) log ⁡ p θ ( d − u ) q ( u ∣ d ) d u ] = E d ∼ P d a t a E u ∼ q ( u ∣ d ) [ log ⁡ p θ ( d − u ) q ( u ∣ d ) ] \begin{aligned} \mathbb{E}_{d\sim P_{data}}[\log P_{model}(d)] &= \mathbb{E}_{d\sim P_{data}}[\log \int_{[0,1]^D} q(u|d)\frac{p_{\theta}(d-u)}{q(u|d)}{\rm d}u] \\ &\ge \mathbb{E}_{d\sim P_{data}}[\int_{[0,1]^D}q(u|d)\log \frac{p_{\theta}(d-u)}{q(u|d)}{\rm d}u] \\ &= \mathbb{E}_{d\sim P_{data}}\mathbb{E}_{u\sim q(u|d)}[\log \frac{p_{\theta}(d-u)}{q(u|d)}] \\ \end{aligned} EdPdata[logPmodel(d)]=EdPdata[log[0,1]Dq(ud)q(ud)pθ(du)du]EdPdata[[0,1]Dq(ud)logq(ud)pθ(du)du]=EdPdataEuq(ud)[logq(ud)pθ(du)]

    • 因此我们很容易可以得到,我们期望的目标函数的变分下界为:
      log ⁡ P m o d e l ( d ) ≥ E u ∼ q ( u ∣ d ) [ log ⁡ p θ ( d − u ) q ( u ∣ d ) ] \log P_{model}(d) \ge \mathbb{E}_{u\sim q(u|d)}[\log \frac{p_{\theta}(d-u)}{q(u|d)}] logPmodel(d)Euq(ud)[logq(ud)pθ(du)]

    • 再加上与 v 的联合概率分布,以及条件 c_text,我们不难推出:
      log ⁡ P m o d e l ( d ∣ c t e x t ) ≥ E q ϕ ( u , v ∣ d , c t e x t ) [ log ⁡ p θ ( d − u , v ∣ c t e x t ) q ϕ ( u , v ∣ d , c t e x t ) ] \log P_{model}(d|c_{text}) \ge \mathbb{E}_{q_\phi(u,v|d, c_{text})}[\log\frac{p_\theta(d-u, v|c_{text})}{q_\phi(u,v|d,c_{text})}] logPmodel(dctext)Eqϕ(u,vd,ctext)[logqϕ(u,vd,ctext)pθ(du,vctext)]
      结论得证。

对抗学习部分(Adversarial Training)

  • 这一部分就很简单了,使用对抗学习使得训练过程更加高效。主要就是引入一个判别器 D 来判断模型输出是真实波形 y 还是解码器 G 输出的波形。损失函数则是选用了两种曾经成功运用于 TTS 任务的损失函数:

    • 最小二乘损失函数(least-squares loss function)(Mao et al., 2017),用于对抗训练。
      L a d v ( D ) = E ( y , z ) [ ( D ( y ) − 1 ) 2 + ( D ( G ( z ) ) ) 2 ] L a d v ( G ) = E z [ ( D ( G ( z ) ) − 1 ) 2 ] \mathcal{L}_{adv}(D) = \mathbb{E}_{(y,z)}[(D(y)-1)^2+(D(G(z)))^2] \\ \mathcal{L}_{adv}(G) = \mathbb{E}_{z}[(D(G(z))-1)^2] Ladv(D)=E(y,z)[(D(y)1)2+(D(G(z)))2]Ladv(G)=Ez[(D(G(z))1)2]

    • 额外的特征匹配损失(feature-matching loss) (Larsen et al., 2016),用于训练生成器(generator)
      L f m ( G ) = E ( y , z ) [ ∑ l = 1 T 1 N l ∥ D l ( y ) − D l ( G ( z ) ) ∥ 1 ] \mathcal{L}_{fm}(G) = \mathbb{E}_{(y,z)}[\sum_{l=1}^{T}\frac{1}{N_l}\lVert D^l(y)-D^l(G(z))\rVert_1] Lfm(G)=E(y,z)[l=1TNl1Dl(y)Dl(G(z))1]

      • T 表示判别器中的总层数
      • D^l 输出具有 N_l 特征数的判别器的第 l 层的特征图
  • 值得一提的是,这两部分损失函数和 HiFiGAN 的生成器损失函数基本相同,如果想要深入了解可以参考相关论文,这里不作过多赘述。其中,特征匹配损失可以看作是在判别器的隐藏层中测量的重建损失,用于约束判别器中间层的输出。

损失函数总结

  • 综合上面所有讲述的内容,我们这个结合了 VAE 和 GAN 训练方式的模型,最终的训练损失函数如下:
    L v a e = L r e c o n + L k l + L d u r + L a d v ( G ) + L f m ( G ) \mathcal{L}_{vae} = \mathcal{L}_{recon} + \mathcal{L}_{kl} + \mathcal{L}_{dur} + \mathcal{L}_{adv}(G) + \mathcal{L}_{fm}(G) Lvae=Lrecon+Lkl+Ldur+Ladv(G)+Lfm(G)

模型架构介绍

  • 通过上面的介绍,现在我们也可以好好将整个模型进行呈现。以训练过程为例,模型组成如下:

后验编码器(Posterior Encoder)【仅用于训练】

  • 在训练时后验编码器以线性谱为输入,输出隐变量 z。推理阶段隐变量 z 则由流模型产生。VITS 的后验编码器采用 WaveGlow 和 Glow-TTS 中的非因果 WaveNet 残差模块。应用于多人模型时,可以将说话人向量添加到残差模块。

先验编码器(Prior Encoder)

  • 先验编码器包括文本编码器(Text Encoder)和提升先验分布多样性的标准化流。文本编码器为基于相对位置编码的 transformer 编码器。我们将**线性投影层(Linear Projection Layer)**添加到文本编码器的最后一层,这样就能生成构建先验分布的均值和方差。标准化流模块包含若干 WaveNet 的残差块。应用于多人模型时,可以向标准化流的残差模块添加说话人向量。

解码器(Decoder)

  • 解码器的结构与 HiFi-GAN V1 的生成器结构相同,应用于多人模型时,会将说话人向量线性变换后与隐变量 z 拼接在一起。

判别器(Discriminator)【仅用于训练】

  • 判别器的结构与 HiFI-GAN 中的多周期判别器结构相同。

随机持续时间预测器(Stochastic Duration Predictor)

  • 随机时长预测器用文本音素表示的隐状态 h_text 作为条件输入,用来估计音素的时长分布。应用于多人模型时,会将说话人向量线性变换后与隐状态 h_text 拼接在一起。

推理阶段架构

  • 最后再将推理时的模型架构给出:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/440619.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Day25:安全开发-PHP应用文件管理模块包含上传遍历写入删除下载安全

目录 PHP文件操作安全 文件包含 文件删除 文件编辑 文件下载 云产品OSS存储对象去存储文件(泄漏安全) 思维导图 PHP知识点 功能:新闻列表,会员中心,资源下载,留言版,后台模块,模版引用,框…

单机版openstack安装

说明: 本文环境:CentOS 7 x64位 1.创建虚拟机 2.在虚拟机中安装 centos 7(最小安装),修改主机名:openstack,设置 root 密码:12345678 3. 网卡设置,重启网络服务&#…

黑马点评-好友关注实现

关注和取关 针对用户的操作,可以对用户进行关注和取消关注功能: 需要实现两个接口: 关注和取关接口 判断是否关注的接口 接口: //关注和取关 PutMapping("/{id}/{isFollow}") public Result follow(PathVariable(&…

听 GPT 讲 client-go 源代码 (22)

分享更多精彩内容,欢迎关注! File: client-go/applyconfigurations/core/v1/attachedvolume.go 在client-go项目中,client-go/applyconfigurations/core/v1/attachedvolume.go文件的作用是为Kubernetes的CoreV1 API对象AttachedVolume提供应用…

2024如何搭建测试平台?理清思路很重要!

01、职责 一个健康的测试平台体系,对测试人员的职责分工、协作模式会有不同的要求。 测试平台核心的职责是完成高质量的交付已满足业务需求。测试活动包括单元测试、集成测试、接口测试、性能测试等,都是通过这些测试手段,协同整个测试平台…

JsonCreator注解InvalidDefinitionException报错解决

"stack_trace": "c.f.j.d.e.InvalidDefinitionException: More than one argument (#0 and left as delegating for Creator [constructor for (

ArcGIS学习(十一)公服设施服务区划分与评价

ArcGIS学习(十一)公服设施服务区划分与评价 本任务带来的内容是公服设施服务区划分与公服设施服务区评价。本任务包括两个关卡: 公服设施服务区划分公服设施服务区空间价值评价1.公服设施服务区划分 首先,来看看这个案例的场景和基础数据。我们以上海市图书馆为例进行分析…

day3 FreeRTOS

抢占式调度 osThreadId_t defaultTaskHandle; const osThreadAttr_t defaultTask_attributes {.name "defaultTask",.stack_size 128 * 4,.priority (osPriority_t) osPriorityNormal, }; /* Definitions for myTask02 */osThreadId_t myTask03Handle; const os…

005-事件捕获、冒泡事件委托

事件捕获、冒泡&事件委托 1、事件捕获与冒泡2、事件冒泡示例3、阻止事件冒泡4、阻止事件默认行为5、事件委托6、事件委托优点 1、事件捕获与冒泡 2、事件冒泡示例 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /…

Linux的top命令解析

Top命令是什么 TOP命令是Linux下常用的性能分析工具&#xff0c;能够实时显示系统中各个进程的资源占用状况。 TOP是一个动态显示过程,即可以通过用户按键来不断刷新当前状态.如果在前台执行该命令,它将独占前台,直到用户终止该程序为止.比较准确的说,top命令提供了实时的对系…

全链路Python环境迁移

全链路Python环境迁移 在当前的Python环境中&#xff0c;安装一些库以后&#xff0c;如果换了一套Python环境&#xff0c;难道再来一次不停的pip install&#xff1f;当然不是。 第一步&#xff0c;使用pip freeze&#xff08;冻结&#xff09;备份当前Python库的环境 pip f…

一起来读李清照

当然先祝各位女生节日快乐&#x1f381;&#x1f381;啦​。​ 但是呢&#xff0c;今天&#xff0c;我们不聊技术&#xff0c;来聊点其他的。 大家都知道今天是三八妇女节&#xff0c;三八妇女节的是中国人的叫法&#xff0c;也叫国际妇女节。是为了纪念妇女权利的运动&#…

测试环境搭建整套大数据系统-问题篇(一:实时遇到的问题)

1. java.io.IOException: Failed to deserialize JSON ‘{“age”:867,“sex”:“fba8c074f9”,“t_insert_time”:“2024-03-04 14:12:24.821”}’ 解决方式 修改数据类型。将TIMESTAMP_LTZ改为TIMESTAMP。 2. java. lang,classNotFoundException: org,apache.flink,streami…

代理模式以及静态代理、JDK代理、Cglib代理的实现

代理模式&#xff08;Proxy&#xff09; 介绍 1、代理模式&#xff1a;为对象提供一个替身&#xff0c;以控制对这个对象的访问&#xff0c;即通过代理对象访问目标对象&#xff0c;这样做的好处是&#xff1a;可以在目标对象实现的基础上&#xff0c;增强额外的功能操作 &…

2024 AI 辅助研发的新纪年

随着人工智能技术的持续发展与突破&#xff0c;2024年AI辅助研发正成为科技界和工业界瞩目的焦点。从医药研发到汽车设计&#xff0c;从软件开发到材料科学&#xff0c;AI正逐渐渗透到研发的各个环节&#xff0c;变革着传统的研发模式。在这一背景下&#xff0c;AI辅助研发不仅…

不允许你不知道Python函数的返回值

函数可以通过return一次性返回多个数据&#xff0c;返回的数据以元组的形式保存。函数中若出现了return&#xff0c;return后面的程序不会执行。若函数中需要将某些数据返回&#xff0c;使用关键字return。若return后面没有返回任何数据&#xff0c;仅仅表示结束程序&#xff0…

Haproxy介绍、安装

Haproxy介绍、安装 文章目录 Haproxy介绍、安装1.Haproxy介绍1.1 企业版1.2 社区版1.3 版本对比1.4 HAProxy功能 2.HAProxy安装2.1 主机初始化2.1.1 设置网卡名和ip地址2.1.2 配置镜像源2.1.3 关闭防火墙2.1.4 禁用SELinux2.1.5 设置时区 2.2 包安装2.2.1 Ubuntu 安装2.2.2 Cen…

WEB接口测试之Jmeter接口测试自动化 (二)(数据分离)

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

数据结构八大算法详解

一、直接插入排序 直接插入排序的核心思想就是&#xff1a;将数组中的所有元素依次跟前面已经排好的元素相比较&#xff0c;如果选择的元素比已排序的元素小&#xff0c;则交换&#xff0c;直到全部元素都比较过。 因此&#xff0c;从上面的描述中我们可以发现&#xff0c;直接…