首页
/ 🐸TTS Vocoder 训练实战:从配置 MelGAN / ParallelWaveGAN 到续训与微调的完整流程

🐸TTS Vocoder 训练实战:从配置 MelGAN / ParallelWaveGAN 到续训与微调的完整流程

2026-09-05 11:58:28作者:冯爽妲Honey

本文以 TTS/vocoder/README.md 为主线,系统讲解 🐸TTS 仓库中 Vocoder 模块的训练方法:如何准备数据、编写 config.json、用 train_vocoder.py 启动训练、续训(continue)与微调(restore)的区别,并深入源码剖析 GAN 训练循环中生成器/判别器交替更新、多损失组合与 PQMF 分带处理的实现细节,帮助你在真实语料上独立训练并复现 MelGAN、ParallelWaveGAN 等声码器。

一、Vocoder 模块的定位与模型清单

TTS/vocoder/README.md 开篇即点明:该目录实现了一批声码器(vocoder)模型,它们可以与其他 TTS 模型组合使用——即 TTS 声学模型负责输出 mel 频谱,Vocoder 负责把频谱还原为波形。README 列出的早期实现为:

  • MelGAN
  • MultiBand-MelGAN
  • ParallelWaveGAN
  • GAN-TTS(当时仅实现了 Discriminator 部分)

从当前仓库的实际结构看,模型清单已经明显扩大。TTS/vocoder/configs/ 目录下提供了 8 套独立配置(melgan_config.pymultiband_melgan_config.pyparallel_wavegan_config.pyhifigan_config.pyunivnet_config.pywavernn_config.pywavegrad_config.pyfullband_melgan_config.py),TTS/vocoder/models/ 目录下则对应实现了各模型的 generator 与 discriminator 类,例如 melgan_generator.pyhifigan_discriminator.pyunivnet_generator.py 等。README 还特别强调该框架“灵活且模块化(but not too modular)”——这一点在模型加载机制上有直接体现(见第五节 setup_model)。

二、训练数据准备:把 wav 文件收进一个目录即可

README 给出的第一步非常直接:把所有 wav 文件收拢到一个文件夹,然后把该文件夹路径填入 config.jsondata_path。这一步在源码中的对应实现是 TTS/vocoder/datasets/preprocess.py

def find_wav_files(data_path, file_ext="wav"):
    wav_paths = glob.glob(os.path.join(data_path, "**", f"*.{file_ext}"), recursive=True)
    return wav_paths

也就是说,data_path 下的 wav 文件会被递归查找,不需要扁平结构。训练/验证集切分同样在这里完成:

def load_wav_data(data_path, eval_split_size, file_ext="wav"):
    wav_paths = find_wav_files(data_path, file_ext=file_ext)
    assert len(wav_paths) > 0, f" [!] {data_path} is empty."
    np.random.seed(0)
    np.random.shuffle(wav_paths)
    return wav_paths[:eval_split_size], wav_paths[eval_split_size:]

两点值得注意:

  1. 切分使用固定随机种子 0(np.random.seed(0)),因此同一数据集每次启动训练时的 train/eval 划分是一致的,便于对比实验;
  2. eval_split_size 指定用于评估的样本数(默认 10,定义于 shared_configs.pyBaseVocoderConfig),其余全部参与训练。

如果不想在线计算 mel 特征,还可以走预计算特征路径:训练入口 TTS/bin/train_vocoder.py 中,当 config 存在非空的 feature_path 时会调用 load_wav_feat_data(config.data_path, config.feature_path, config.eval_split_size),该函数会按文件名(stem)把 wav 与 .npy 特征文件一一配对,并断言二者数量与命名一致。这一分支主要服务于需要量化波形特征的模型(如 WaveRNN,见 preprocess.py 中的 preprocess_wav_files)。

三、配置文件体系:三个层次继承下来的参数表

Vocoder 配置采用 dataclass + coqpit 的层次化设计,全部继承链为:

BaseTrainingConfig (TTS.config)
  └── BaseVocoderConfig            # 所有声码器共享
        └── BaseGANVocoderConfig   # GAN 类声码器共享
              ├── MelganConfig / ParallelWaveganConfig / HifiganConfig / ...

3.1 BaseVocoderConfig:数据加载与基础训练参数

定义于 TTS/vocoder/configs/shared_configs.py,核心字段及默认值如下:

