- 人工智能
- 语音
- 音频
- NLP
- 媒体生成
【免费下载链接】PaddleSpeech
Easy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation and Keyword Spotting. Won NAACL2022 Best Demo Award.
本篇文章聚焦飞桨 PaddleSpeech 中paddlespeech.t2s.exps.gan_vocoder.multi_band_melgan这一 API 模块,深入解析 Multi-Band MelGAN 神经声码器(GAN Vocoder)在 PaddleSpeech 中的训练实现:从 API 文档页 出发,逐一讲解训练入口脚本、生成器与多尺度判别器结构、PQMF 子带编解码原理、全频带/子带双路 STFT 损失与对抗损失的组合策略,并结合examples/csmsc/voc3给出从数据预处理、模型训练到波形合成的完整可复现流程。读完本文,你将掌握如何用 PaddleSpeech 训练、评估与部署 Multi-Band MelGAN 声码器,并理解其与 FastSpeech2 声学模型级联成完整 TTS 系统的方式。
一、模块定位:API 文档与代码的对应关系
在 PaddleSpeech 的 API 参考文档中,paddlespeech.t2s.exps.gan_vocoder.multi_band_melgan.rst 是 Sphinx 自动生成的模块文档页,核心内容如下:
.. automodule:: paddlespeech.t2s.exps.gan_vocoder.multi_band_melgan :members: :undoc-members: :show-inheritance:并通过toctree引入其唯一子模块 multi_band_melgan.train.rst。虽然.rst文件本身只是automodule指令的占位页,但它实际承载的内容就是被引用的 Python 模块的全部公开成员。该模块在仓库中的真实代码位于 paddlespeech/t2s/exps/gan_vocoder/multi_band_melgan/:
__init__.py:包初始化文件;train.py:Multi-Band MelGAN 的训练入口脚本,即本 API 文档页的主体。
从源码结构看,该模块属于paddlespeech/t2s/exps/gan_vocoder/实验代码体系,与hifigan、style_melgan、parallel_wavegan等声码器训练脚本并列,是 PaddleSpeech TTS 子系统中"声码器(Vocoder)"环节的实现之一。对应的模型实现位于 paddlespeech/t2s/models/melgan/melgan.py(生成器/判别器)、multi_band_melgan_updater.py(训练更新器/评估器)与 paddlespeech/t2s/modules/pqmf.py(子带滤波器组)。
二、训练入口:train.py的参数与主流程
训练脚本的命令行接口由 train.py 中的argparse定义,与examples/csmsc/voc3/README.md中给出的帮助信息一致:
usage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA] [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR] [--ngpu NGPU] Train a Multi-Band MelGAN model. optional arguments: --config CONFIG Multi-Band MelGAN config file. --train-metadata training data. --dev-metadata dev data. --output-dir output dir. --ngpu if ngpu == 0, use cpu.各参数作用如下:
| 参数 | 说明 |
|---|---|
--config | YAML 格式的模型配置文件,训练时以它为唯一配置来源,运行时通过yacs.config.CfgNode(yaml.safe_load(f))解析为CfgNode对象 |
--train-metadata | 训练集metadata.jsonl文件路径(预处理后dump/train/norm/下) |
--dev-metadata | 验证集metadata.jsonl文件路径(dump/dev/norm/下) |
--output-dir | 实验输出目录,checkpoint 保存在其checkpoints/子目录 |
--ngpu | 使用的 GPU 数量;ngpu == 0时使用 CPU |
主流程main()在读取配置后做了设备分派:当ngpu > 1时调用dist.spawn(train_sp, (args, config), nprocs=args.ngpu)启动多进程分布式训练,否则直接执行train_sp(args, config)。train_sp内部的核心步骤依次为:
- 运行环境初始化:根据是否编译 CUDA 以及
args.ngpu决定paddle.set_device("cpu"/"gpu");当world_size > 1时调用paddle.distributed.init_parallel_env()初始化并行环境; - 随机种子固定:调用
seed_everything(config.seed),代码注释明确指出"it is a must for multiprocess training"(多进程训练必须固定种子以保证可复现); - 数据集构建:用
jsonlines读取 metadata,构造DataTable,字段为["wave", "feats"],转换器均为np.load——即 metadata 中记录的是.npy文件的路径,加载得到波形数组与 mel 频谱数组; - DataLoader 与裁剪:训练/验证集均使用
DistributedBatchSampler,并用Clip批处理函数按batch_max_steps与n_shift(hop size)对波形与特征做长度裁剪(Clip定义于 paddlespeech/t2s/datasets/vocoder_batch_fn.py); - 模型构建:实例化
MelGANGenerator、MelGANMultiScaleDiscriminator,多卡时用DataParallel包装; - 损失与优化器:构建
MultiResolutionSTFTLoss(全频带)、MultiResolutionSTFTLoss(子带)、生成器/判别器对抗损失、PQMF 模块,并为生成器与判别器分别配置MultiStepDecay学习率调度器与Adam优化器; - 组装 Trainer:将
MBMelGANUpdater、MBMelGANEvaluator与Trainer组合,注册VisualDL、Snapshot扩展,按stop_trigger=(config.train_max_steps, "iteration")停止训练。
值得一提的实现细节是:训练脚本为生成器单独支持了梯度裁剪generator_grad_norm(nn.ClipGradByGlobalNorm,当值大于 0 时启用,否则为None不裁剪),并注释说明"Compared to multi_band_melgan.v1 config, Adam optimizer without gradient norm is used",即不同版本配置对梯度裁剪策略有差异。
三、生成器与判别器:melgan.py中的网络结构
Multi-Band MelGAN 的生成器与判别器定义在 paddlespeech/t2s/models/melgan/melgan.py(头文件注明"Modified from espnet")。
3.1 MelGANGenerator:子带输出的生成器
MelGANGenerator(melgan.py#L32)的构造函数参数即配置文件中generator_params的字段:
in_channels:输入 mel 频谱通道数,默认 80(与n_mels一致);out_channels:输出通道数,默认 1;在 Multi-Band 场景下,它等于子带数 subbands(默认 4),源码注释明确指出"the number of sub-band is out_channels in multi-band melgan";kernel_size:首尾卷积核大小,默认 7,要求为奇数(非因果卷积时断言(kernel_size - 1) % 2 == 0);channels:初始卷积通道数,需满足channels >= prod(upsample_scales)且channels % 2**len(upsample_scales) == 0;upsample_scales:上采样倍数列表,默认[8, 8, 2, 2],其乘积决定了 mel 帧到波形的总上采样倍率;stack_kernel_size/stacks:残差堆叠中空洞卷积核大小(默认 3)与堆叠层数(默认 3),空洞率按dilation = stack_kernel_size ** j递增;nonlinear_activation:默认leakyrelu,参数negative_slope=0.2;pad/pad_params:默认Pad1D+reflect反射填充;use_weight_norm:默认True,通过apply_weight_norm()递归对全部Conv1D/Conv2D/Conv1DTranspose层应用权重归一化;use_causal_conv:是否使用因果卷积(CausalConv1D/CausalConv1DTranspose),用于流式(streaming)场景;init_type:默认xavier_uniform。
网络按upsample_scales逐级堆叠:每级包含激活层 → 转置卷积(通道数逐级减半)→stacks个ResidualStack,最后接激活层、反射填充与输出卷积,并以nn.Tanh()作为最终非线性激活(当use_final_nonlinear_activation=True)。参数重置reset_parameters()遵循官方实现,使用均值为 0、标准差 0.02 的正态分布重采样卷积权重。
Multi-Band 的关键体现在推理路径inference()(melgan.py#L258):生成器输出张量形状为(B, out_channels, T ** prod(upsample_scales)),即每个子带一路波形;当out_channels > 1时,构造时会在生成器内部挂载self.pqmf = PQMF(subbands=out_channels),inference()中对子带输出执行pqmf(out)(即 synthesis 合成),把多路子带信号重建成全频带波形。
3.2 MelGANMultiScaleDiscriminator:三尺度判别器
判别器采用 MelGAN 的多尺度结构(melgan.py#L406),默认scales=3:输入波形先经AvgPool1D(kernel_size=4, stride=2, padding=1)逐级下采样得到多个尺度,每个尺度共享同一MelGANDiscriminator子网络。子网络结构为:首层卷积(核大小取kernel_sizes乘积,如 5×3=15)→ 多个下采样卷积层(核大小downsample_scale * 10 + 1,分组卷积groups=in_chs // 4)→ 两个末层卷积。forward返回每一层输出构成的列表(用于后续可选的 feature matching loss),各尺度输出由判别器对抗损失统一处理。
四、PQMF:子带分析与合成的基础模块
Multi-Band MelGAN 之所以能"多带",核心依赖伪正交镜像滤波器组 PQMF(Pseudo-Quadrature Mirror Filter),实现于 paddlespeech/t2s/modules/pqmf.py。该模块基于近完美重建(near-perfect-reconstruction)伪 QMF 滤波器组设计,默认参数subbands=4, taps=62, cutoff_ratio=0.142, beta=9.0(原型滤波器由design_prototype_filter用 Kaiser 窗法设计,注释说明 cutoff_ratio 与 beta 是针对 4 子带优化的)。
analysis(x):把全频带波形(B, 1, T)分解为(B, subbands, T // subbands)的子带信号;synthesis(x):把子带信号重建为全频带波形(B, 1, T);forward(x)即synthesis,注释说明"when converting dygraph to static graph, can not use self.pqmf.synthesis directly",即静态图转换时的兼容处理。
在训练脚本中,PQMF 以PQMF(subbands=config["generator_params"]["out_channels"])实例化并作为criterion_pqmf传入 updater:全频带波形由pqmf.analysis(wav)得到子带目标,生成器的子带输出wav_mb_通过pqmf.synthesis(wav_mb_)重建为全频带波形以计算全频带损失。这样,生成器在子带域输出、以"子带域+全频带域"双重监督进行优化。
五、训练策略:MBMelGANUpdater与MBMelGANEvaluator
训练与评估的核心逻辑封装在 multi_band_melgan_updater.py 中,分为MBMelGANUpdater(继承StandardUpdater)与MBMelGANEvaluator(继承StandardEvaluator)两个类。
5.1 生成器更新:多分辨率 STFT 损失 + 对抗损失
update_core中生成器更新流程如下:
- 生成器以 mel 频谱为输入输出子带波形
wav_(形状(B, out_channels, T ** prod(upsample_scales))),再经criterion_pqmf.synthesis得到全频带波形; - 全频带 Multi-resolution STFT loss:
criterion_stft(wav_, wav)返回频谱收敛损失sc_loss与 log-STFT 幅度损失mag_loss; - 子带 Multi-resolution STFT loss:先
pqmf.analysis(wav)得到子带目标wav_mb,再与生成器子带输出wav_mb_计算sub_sc_loss、sub_mag_loss; - 辅助损失按论文 Eq.(9) 组合:
aux_loss += 0.5 * (sc_loss + mag_loss)(全频带与子带各 0.5 系数),最终gen_loss += aux_loss * lambda_aux; - 当迭代步数超过
discriminator_train_start_steps后加入对抗损失:gen_loss += lambda_adv * adv_loss,其中adv_loss = criterion_gen_adv(p_),p_为判别器对生成波形wav_的判定; - 反向传播后
optimizer_g.step()与scheduler_g.step()同步推进。
训练过程中通过report()记录train/spectral_convergence_loss、train/log_stft_magnitude_loss、train/sub_spectral_convergence_loss、train/sub_log_stft_magnitude_loss、train/adversarial_loss、train/generator_loss等指标,这些指标与examples/csmsc/voc3/README.md中给出的评估表列名(eval/spectral_convergence_loss等)一一对应。
5.2 判别器更新与"慢启动"策略
判别器更新在state.iteration > discriminator_train_start_steps时触发(默认配置为 200000 步,见下节配置)。为了提升生成质量,判别器更新前会用paddle.no_grad()重新计算wav_(代码注释 "re-compute wav_ which leads better quality"),然后分别计算真实波形与生成波形(detach()后的)的判别输出,得到real_loss、fake_loss,二者之和为dis_loss。
MBMelGANUpdater构造函数还预留了generator_train_start_steps=0、lambda_aux=1.0、lambda_adv=1.0等参数,其中lambda_aux是辅助(STFT)损失的平衡系数,lambda_adv是对抗损失平衡系数,二者在train.py中从配置读取并传入。
5.3 评估器:与训练一致的指标口径
MBMelGANEvaluator.evaluate_core在验证集上同步计算对抗损失、全频带/子带 STFT 损失与判别器损失,指标以eval/前缀记录。train.py中评估器通过trainer.extend(evaluator, trigger=(config.eval_interval_steps, 'iteration'))注册,即每eval_interval_steps步在验证集上评估一次;VisualDL以(1, 'iteration')频率记录训练曲线;Snapshot(max_size=config.num_snapshots)按save_interval_steps保存快照。
六、配置文件详解:以 CSMSC 为例
examples/csmsc/voc3是仓库中基于中文标准女声库 CSMSC(Chinese Standard Mandarin Speech Copus)训练 Multi-Band MelGAN 的完整示例,其配置文件 examples/csmsc/voc3/conf/default.yaml 中的关键参数如下。
特征提取设置(与声学模型对齐):
| 参数 | 值 | 含义 |
|---|---|---|
fs | 24000 | 采样率 24kHz |
n_fft | 2048 | FFT 点数 |
n_shift | 300 | 帧移(hop size),约 12.5ms |
win_length | 1200 | 窗长,约 50ms |
window | "hann" | 窗函数 |
n_mels | 80 | mel 滤波器组个数 |
fmin/fmax | 80 / 7600 | mel 频率上下限(Hz) |
生成器架构(generator_params):
generator_params: in_channels: 80 # 输入 mel 通道数,与 n_mels 一致 out_channels: 4 # 输出子带数(Multi-Band 核心参数) kernel_size: 7 # 首尾卷积核大小 channels: 384 # 初始卷积通道数 upsample_scales: [5, 5, 3] # 上采样倍数,prod × out_channels == n_shift stack_kernel_size: 3 # 残差堆中空洞卷积核大小 stacks: 4 # 单个残差堆的堆叠层数 use_weight_norm: True # 是否使用权重归一化 use_causal_conv: False # 是否使用因果卷积 use_final_nonlinear_activation: True注意注释强调prod(upsample_scales) x out_channels == n_shift(5×5×3×4 = 300 = n_shift),这正是 Multi-Band MelGAN 的分辨率约束:每个子带负责四分之一带宽,子带 hop 相应缩小。
判别器架构:scales: 3(三尺度)、kernel_sizes: [5, 3]、channels: 16、max_downsample_channels: 512、downsample_scales: [4, 4, 4]、激活为leakyrelu(negative_slope: 0.2)。
损失配置:use_stft_loss: True且全频带stft_loss_params的fft_sizes: [1024, 2048, 512]、hop_sizes: [120, 240, 50]、win_lengths: [600, 1200, 240];use_subband_stft_loss: True且子带损失fft_sizes: [384, 683, 171]、hop_sizes: [30, 60, 10]、win_lengths: [150, 300, 60]——子带损失的各窗口尺寸约为全频带的三分之一左右,与 4 子带划分相适配。lambda_adv: 2.5为对抗损失平衡系数,use_feat_match_loss: False表示本配置未使用特征匹配损失。
优化器与调度:生成器与判别器均为Adam(epsilon: 1.0e-7、weight_decay: 0.0),学习率 1.0e-3,MultiStepDecay在milestones: [100000, 200000, 300000, 400000, 500000, 600000]处以gamma: 0.5逐级衰减;generator_grad_norm: -1、discriminator_grad_norm: -1表示本配置不启用全局梯度裁剪。
训练步数:discriminator_train_start_steps: 200000(前 20 万步只训练生成器)、train_max_steps: 1000000、save_interval_steps: 5000、eval_interval_steps: 1000;数据侧batch_size: 64、batch_max_steps: 16200(需能被n_shift整除)、num_workers: 2;其他num_snapshots: 10、seed: 42。
七、端到端实操:从数据到合成
7.1 数据准备与预处理
按照 examples/csmsc/voc3/README.md,首先从 CSMSC 官网下载数据集解压到~/datasets/BZNSYP,并使用 MFA(Montreal Forced Aligner)对齐结果切除音频边缘静音。随后执行:
./run.sh --stage 0 --stop-stage 0 # 只做数据预处理 # 或直接 ./run.sh 依次完成预处理、训练、合成预处理脚本./local/preprocess.sh ${conf_path}结束后会在当前目录生成dump目录,结构如下:
dump ├── dev │ ├── norm │ └── raw ├── test │ ├── norm │ └── raw └── train ├── norm ├── raw └── feats_stats.npy数据集被划分为train、dev、test三部分,各含raw(log 幅度 mel 频谱)与norm(归一化后频谱)子目录;归一化统计量由训练集计算得到,存于dump/train/feats_stats.npy。每个子目录下还有metadata.jsonl,是记录音频 id 与频谱文件路径的表格式文件,即训练脚本--train-metadata/--dev-metadata的输入。
7.2 模型训练
CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}./local/train.sh实际调用${BIN_DIR}/train.py(即上文的训练脚本),--train-metadata与--dev-metadata分别指向dump/train/norm与dump/dev/norm下的metadata.jsonl,--output-dir为实验输出目录,checkpoint 保存于其checkpoints/目录。
7.3 波形合成
合成分为两种模式:
- 从 metadata 合成(
./local/synthesize.sh调用synthesize.py):参数包括--generator-type(取值{pwgan, mb_melgan, style_melgan, ...})、--config、--checkpoint、--test-metadata、--output-dir、--ngpu; - 端到端从文本合成(
./local/synthesize_e2e.sh调用synthesize_e2e.py):通过--am指定声学模型(如fastspeech2_csmsc)、--voc指定声码器(如mb_melgan_csmsc),并配套提供--am_config、--am_ckpt、--am_stat、--phones_dict与--voc_config、--voc_ckpt、--voc_stat等文件,形成"FastSpeech2 声学模型 + Multi-Band MelGAN 声码器"的完整 TTS 链路。仓库中examples/csmsc/tts3等端到端示例即采用这一组合,run.sh中的--stage/--stop-stage机制允许按阶段单独执行。
7.4 微调(Fine-tuning)
由于 Multi-Band MelGAN 输入没有噪声项,直接用真实频谱训练时音质仍有提升空间。README 记录了参照 HiFiGAN 思想的微调方案:先下载预训练 FastSpeech2 模型,用其预测的 mel 频谱(配合真实对齐时长)与训练阶段使用的真实波形重新构造dump_finetune数据集(波形软链接自原dump,频谱换为声学模型预测的 ground-truth-aligned mel,并复用原feats_stats.npy做归一化),然后基于conf/finetune.yaml从预训练 checkpoint 继续训练。微调前需将预训练模型放入${output-dir}/checkpoints并编写records.jsonl指明其路径与迭代步数(如{"time": "...", "path": ".../snapshot_iter_1000000.pdz", "iteration": 1000000}),最后执行./finetune.sh。
7.5 预训练与导出产物
README 提供的预训练/导出产物覆盖多种部署形态,包括普通 checkpoint(mb_melgan_csmsc_ckpt)、微调模型(mb_melgan_baker_finetune_ckpt)、静态图模型(_static_)、PIR 静态模型(需paddlepaddle>=3.0.0b2且设置FLAGS_enable_pir_api=1)、ONNX 模型与 Paddle-Lite 模型(_pdlite_)。每个 Multi-Band MelGAN 发布包均包含三件套:default.yaml(训练配置)、feats_stats.npy(频谱归一化统计量)与snapshot_iter_1000000.pdz(生成器参数)。
八、总结
PaddleSpeech 的paddlespeech.t2s.exps.gan_vocoder.multi_band_melgan模块承载了 Multi-Band MelGAN 声码器的完整训练闭环。通过本文可以梳理出该实现的几条主线:
- 多带架构:生成器直接输出 4 个子带波形(
out_channels=4),由 PQMF 负责子带分解(analysis)与全频带重建(synthesis),使整体上采样负担分摊到子带,降低模型计算量; - 双路频谱监督:全频带与子带各一路 Multi-Resolution STFT 损失,按论文 Eq.(9) 以 0.5 系数加权组合,配合延迟 20 万步启动的对抗损失与三尺度判别器共同优化;
- 工程完备性:支持多卡分布式训练、VisualDL 可视化、快照保存、动态图/静态图转换兼容,并配套从数据预处理、训练、合成到微调、多种部署产物导出的完整示例(examples/csmsc/voc3);
- 生态集成:作为 TTS 声码器环节,可与 FastSpeech2 等声学模型级联(
--voc mb_melgan_csmsc)实现文本到语音的端到端合成。
对希望深入源码的读者,建议按 train.py → multi_band_melgan_updater.py → melgan.py → pqmf.py 的顺序阅读,再结合 default.yaml 与 voc3/README.md 跑通一个 CSMSC 训练实验,即可完整掌握该声码器的原理与实战方法。
- 人工智能
- 语音
- 音频
- NLP
- 媒体生成
【免费下载链接】PaddleSpeech
Easy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation and Keyword Spotting. Won NAACL2022 Best Demo Award.
相关推荐
PaddleSpeech MelGAN 神经声码器源码深度解析:MelGAN / Multi-Band MelGAN / StyleMelGAN 全家族 API 与实现
PaddleSpeech MelGAN 神经声码器源码深度解析:MelGAN / Multi Band MelGAN / StyleMelGAN 全家族 API
人工智能语音音频Jaeger 的 Elasticsearch 存储后端:索引建模、数据写入与集成测试实战指南
Jaeger 的 Elasticsearch 存储后端:索引建模、数据写入与集成测试实战指南 本文以 Jaeger 仓库中 Elasticsearch 存储后端
人工智能语音音频NLP媒体生成lo 库 Slice 切片操作全家桶:从 `lo.Slice` 安全切割到 `Splice` 插入、`Drop` 裁剪与 `Replace` 替换的完整实战指南
lo 库 Slice 切片操作全家桶:从 lo.Slice 安全切割到 Splice 插入、 Drop 裁剪与 Replace 替换的完整实战指南 导读 切片(
人工智能语音音频
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考