声码器 | WaveRNN:声码器的深度学习思路
知更鸟 Lv4

论文摘要

序列模型对于数据分布的估计和高质量样本的生成任务,已经能够达到SOTA的水平,但是就采样 的有效性来说仍然有待提高。本文针对TTS中的声码器,提出了一些降低采样的时间、同时保持高质量输出的通用方法。论文的模型的结构是简单的一层RNN,取名为 WaveRNN,特点是有两个 softmax 输出层,能够达到和 WaveNet 相匹配的结果。

WaveRNN 结构本身对于 24k 16-bit 的音频生成任务,能够在 GPU 上达到4倍实时的速度;另外,论文还针对网络参数进行了权重裁剪 (weight pruning),当模型参数量不变时,更大更稀疏的 WaveRNN 会有更好的效果,这一结论当稀疏比达到 96% 时仍然成立。所以,稀疏 的 WaveRNN 使得在移动端 CPU 设备上进行高保真的音频采样成为可能。

论文还提出了一种新的生成模式,基于 subscaling 将一个长序列转换成一个 batch 的短序列,从而能够同一时间步生成多个采样点。Subscale WaveRNN 一个时间步生成16 个采样点,同时没有损失合成语音的质量,可以作为一种提高采样效率的范式。

背景介绍

序列生成的任务中,模型学习的是模型的联合概率分布,可以将分布拆为条件概率的乘积,每个 采样点的概率是基于之前采样点的条件概率。两个好处:分解之后估计每个条件因子时的训练和推理更加鲁棒;具有严格的时序前后特点,每个采样点必须在它依赖的采样点生成之后才能生成,但这样的特点也会导致生成高维的序列(语音/视频)时速度难以达到应用水平。本文的目的即是解决采样的效率(速度),同时不损失模型生成语音的质量。

首先建模一下模型运算的耗费时间:每个采样点花费的时间 * 采样点个数。每个采样点花费的时间包含:N层*(每层的运算时间 c(op) + 每层的额外 overhead 开销d(op))。overhead开销可能包含程序的启动、数据的通讯等等时间,除了矩阵/向量浮点运算之外的时间开销都 可以计入 overhead。

image

从公式可以看出,模型运算时间的影响因素有四个:

  1. |u|:采样点个数,对于 24k 的 16bit 位深的音频来说,1s 有 24000 个采样点需要生成,计算量很大;
  2. N:网络层数,比如 WaveNet的深层 CNN 结构,N 的影响很大
  3. c(op):比如神经网络层之间的权值矩阵,隐含结点过多/参数量过大,导致相同算力的情况下运算时间更长
  4. d(op):当启动每个单独的计算程序时间消耗比较大时,d(op) 也会明显影响采样速度

减小模型计算量的方法

论文针对 TTS 声码器,从以上四方面减小了模型的计算量,同时保持合成质量不变。

1. 减小 N

使用RNN是因为非线性表达能力高,而且适用于序列建模,模型的输出是两个 softmax 层用于预测 16-bit 的样本点值。WaveRNN 对于每个 16bit 的样本点,矩阵向量乘法的次数为 N=5,与之效果相当的 WaveNet 结构,则需要 30 个残差 block,每个 block 两层网络,即 N=60 个矩阵向量乘法。

2. 减小 overhead d(op)

即使 N 比较小,overhead 也是一个比较大的计算瓶颈,对于单卡 P100 的实验,论文提出的 WaveRNN 每秒可以生成 96k 个 16-bit 的采样点,对于 24k/16bit 的目标音频来说 ,相当于 4 倍实验的合成效果。但是对于WaveNet,同样条件下却只能达到0.3倍实时 。batch 为 4 时,总吞吐量可以提升至每秒 156k 个采样点。

3. 减小计算量 c(op)

减小模型的参数量,能够减小计算量,所以在计算量受限的情况下,需要进行模型剪枝或稀疏化。论文发现更大的稀疏的 RNN 比不稀疏的 dense 效果更好,即使稀疏度高于 96% 这个结论也成立。

Sparse WaveRNN 应用在移动端 CPU 上的三个要点:sparse 参数量小,内存消耗小,而且性能无损失。相比于 GPU 上的模型参数量,CPU 端的参数量是百分之甚至千分之量级,但是是首个能够在移动端可用的 TTS 语音合成模型。

4. 关于采样点的个数

提高采样点计算的并行度,前人工作会在序列模型的基础上引入一些局部信息假设、或者引入一些 domain 的专门的 loss (会影响到模型的泛化能力)。论文提出一种 subscaling 的并行化生成方式。