参数 类型/默认值 说明
audio BaseAudioConfig 音频处理器配置(采样率、mel 参数等),训练时据此构建 AudioProcessor
data_path "" 训练数据根目录,递归查找全部 wav
feature_path None 预计算特征目录;留空则在线计算特征
seq_len 1000 训练时截取的声音片段长度(各模型会覆盖,如 MelGAN 为 8192)
pad_short 0 对短于 seq_len 的波形的额外 padding
conv_pad 0 针对频谱边缘卷积的额外 padding
use_noise_augment False 是否对输入添加随机噪声增强
use_cache False 是否把计算好的特征缓存在内存中,RAM 不足可能 OOM
eval_split_size 10 评估样本数
epochs 10000 训练总轮数
optimizer "AdamW" 优化器名称
optimizer_params {"betas": [0.8, 0.99], "weight_decay": 0.0} 优化器超参,注意默认 betas 是 (0.8, 0.99) 而非 (0.9, 0.999)

3.2 BaseGANVocoderConfig:GAN 训练与损失组合的“开关面板”

GAN 类声码器的训练完全由一组开关 + 权重控制。每个 use_* 布尔位决定是否启用某项损失,对应的 *_loss_weight 负责加权求和:

开关 默认 对应权重(默认) 损失来源
use_stft_loss True stft_loss_weight = 0 ParallelWaveGAN 提出的多分辨率 STFT 损失
use_subband_stft_loss True subband_stft_loss_weight = 0 MultiBand-MelGAN 的分带 STFT 损失
use_mse_gan_loss True mse_G_loss_weight = 1 MSE 型 GAN 损失
use_hinge_gan_loss True hinge_G_loss_weight = 0 Hinge GAN 损失(与 MSE 二选一)
use_feat_match_loss True feat_match_loss_weight = 100 MelGAN 的特征匹配损失(依赖能输出中间特征的判别器)
use_l1_spec_loss True l1_spec_loss_weight = 45 HiFi-GAN 的 L1 频谱(mel)损失

STFT 损失的多分辨率参数默认为 {"n_ffts": [1024, 2048, 512], "hop_lengths": [120, 240, 50], "win_lengths": [600, 1200, 240]};L1 频谱损失默认在 mel 域计算(n_mels: 80, hop_length: 256, n_fft: 1024,采样率 22050)。

除损失外,BaseGANVocoderConfig 还定义了 GAN 训练特有的优化器与调度器参数:lr_gen = 0.0002lr_disc = 0.0002,各自的 ExponentialLR 学习率调度器(gamma = 0.999scheduler_after_epoch = True),梯度裁剪 grad_clip = [5, 5](对两个优化器各设阈值),以及两个训练策略开关:

  • steps_to_start_discriminator(默认 0):前若干步只训生成器、推迟判别器启动;
  • diff_samples_for_G_and_D(默认 False):让判别器使用与生成器不同的样本对,迭代变慢但某些情况下收敛更好;
  • use_pqmf(默认 False):启用 PQMF 进行多分带训练(MultiBand-MelGAN 使用)。

3.3 以 MelganConfig 为例的完整配置

TTS/vocoder/configs/melgan_config.py 为例,它在上层开关基础上的默认值给出了一个可直接复用的训练起点:

@dataclass
class MelganConfig(BaseGANVocoderConfig):
    model: str = "melgan"
    discriminator_model: str = "melgan_multiscale_discriminator"
    discriminator_model_params: dict = field(
        default_factory=lambda: {"base_channels": 16, "max_channels": 1024, "downsample_factors": [4, 4, 4, 4]}
    )
    generator_model: str = "melgan_generator"
    generator_model_params: dict = field(
        default_factory=lambda: {"upsample_factors": [8, 8, 2, 2], "num_res_blocks": 3}
    )
    batch_size: int = 16
    seq_len: int = 8192
    pad_short: int = 2000
    use_noise_augment: bool = True
    use_cache: bool = True
    # 损失组合:STFT + MSE-GAN + 特征匹配;关闭 hinge 与 subband
    use_stft_loss: bool = True
    use_subband_stft_loss: bool = False
    use_mse_gan_loss: bool = True
    use_hinge_gan_loss: bool = False
    use_feat_match_loss: bool = True
    stft_loss_weight: float = 0.5
    mse_G_loss_weight: float = 2.5
    feat_match_loss_weight: float = 108

