- 人工智能
- 语音
- 音频
【免费下载链接】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 仓库中的 examples/opencpop/voc1 示例为主线,完整讲解如何用中文普通话歌唱数据集 Opencpop 训练 Parallel WaveGAN(并行波网)声码器,并覆盖数据预处理、模型训练、波形合成、动转静与量化部署的端到端流程。读完本文,你将掌握该示例的run.sh流水线各阶段用法、conf/default.yaml 中全部超参数的语义与调参要点,以及train.py/synthesize.py的底层实现原理,能够独立复现一个面向歌声合成(SVS)场景的高质量声码器。
一、背景:为什么歌声合成需要 Parallel WaveGAN
在 PaddleSpeech 的歌声合成(Singing Voice Synthesis, SVS)技术栈中,声码器(Vocoder)承担着将声学特征(通常是梅尔频谱)还原为时域波形的关键角色。Parallel WaveGAN 是一种基于对抗生成思路的并行神经声码器,与自回归声码器相比,它可以在一次前向传播中并行生成整段波形,显著降低合成耗时,同时通过多分辨率 STFT 损失与对抗损失的联合优化保持高音质。该模型由 kan-bayashi/ParallelWaveGAN 项目提出,PaddleSpeech 在 paddlespeech/t2s/models/parallel_wavegan/parallel_wavegan.py 中提供了 Paddle 实现(文件头部注明 "Modified from espnet",本示例 Acknowledgement 部分也说明参考了原实现)。
本示例对应的核心代码路径为:
- 训练脚本:paddlespeech/t2s/exps/gan_vocoder/parallelwave_gan/train.py
- 模型定义:paddlespeech/t2s/models/parallel_wavegan/parallel_wavegan.py
- 预处理与合成:paddlespeech/t2s/exps/gan_vocoder/preprocess.py、paddlespeech/t2s/exps/gan_vocoder/synthesize.py
该示例位于 examples/opencpop/voc1,与同目录下的歌声合成器示例 examples/opencpop/svs1 配套使用:svs1 负责训练歌声合成器(生成梅尔频谱),voc1 负责训练声码器(将梅尔频谱还原为歌声波形)。
二、数据集准备:下载与目录结构
Opencpop 是用于中文歌声合成研究的普通话歌唱数据集,由 WeNet 社区发布。按 README 说明,从其官网下载数据集后解压到~/datasets,得到数据集根目录~/datasets/Opencpop。
预处理脚本 examples/opencpop/voc1/local/preprocess.sh 中实际使用的数据路径为:
--rootdir=~/datasets/Opencpop/segments/:存放分句后的歌声片段音频的目录(wavs子目录)--dur-file=~/datasets/Opencpop/segments/transcriptions.txt:音素时长标注文件,同时提供说话人信息
从预处理源码 paddlespeech/t2s/exps/gan_vocoder/preprocess.py(main()函数中args.dataset == "opencpop"分支)可以看到 Opencpop 特有的数据划分逻辑:音频从rootdir / "wavs"读取,训练集由train.txt中的 utt 列表确定,测试集由test.txt确定,其中test.txt的前 106 条被划为dev,其余归入test。因此,请确保解压后的Opencpop目录中包含segments/wavs、segments/transcriptions.txt、train.txt、test.txt等文件。
三、一键流水线:run.sh 的阶段控制
进入示例目录(注意path.sh会通过MAIN_ROOT定位仓库根目录并设置BIN_DIR指向paddlespeech/t2s/exps/gan_vocoder/parallelwave_gan):
cd examples/opencpop/voc1 ./run.shrun.sh使用 utils/parse_options.sh 解析--stage与--stop-stage参数,默认配置为gpus=0、conf_path=conf/default.yaml、train_output_path=exp/default、ckpt_name=snapshot_iter_100000.pdz。各阶段含义如下(源码见 examples/opencpop/voc1/run.sh):
| Stage | 行为 | 调用脚本 |
|---|---|---|
| 0 | 数据预处理(特征提取、统计量计算、归一化) | ./local/preprocess.sh |
| 1 | 训练模型,checkpoint 保存在exp/default/checkpoints/ | ./local/train.sh |
| 2 | 用测试集合成波形 | ./local/synthesize.sh |
| 3 | 动态图转静态图推理模型 | ./local/dygraph_to_static.sh |
| 4 | 静态图 PTQ 量化并导出 ONNX 格式 | ./local/PTQ_static.sh |
只需运行预处理阶段:
./run.sh --stage 0 --stop-stage 0当你想从某个阶段继续或只执行特定阶段时,均可用--stage N --stop-stage N精确控制,这与 parse_options.sh 的通用约定一致。
四、数据预处理:从歌声片段到梅尔频谱特征
预处理脚本的完整调用方式:
./local/preprocess.sh ${conf_path}脚本内部按三个阶段执行(见 examples/opencpop/voc1/local/preprocess.sh):
- 特征提取:调用
python3 ${BIN_DIR}/../preprocess.py,参数包括--rootdir=~/datasets/Opencpop/segments/、--dataset=opencpop、--dumpdir=dump、--dur-file、--config、--cut-sil=False、--num-cpu=20。此处--cut-sil=False表示不对歌声片段做边缘静音切除(歌唱数据通常已由数据集切分好);--num-cpu=20表示使用 20 线程并行处理。 - 统计量计算:调用
${MAIN_ROOT}/utils/compute_statistics.py --metadata=dump/train/raw/metadata.jsonl --field-name="feats",从训练集原始特征计算均值和标准差,保存为dump/train/feats_stats.npy。 - 归一化:调用
normalize.py三次,分别对 train、dev、test 的 raw 特征做归一化,注意dev 与 test 必须复用 train 的统计量,以保证与训练时特征分布一致。
处理完成后当前目录生成dump文件夹:
dump ├── dev │ ├── norm │ └── raw ├── test │ ├── norm │ └── raw └── train ├── norm ├── raw └── feats_stats.npy从源码 paddlespeech/t2s/exps/gan_vocoder/preprocess.py 的process_sentence()可以看出特征提取细节:读取音频后先按config.fs(24000 Hz)重采样,将样本对齐到num_frames * n_shift的整数倍,随后用LogMelFBank(其参数取自配置文件的fs / n_fft / n_shift / win_length / window / n_mels / fmin / fmax)提取对数梅尔频谱。每个音频产出两个.npy文件:
{utt_id}_feats.npy:形状为(num_frames, n_mels)的对数梅尔频谱{utt_id}_wave.npy:形状为(num_samples,)的对齐后的时域波形
raw子目录存放的就是这些未归一化的频谱(对数梅尔频谱),norm子目录存放经feats_stats.npy归一化后的频谱。
每个子目录内还有一个metadata.jsonl,它是"表状"的记录文件,每行包含utt_id、num_samples、num_frames、feats(特征文件路径)、wave(波形文件路径)等字段,供训练与合成阶段的数据加载器(DataTable)直接读取。
五、模型训练:train.py 参数与配置深度解析
训练命令:
CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${train_output_path}train.sh 内部设置了FLAGS_cudnn_exhaustive_search=true与FLAGS_conv_workspace_size_limit=4000两个 Paddle FLAGS,然后调用${BIN_DIR}/train.py,传入--train-metadata=dump/train/norm/metadata.jsonl、--dev-metadata=dump/dev/norm/metadata.jsonl、--config、--output-dir与--ngpu=1。
train.py(源码:paddlespeech/t2s/exps/gan_vocoder/parallelwave_gan/train.py)的完整帮助信息:
usage: train.py [-h] [--config CONFIG] [--train-metadata TRAIN_METADATA] [--dev-metadata DEV_METADATA] [--output-dir OUTPUT_DIR] [--ngpu NGPU] [--batch-size BATCH_SIZE] [--max-iter MAX_ITER] [--run-benchmark RUN_BENCHMARK] [--profiler_options PROFILER_OPTIONS] Train a ParallelWaveGAN model. optional arguments: -h, --help show this help message and exit --config CONFIG ParallelWaveGAN config file. --train-metadata TRAIN_METADATA training data. --dev-metadata DEV_METADATA dev data. --output-dir OUTPUT_DIR output dir. --ngpu NGPU if ngpu == 0, use cpu. benchmark: arguments related to benchmark. --batch-size BATCH_SIZE batch size. --max-iter MAX_ITER train max steps. --run-benchmark RUN_BENCHMARK runing benchmark or not, if True, use the --batch-size and --max-iter. --profiler_options PROFILER_OPTIONS The option of profiler, which should be in format "key1=value1;key2=value2;key3=value3".参数使用说明:
--config:yaml 格式配置文件,用于覆盖默认配置,即 conf/default.yaml。--train-metadata、--dev-metadata:应使用dump文件夹中 train 与 dev 的norm子目录下的metadata.jsonl。--output-dir:实验结果保存目录,checkpoint 保存在该目录的checkpoints/子目录中。--ngpu:使用的 GPU 数量,ngpu == 0时使用 CPU;ngpu > 1时train.py会调用dist.spawn启动多卡分布式训练。
从源码看,训练流程的核心组织如下:train_sp()中先按--ngpu决定设备并设置随机种子(config.seed,默认 42),用DataTable读取 train/dev 的wave与feats字段,通过Clip批处理函数按batch_max_steps(25500)与hop_size=n_shift裁剪音频并保持与辅助特征(含aux_context_window上下文)对齐;随后实例化PWGGenerator、PWGDiscriminator,损失函数为MultiResolutionSTFTLoss(参数取自stft_loss_params)加nn.MSELoss();生成器与判别器分别使用独立的 Adam 优化器与StepDecay学习率调度器,并挂载ClipGradByGlobalNorm梯度裁剪。训练由Trainer驱动,stop_trigger为train_max_steps次迭代,并注册了evaluator(每eval_interval_steps评估一次)、VisualDL(可视化)、Snapshot(每save_interval_steps保存一次,最多保留num_snapshots个)。
5.1 配置文件 default.yaml 全解
配置文件 conf/default.yaml 是训练的"总开关",文件头部注释提示:该配置针对 CSMSC 数据集调优,迁移到其他数据集时需仔细调整部分参数,并注明在 RTX TITAN 上约需 12 GB 显存、约 3 天训练时长(该信息为仓库配置文件原文说明)。按功能分组解读如下。
特征提取设置(FEATURE EXTRACTION SETTING):
| 参数 | 默认值 | 含义 |
|---|---|---|
fs | 24000 | 采样率(Hz),Opencpop 歌声数据的重采样目标 |
n_fft | 512 | FFT 大小(样本数) |
n_shift | 128 | 帧移(hop size,样本数),约 12.5 ms |
win_length | 512 | 窗长(样本数),约 50 ms;置 null 时与 fft_size 相同 |
window | "hann" | 窗函数类型 |
n_mels | 80 | 梅尔滤波器组数量 |
fmin/fmax | 30 / 12000 | 梅尔滤波的频率范围(Hz) |
这些参数直接决定LogMelFBank提取的特征形态,也决定了后续模型的上采样总比例(upsample_scales乘积必须等于n_shift)。
生成器网络结构(GENERATOR NETWORK ARCHITECTURE SETTING):
| 参数 | 默认值 | 含义 |
|---|---|---|
in_channels/out_channels | 1 / 1 | 输入/输出波形通道数(单声道) |
kernel_size | 3 | 膨胀卷积核大小 |
layers | 30 | 残差块层数 |
stacks | 3 | 堆叠数,即膨胀周期数;每组内残差块膨胀率指数增长 |
residual_channels | 64 | 残差卷积通道数 |
gate_channels | 128 | 门控卷积通道数 |
skip_channels | 64 | 跳跃连接卷积通道数 |
aux_channels | 80 | 辅助特征(梅尔频谱)卷积通道数,必须与 n_mels 相同 |
aux_context_window | 2 | 辅助特征上下文窗口,取 2 时考虑前后各 2 帧 |
dropout | 0.0 | 残差块 dropout 率 |
bias | True | 残差块是否使用偏置 |
use_weight_norm | True | 是否对全部卷积层应用权重归一化 |
use_causal_conv | False | 残差块与上采样层是否使用因果卷积 |
upsample_scales | [8, 4, 2, 2] | 上采样倍数序列,乘积必须等于 hop size(128) |
interpolate_mode | "nearest" | 上采样网络插值方式 |
freq_axis_kernel_size | 1 | 上采样网络在频率轴上的卷积核大小 |
nonlinear_activation/nonlinear_activation_params | null / {} | 上采样网络中的非线性激活函数及参数 |
这些参数与PWGGenerator的构造签名一一对应(见 paddlespeech/t2s/models/parallel_wavegan/parallel_wavegan.py 的类注释)。upsample_scales与aux_context_window的配合在训练数据的Clip批处理中尤为关键:辅助特征需要按上下文窗口扩展后与波形片段严格对齐。
判别器网络结构(DISCRIMINATOR NETWORK ARCHITECTURE SETTING):
| 参数 | 默认值 | 含义 |
|---|---|---|
in_channels/out_channels | 1 / 1 | 输入/输出通道数 |
kernel_size | 3 | 卷积核大小 |
layers | 10 | 卷积层数 |
conv_channels | 64 | 卷积通道数 |
bias | True | 卷积是否使用偏置 |
use_weight_norm | True | 是否使用权重归一化 |
nonlinear_activation | "leakyrelu" | 每层卷积后的非线性激活 |
nonlinear_activation_params.negative_slope | 0.2 | LeakyReLU 的负斜率 α |
STFT 损失设置(STFT LOSS SETTING):fft_sizes: [1024, 2048, 512]、hop_sizes: [120, 240, 50]、win_lengths: [600, 1200, 240]、window: "hann"。这是多分辨率 STFT 损失的三组频谱参数,分别对应不同的时间/频率分辨率,用于约束生成波形与真实波形在多个尺度上的频谱一致性。
对抗损失设置(ADVERSARIAL LOSS SETTING):lambda_adv: 4.0,对抗损失的平衡系数,控制 GAN 损失相对 STFT 损失的权重。
数据加载设置(DATA LOADER SETTING):batch_size: 8、batch_max_steps: 25500(批内每条音频的长度,须能被n_shift整除)、num_workers: 1(DataLoader 工作进程数)。
优化器与调度器设置(OPTIMIZER & SCHEDULER SETTING):
| 参数 | 默认值 | 含义 |
|---|---|---|
generator_optimizer_params.epsilon/weight_decay | 1e-6 / 0.0 | 生成器 Adam 参数 |
generator_scheduler_params | lr=1e-4, step_size=200000, gamma=0.5 | 生成器学习率调度:每 step_size 步 lr 乘 gamma |
generator_grad_norm | 10 | 生成器全局梯度范数裁剪阈值 |
discriminator_optimizer_params | epsilon=1e-6, weight_decay=0.0 | 判别器 Adam 参数 |
discriminator_scheduler_params | lr=5e-5, step_size=200000, gamma=0.5 | 判别器学习率调度 |
discriminator_grad_norm | 1 | 判别器梯度裁剪阈值 |
注意判别器学习率(5e-5)仅为生成器(1e-4)的一半,这是训练 GAN 时常用的不平衡策略。
训练间隔设置(INTERVAL SETTING):
| 参数 | 默认值 | 含义 |
|---|---|---|
discriminator_train_start_steps | 100000 | 开始训练判别器的步数(前 10 万步仅训练生成器,使其先稳定) |
train_max_steps | 400000 | 总训练步数 |
save_interval_steps | 5000 | 保存 checkpoint 的间隔 |
eval_interval_steps | 1000 | 评估间隔 |
其他设置(OTHER SETTING):num_save_intermediate_results: 4(保存中间结果的条数)、num_snapshots: 10(保留的 checkpoint 快照最大数量)、seed: 42(paddle、random、np.random 的随机种子)。训练开始时train.py会把配置文件复制到输出目录(output_dir / config_name),因此exp/default/default.yaml会随实验一起存档,保证可复现性。
六、波形合成:从梅尔频谱到歌声音频
合成命令:
CUDA_VISIBLE_DEVICES=${gpus} ./local/synthesize.sh ${conf_path} ${train_output_path} ${ckpt_name}train.sh 同目录的 synthesize.sh 设置了FLAGS_allocator_strategy=naive_best_fit与FLAGS_fraction_of_gpu_memory_to_use=0.01(低显存占用),然后调用${BIN_DIR}/../synthesize.py,参数为--config、--checkpoint=${train_output_path}/checkpoints/${ckpt_name}、--test-metadata=dump/test/norm/metadata.jsonl、--output-dir=${train_output_path}/test、--generator-type=pwgan。
synthesize.py(源码:paddlespeech/t2s/exps/gan_vocoder/synthesize.py)的完整帮助信息:
usage: synthesize.py [-h] [--generator-type GENERATOR_TYPE] [--config CONFIG] [--checkpoint CHECKPOINT] [--test-metadata TEST_METADATA] [--output-dir OUTPUT_DIR] [--ngpu NGPU] Synthesize with GANVocoder. optional arguments: -h, --help show this help message and exit --generator-type GENERATOR_TYPE type of GANVocoder, should in {pwgan, mb_melgan, style_melgan, } now --config CONFIG GANVocoder config file. --checkpoint CHECKPOINT snapshot to load. --test-metadata TEST_METADATA dev data. --output-dir OUTPUT_DIR output dir. --ngpu NGPU if ngpu == 0, use cpu.参数使用说明:
--config:Parallel WaveGAN 配置文件,必须与训练时使用同一份配置,因为生成器结构由generator_params决定。--checkpoint:从训练输出目录checkpoints/中选择一个 checkpoint 加载。源码中通过paddle.load读取后取state_dict["generator_params"]赋给生成器,并调用remove_weight_norm()后进入eval()模式——这也是预训练模型包中snapshot_iter_100000.pdz即生成器参数的原因。--test-metadata:测试集元数据,即dump/test/norm/metadata.jsonl(README 原文写的是 dev/norm 子目录,示例脚本实际使用dump/test/norm/metadata.jsonl,以仓库实际脚本为准)。--output-dir:合成音频输出目录,每句话保存为{utt_id}.wav。--ngpu:GPU 数量,为 0 时使用 CPU。合成循环中会对每个 utt 打印耗时与 RTF(实时率),并在结束时汇总整体生成速度(Hz)与 RTF,方便评估声码器效率。--generator-type支持pwgan / mb_melgan / style_melgan等(源码中 class_map 还包含hifigan),本示例固定为pwgan。
七、预训练模型、动转静与量化部署
7.1 预训练模型
官方提供面向 Opencpop 训练好的 Parallel WaveGAN 模型,可直接下载:
- pwgan_opencpop_ckpt_1.4.0
解压后包含三个文件:
pwgan_opencpop_ckpt_1.4.0 ├── default.yaml # default config used to train parallel wavegan ├── snapshot_iter_100000.pdz # generator parameters of parallel wavegan └── feats_stats.npy # statistics used to normalize spectrogram when training parallel wavegansnapshot_iter_100000.pdz是 10 万步时保存的生成器参数,default.yaml即训练配置,feats_stats.npy是训练时用于归一化频谱的统计量——三者与训练流程的产物一一对应,下载后即可配合synthesize.py直接合成,无需重新训练。
7.2 动态图转静态图与 PTQ 量化
run.sh的阶段 3 与阶段 4 针对推理部署:
- 阶段 3 动转静(local/dygraph_to_static.sh):调用
${BIN_DIR}/../../dygraph_to_static.py,传入--type=voc、--voc=pwgan_opencpop、--voc_config、--voc_ckpt、--voc_stat=dump/train/feats_stats.npy、--inference_dir=exp/default/inference/,把训练好的动态图模型转换为静态图推理模型,输出到exp/default/inference/。 - 阶段 4 PTQ 量化(local/PTQ_static.sh):调用
${BIN_DIR}/../../PTQ_static.py,使用dump/dev/raw/metadata.jsonl作为校准数据,对inference目录中的静态图模型做后训练量化(PTQ),模型名为pwgan_opencpop,并设置--onnx_format=True同时导出 ONNX 格式,便于在更多推理框架中部署。
这两个阶段与仓库中通用的部署流程一致:先动转静保证模型可脱离训练框架执行,再 PTQ 降低推理显存/内存占用并导出 ONNX,为流式或服务端歌声合成提供轻量化声码器。
八、结语
至此,从 Opencpop 数据下载、dump特征工程、default.yaml超参数体系、train.py训练管线,到synthesize.py波形合成,再到动转静与 PTQ 量化,你已经掌握了 PaddleSpeech 中基于 Opencpop 训练 Parallel WaveGAN 声码器的完整闭环。这套流程与 examples/opencpop/svs1 的歌声合成器示例相互配合,即可搭建端到端的中文歌声合成系统。调参时请牢记两条"硬约束":upsample_scales的乘积必须等于n_shift(128),aux_channels必须等于n_mels(80);其余参数均可结合显存与数据规模按上表调整,并以dev集的评估与合成听感为准。
- 人工智能
- 语音
- 音频
【免费下载链接】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 基于 Opencpop 的 Parallel WaveGAN 歌声合成声码器训练与部署全指南
PaddleSpeech 基于 Opencpop 的 Parallel WaveGAN 歌声合成声码器训练与部署全指南 导读 本文以 PaddleSpeech
人工智能语音音频NLP媒体生成打破单机游戏限制:Nucleus Co-Op如何将任意游戏变成本地多人体验
打破单机游戏限制:Nucleus Co Op如何将任意游戏变成本地多人体验 想象一下,你和朋友们围坐在电脑前,准备一起玩一款经典的单机游戏,却发现游戏本身只支持
人工智能语音音频NLP媒体生成基于 PaddleSpeech 训练 Parallel WaveGAN 声码器:AISHELL-3 多说话人 TTS 实战指南
基于 PaddleSpeech 训练 Parallel WaveGAN 声码器:AISHELL 3 多说话人 TTS 实战指南 导读 本文以 examples/
人工智能语音音频NLP媒体生成
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考