We propose a generation process based on subscaling. **A tensor of scale L is folded into B sub-tensors of scale L/B. **The B sub-tensors are generated in order, each conditioned on the previous sub-tensors. Subscaling lets us generate multiple samples at once in a batch. Since the conditioning of the generation of each sub-tensor on previous sub-tensors requires in practice only a relatively small future horizon, the generation of the next sub-tensor may start soon after the start of the generation for the previous sub-tensor. It is possible in principle – although not necessary in practice – to recover distant future and past dependencies beyond the horizon; **the precise cost of batched sampling is then just the B distant dependencies between the samples in the current batch. **The Subscale WaveRNN is able to produce B = 16 samples per step without loss in audio fidelity as evidenced by A/B comparison tests (Table 1). Batched sampling for the Subscale WaveRNN opens many orthogonal ways of increasing sampling efficiency. Even our regular Tensorflow implementation of the model achieves real-time sampling speed on a Nvidia V100 GPU. A Fused variant of Subscale WaveRNN also gives a sampling speed of 10× real time on a Nvidia P100 GPU using a slight modification of the GPU kernel for WaveRNN-896.

WaveRNN 模型细节

1. 为什么选择 RNN 模型?

CNN 模型在 WaveNet 中得到应用,达到了很好的效果,但是模型是窄而深的结构,对于每个采样点来说需要很多层的计算。RNN具有同样的建模效果,而且context的非线性变换形式更适合样本生成的任务——仅通过一次非线性变换即可将context建模到模型中。

2. WaveRNN 的建模方式

WaveRNN 的计算流程如下所示:

image

image

  • 采样点一共是 16位 (位深),高 8 位记作 c = coarse,低 8 位记作 f = fine。
  • 将16位的采样点分成两个 8 bit 的部分,每部分整数值的范围为 [0,255],规整到[-1,1]区间内作为预测的目标。****两个8bit分别预测,dual softmax layer,将一个大区间内的预测问题拆分成两个小区间内的预测问题
  • ut, rt, et的计算公式中带有I*,表示 mask 矩阵
  • 高8位的 coarse 输入 ct,只和 ut, rt, et, ht 的 fine part 也就是低8位有关,因此只会影响到低8位的输出 yt
  • 矩阵 R 由Ru, Rr, Re 三部分构成,分别计算可得到 ut, rt, et。
  • σ 和 τ 分别是 sigmoid 和 tanh 函数
  • ft 的计算是 依赖于 ct 的,
  • 一种可能的架构变体是让ht仅依赖于xt_1并使用一个全连接层,然后使用求和或拼接基于ct计算ft;这个版本需要多出 20% 的参数,并且性能也差了一些。
The multiplication by R happens for both the coarse and fine bits simultaneously, then output of the gates is evaluated for the coarse bits only and ct is sampled. Once ct has been sampled from P(ct), the gates are evaluated for the fine bits and ft is sampled.
由于f(t)的值依赖于c(t),所以必须先计算c(t),为什么c(t)要作为生成c(t)的输入呢?其实作者把公式写成这样只是为了简便,矩阵I其实就是一个mask matrix,用来切断输入中c(t)和输出c(t)的一切连接。因此上述公式除了最后两个之外,其实都是要计算两遍的。

简单理解,WaveRNN 模型的本意是将 ct和 ft 两部分分开后单独预测,采用 multi-task 双 softmax loss 的形式来训练/预测,但在预测 ft 时要依赖于ct,所以流程上应该是高 8 bit 的c 先经过RNN预测采样后,再作为 ft 的预测输入 (ft condition on ct)。

论文比较,不采用 dual loss,而是直接 RNN 预测 16-bit 的采样点输出,发现除了模型参数量、内存占用更大以外,模型的效果反而没有两个 8-bit 的dual loss 方案好。

3. WaveRNN 在 GPU 上的采样

On a GPU the primary hindrance is not the raw FLOPs required for sampling; rather, the difficulties are twofold: limits on the memory bandwidth and the time that it takes to launch each of the N operations
  • WaveRNN 在GPU上运算的效率,最主要的影响因素并不是模型计算的FLOPS浮 点运算数,而是来源于更重要的两方面:显存带宽 + N层网络各自运算的启动开销
  • 显存带宽:对于隐含层为896的WaveRNN模型来说,模型参数量为 3M 左右,普通的GPU运算,序列的每个实践步将模型load到显存中,1s=24k个采样点,带宽占用:3M*24k * 4 (每个参数是32位的浮点,占4个字节B),所以计算下来需要 288GB 的带宽,(P100 总带宽732GB),所以从带宽的角度来看,此时WaveRNN的实时率上限为3倍实时
  • GPU上运算的overhead 开销更大。对于GPU来说,每个计算的启动开销为5us,5层网络需要25us,所以1s最多启动1s/25us = 40000 = 40k个采样点,对于WaveNet 这种层数更深的模型来说,N=60时,每秒生成的采样点个数最多为3.3k个,这还只是 overhead 的时间开销,没有计入真正的矩阵运算时间。
  • 如果综合考虑上带宽/overhead 开销,普通的Tensorflow RNN实现情况下,WaveRNN每秒生成1600个采样点,WaveNet则只有170个