可以看到 MelGAN 的默认组合是「STFT 损失(0.5) + MSE-GAN(2.5) + 特征匹配(108)」,并开启了噪声增强与特征缓存。ParallelWaveganConfig 则默认使用 parallel_wavegan_discriminatorparallel_wavegan_generatorupsample_factors [4,4,4,4]stacks 3num_res_blocks 30 等,见 parallel_wavegan_config.py 的文档串)。各配置的字段注释本身就是一份参数手册,建议训练前通读对应 dataclass。

如果你想要现成的完整 config.json 起点,除了 TTS/vocoder/configs/ 外,recipes/ljspeech/ 下为每个模型都提供了配方脚本(如 hifigan/train_hifigan.pymultiband_melgan/train_multiband_melgan.py),可以直接参考其中的参数组合。

四、训练、续训与微调:三条命令的语义差异

README 给出的核心操作如下(仓库中该入口脚本实际位于 TTS/bin/train_vocoder.py):

1. 新起一次训练——先准备 config.json,然后:

CUDA_VISIBLE_DEVICES='0' python TTS/bin/train_vocoder.py --config_path path/to/config.json

2. 从上次训练中断处继续(continue):

CUDA_VISIBLE_DEVICES='0' python TTS/bin/train_vocoder.py --continue_path path/to/your/model/folder

3. 用预训练权重微调(restore):

CUDA_VISIBLE_DEVICES='0' python TTS/bin/train_vocoder.py --restore_path path/to/your/model.pth

README 对后两条命令的差异有一句关键说明,值得逐字理解:

Restoring a model starts a new training in a different folder. It only restores model weights with the given checkpoint file. However, continuing a training starts from the same directory where the previous training run left off.

即:restore 只恢复模型权重、在新目录开一次全新训练(优化器状态、步数计数等不继承);continue 则原地继续,从上次留下的目录接着跑。这一行为在源码中得到印证:TTS/bin/train_vocoder.py--config_pathload_config(args.config_path)--continue_path 则读取 <continue_path>/config.json——后者依赖训练器在实验目录下回写的配置,这正是“原地继续”的实现基础。

启动入口 main() 的完整流程为:

  1. 解析命令行参数(TrainVocoderArgs,允许用额外的 --xxx 覆盖 config 中的字段,见 parser.parse_known_argsconfig.parse_known_args(config_overrides, relaxed_parser=True));
  2. feature_path 是否存在选择 load_wav_feat_dataload_wav_data 载入样本;
  3. AudioProcessor(**config.audio) 构建音频处理器;
  4. 通过 setup_model(config) 依据配置实例化模型;
  5. 交给通用 Trainer 并执行 trainer.fit(),同时把 audio_processor 作为 training_assets 传入(供训练日志画图、合成试听音频)。

README 最后还提示:训练过程与 TTS 模型一样,可以通过 Tensorboard 跟踪——日志由 Trainer 的 logger 统一写出,GAN.train_log / GAN.eval_log 会在每个评估周期调用 plot_resultsTTS/vocoder/utils/generic_utils.py)绘制预测波形/频谱对比图,并保存一条试听音频(见 gan.py_log 方法)。

五、框架纵深:模型如何被动态装配,GAN 训练循环如何运转

5.1 “灵活且模块化”的模型装载机制

README 提到适配新声码器很容易,这对应 TTS/vocoder/models/init.py 中基于配置名的动态导入:

def setup_model(config: Coqpit):
    if "discriminator_model" in config and "generator_model" in config:
        MyModel = importlib.import_module("TTS.vocoder.models.gan")
        MyModel = getattr(MyModel, "GAN")
    else:
        MyModel = importlib.import_module("TTS.vocoder.models." + config.model.lower())
        ...
    return MyModel.init_from_config(config)

也就是说:只要配置里同时声明了 discriminator_modelgenerator_model,就一律走统一的 GAN 包装类,其余单模型(WaveRNN、Wavegrad 等)则按 config.model 字符串映射到 models/ 下的同名模块。setup_generator / setup_discriminator 再按 generator_model / discriminator_model 的字符串名实例化具体网络,并把 generator_model_params / discriminator_model_params 展开为构造参数——这正是“mix and match”的落点:你可以用 HifiganConfig 的生成器换配 MelGAN 系判别器,而不用改任何训练代码。

所有声码器模型继承 TTS/vocoder/models/base_vocoder.py 中的 BaseVocoder,其约定:

  • MODEL_TYPE = "vocoder",标识模型类别;
  • 输入/输出张量形状规范:batch x time x channels(3D)、batch x channels(2D)、batch x 1(1D);
  • _set_model_args 会区分 *Config(训练用,参数嵌在 config.model_args 中)与 *Args(纯推理配置)两种 config 形态。