关于 WaveRNN 为什么选用 896 的隐含层

  • P100 GPU有56个多处理器,P100中每个多处理器为了获取完整的register file,对应的最小Warp数目(warp是调度和运行的基本单元)是8。P100的warp数=56*8=448,如果每个hidden state 对应n个Warp,那么hidden state 的数目需要是 448 的整数倍,P100 允许的最大的448的倍数为896。

如何解决以上问题

  • 采样过程作为一个长时的 persistent 的操作,模型一次性加入GPU寄存器后不再重复载入。P100有3.67M的全浮点寄存器,足够容纳7M个半精度的模型参数。
  • overhead 开销问题也因此解决了,因为不需要持续的启动计算
  • 解决了以上问题之后,WaveRNN 从每秒只能生成1600个采样点,提升至每秒可以生成96000个采样点,提升了60倍,WaveNet 从170 提升至8000个采样点。overhead 则变成了每次同步 synchronization 500纳秒

4. Sparse WaveRNN

N,d(op) 的问题解决之后,再解决 c(op) 的问题。降低隐含结点数不考虑,因为会大大损失模型精度。论文采用的是稀疏化的思想,减小网络中非0参数的个数,模型大小保持不变,但是提高参数中0的比例,达到大幅稀疏化的目的。非0参数的个数和运算量c(op) 是成正比的。

a) 稀疏化训练方案

二值mask,用于标记零和非零参数的位置。最开始矩阵是完整的dense的,每训练500步,每层的权重排序之后,将k个(总体权重个数的一个比例z)权值最小的参数置为0。置为0的部分所占比例随着训练 step 的变化关系为:

image

  • 启动weight pruning 的step:t0 = 1000
  • weight pruning 的全部step 数:S=200k
  • 全部训练step数:500k
  • 计算的粒度为每 500 次迭代变化一次
  • GRU 的三个门的权值矩阵是分别稀疏化的

b) 结构的稀疏化

  • 稀疏化的粒度从矩阵每个参数升级到block 级别,基于 block (不重叠) 的平均值排序后决定是否整个block 置零。这么做的好处是能够减轻存储 sparsity pattern 带来的内存消耗,block 大小m=16时,存储稀疏模式的内存可以降低至原来的1/16。
  • m=16时,论文比较了4 * 4 和 16 * 1 两种分块方案,其中161 有更好的优势,只需要进行一次激活,然后进行点积即可;而 44 则需要进行4次激活运算。

c) CPU上的 Sparse WaveRNN 采样

  • Sparse WaveRNN 具有低计算量、低带宽占用的优点,在移动端上,权重参数值存储为16-bit 的半浮点数,运算前会转换成32-bit 浮点,激活函数及运算结果保持为32位不变。每秒矩阵向量的运算数完全由网络的参数个数决定

5. Subscale WaveRNN

N, d(op), c(op) 都处理之后,需要解决 |u| 的问题,同时不损失合成语音的音质。论文提出了subscaling 的方法,能够并行化每次生成B个sample,相当于 |u| 的长度变成了:

image

In many cases, the computation time for a batch of B examples, c(opBi ), grows sublinearly in the computation time of a single example c(opi) because weights are reused and spare computational capacity is available. The ability to batch samples also makes it possible to generate across multiple processors and have a reduction in total sampling time that is linear in the number of processors.

subscale 的策略

image

关于 subscale 更细致的说明,详见https://medium.com/papercup-ai/subscale-wavernn-f91fc9c7a106

实验部分

1. 实验配置

  1. 训练数据:44小时美国北部英语,单个说话人
  2. 音频参数:24k,16bit位深
  3. 评价指标:
    1. 负对数似然:NLL
    2. MOS
    3. A/B 对比
  4. The generation is conditioned on conventional linguistic features and predicted pitch information

2. 实验结果

a) WaveRNN 合成的质量和速度

image

b) Sparse WaveRNN 的效果

image

c) Subscale WaveRNN

image

d) 结论

WaveRNN 结构 & SparseWaveRNN & Subscale RNN 能够达到和WaveNET 比较接近的结果,同时可以在GPU/CPU上满足实时性要求。