5.2 GAN 训练循环:一次 train_step 里发生了什么

GAN 类声码器的核心是 TTS/vocoder/models/gan.py 中的 GAN 类。它把 generator(model_g)与 discriminator(model_d)包在一个 Lightning 兼容的模型里,通过 optimizer_idx 区分当前是判别器还是生成器优化步:

  • optimizer_idx == 0(判别器步):先用生成器前向得到 y_hat 并缓存(self.y_hat_g);若 diff_samples_for_G_and_D 开启,则用 batch 中额外提供的 input_disc / waveform_disc 样本重新跑一次生成器(no_grad);随后用真/假样本对调用判别器,取 (scores_fake, scores_real) 计算判别器损失。判别器是否带条件输入通过反射检查 forward 参数个数(2 个参数即条件判别器,如 UnivNet)自动适配。
  • optimizer_idx == 1(生成器步):复用缓存的 y_hat_g 过判别器得到 scores_fake(及特征 feats_fake),若启用特征匹配损失则以 no_grad 过一遍真样本得到 feats_real,最后统一交给 GeneratorLoss 按配置中的开关组合出总损失。
  • PQMF 多分带处理:当生成器输出通道数 > 1(如 MultiBand-MelGAN 输出 4 个带),代码自动调用 model_g.pqmf_synthesis(y_hat) 合成回单声道波形再喂给判别器,并对真波形做 pqmf_analysis 得到分带目标——这就是配置里 use_pqmf 选项背后的机制,分带相关层实现在 TTS/vocoder/layers/pqmf.py
  • 延迟启动判别器on_train_step_startself.train_disc = trainer.total_steps_done >= self.config.steps_to_start_discriminator,在训练早期只训生成器,实现“热身”策略。
  • 优化器顺序get_optimizer 返回 [optimizer2(disc), optimizer1(gen)],与 train_stepoptimizer_idx 的语义(0=判别器,1=生成器)严格对齐;调度器通过 lr_scheduler_gen / lr_scheduler_disc 分别构建。
  • 损失组合get_criterion 返回 [DiscriminatorLoss(config), GeneratorLoss(config)],二者均实现在 TTS/vocoder/layers/losses.py,按第三节表格中的开关与权重把 STFT / Subband-STFT / MSE-GAN / Hinge-GAN / 特征匹配 / L1 频谱损失加权求和。

数据侧,GAN.get_data_loader 构建 GANDataset,透传 seq_lenpad_shortconv_paduse_noise_augmentuse_cache 等配置;当 diff_samples_for_G_and_D 开启时,return_pairs=True 让数据集每次返回两对样本(G 用与 D 用各一份),format_batch 则把 (x_G, y_G, x_D, y_D) 整理成 {"input", "waveform", "input_disc", "waveform_disc"}train_step 消费。

六、验证与测试:如何确认你的训练在正常工作

仓库为声码器模块准备了成体系的测试,位于 tests/vocoder_tests/,例如:

排查训练问题时,可以对照这些测试确认:配置能否被 setup_model 正确装配(模型/判别器名字拼写错误会在此阶段报 ValueError: Model xxx not exist!)、损失开关组合是否与 test_vocoder_losses.py 中的场景一致、评估样本数是否符合 eval_split_size 预期。

七、小结与致谢

回到 TTS/vocoder/README.md 的原始主张,可以把它浓缩为三条可操作的原则:

  1. 数据:wav 收进一个目录 → data_path;需要预计算特征时用 feature_path 配对 wav 与 .npy
  2. 配置:继承 BaseGANVocoderConfig 的 dataclass(或对应的 config.json)决定一切——网络结构(*_model + *_model_params)、数据行为(seq_len / pad_short / use_cache)、损失组合(use_* + 权重)、优化与调度(lr_gen / lr_disc / ExponentialLR / grad_clip);
  3. 训练--config_path 新起、--continue_path 原地续训、--restore_path 换目录只带权重微调,全程 Tensorboard 可观测。

最后按 README 原样保留致谢:本模块的 GAN 声码器工作以 kan-bayashi 的 ParallelWaveGAN 开源实现为起点,仓库在其基础上统一了配置、数据与训练接口。

登录后查看全文
热门项目推荐
相关项目推荐