微调指南¶
本指南介绍如何使用两种方式微调 VoxCPM:LoRA(参数高效)与全量微调。二者使用相同的训练脚本与数据格式。
环境准备¶
软件要求¶
依赖 |
版本 |
|---|---|
Python |
训练建议使用 3.10–3.11 |
PyTorch |
2.5.0+ |
CUDA |
12.0+ |
safetensors |
推荐(若不可用则回退到 |
训练脚本还会用到以下 Python 包:tensorboardX、argbind、transformers (余弦调度器)、librosa (验证用 mel 频谱)。
硬件要求¶
配置 |
LoRA |
Full Fine-Tuning |
|---|---|---|
VoxCPM 1.5 (750M) |
约 12 GB 显存 |
约 24 GB 显存 |
VoxCPM 2 (2B) |
约 20 GB 显存 |
约 40 GB 显存 |
以上为在 batch_size=16、max_batch_tokens=8192 下的粗略估算;实际占用取决于音频长度与梯度累积步数。若出现 OOM,请参阅 微调常见问题。
多卡训练可通过 torchrun 进行:
CUDA_VISIBLE_DEVICES=0,1,2,3 torchrun --nproc_per_node=4 \
scripts/train_voxcpm_finetune.py --config_path your_config.yaml
数据准备¶
数据格式¶
训练数据为 JSONL 清单文件,每行一个样本:
{"audio": "path/to/audio1.wav", "text": "Transcript of audio 1."}
{"audio": "path/to/audio2.wav", "text": "Transcript of audio 2.", "ref_audio": "path/to/audio1.wav"}
{"audio": "path/to/audio3.wav", "text": "Optional fields.", "duration": 3.5, "dataset_id": 1}
字段 |
必填 |
说明 |
|---|---|---|
|
是 |
音频文件路径(建议 WAV) |
|
是 |
与音频内容一致的转写文本 |
|
否 |
Path to a reference audio clip from the same speaker. It is used as speaker-conditioning context for voice cloning, so it does not need to be an unseen sample. In practice, |
|
否 |
时长(秒);可加速按长度过滤 |
|
否 |
多数据集混合用的整数 ID(默认:0) |
仓库中的 examples/train_data_example.jsonl 可供参考。
小技巧
Mixing ref_audio and non-ref_audio samples — We recommend that 30–50% of your training samples include ref_audio, so the model retains both zero-shot and reference-based voice cloning abilities. A simple strategy is to randomly choose another clean recording from the same speaker as ref_audio for each target sample.
音频要求¶
格式: 建议使用 WAV;torchaudio 支持的其它格式也可用。
采样率: 数据加载器会自动重采样到目标模型的采样率,一般无需预先重采样。训练配置中的
sample_rate必须匹配 AudioVAE 编码器的输入采样率:VoxCPM 1.0:16 kHz
VoxCPM 1.5:44.1 kHz
VoxCPM 2:16 kHz(编码器以 16 kHz 运行;解码器输出 48 kHz)
时长: 每条片段 3–30 秒较为稳妥。过短(< 1 s)容易不稳定;过长会增加显存占用,并可能被
max_batch_tokens过滤。
预处理要点¶
去掉尾部静音,控制在 0.5 秒以内。尾静音过长是微调后「生成停不下来」最常见原因之一。
若录音电平不一致,请做音量归一化。
转写要干净: 文本须与音频逐字一致;不匹配会同时损害克隆质量与文本贴合度。
剔除噪声样本。 模型对训练数据中的背景噪声较敏感。
选择哪种微调方式¶
数据规模与目标决定采用哪种微调方式:
目标 |
数据量 |
推荐做法 |
|---|---|---|
克隆单个说话人 |
5–50 条片段 |
LoRA Fine-Tuning — 快、显存占用低 |
适配领域或风格 |
50–500 条片段 |
LoRA Fine-Tuning — 使用更高 rank( |
新增语言 |
500+ 小时 |
Full Fine-Tuning — 混入部分中英数据以减轻遗忘 |
大规模定制 |
1000+ 条片段 |
LoRA 与全量微调一览:
在内部单说话人克隆基准上,LoRA(r=32)的说话人相似度约为全量微调的 98%,显存约减半,checkpoint 体积也小几个数量级。多数任务建议从 LoRA 起步;不同数据与目标下结果会有差异。
LoRA Fine-Tuning¶
LoRA 在冻结基座的前提下,仅训练少量附加参数(通常 < 模型参数的 1%)。多数微调任务建议从此入手。
Training¶
配置
请创建 YAML 配置文件。以下为 VoxCPM 2 的示例:
pretrained_path: /path/to/VoxCPM2/
train_manifest: /path/to/train.jsonl
val_manifest: /path/to/val.jsonl # optional, leave empty to skip validation
sample_rate: 16000 # AudioVAE encoder input rate (NOT the 48kHz output rate)
out_sample_rate: 48000 # AudioVAE decoder output rate; only used at inference, not during training
batch_size: 16
grad_accum_steps: 1
num_workers: 2
num_iters: 1000
log_interval: 10
valid_interval: 500
save_interval: 500
learning_rate: 0.0001
weight_decay: 0.01
warmup_steps: 100
max_steps: 1000
max_batch_tokens: 8192
save_path: /path/to/checkpoints/lora
tensorboard: /path/to/logs/lora
lambdas:
loss/diff: 1.0
loss/stop: 1.0
lora:
enable_lm: true
enable_dit: true
enable_proj: false
r: 32
alpha: 32
dropout: 0.0
小技巧
若使用 VoxCPM 1.5,请将 sample_rate 改为 44100,并将 pretrained_path 指向你的 1.5 checkpoint。sample_rate 必须始终匹配 config.json 中 AudioVAE 编码器的输入采样率 — 而非输出采样率。训练脚本会依据 config.json 自动识别模型结构。
LoRA 参数说明
参数 |
说明 |
建议值 |
|---|---|---|
|
对语言模型(基座 LM + 残差 LM)应用 LoRA |
|
|
对扩散 Transformer(DiT)应用 LoRA |
|
|
对 LM 与 DiT 之间的投影层应用 LoRA |
多数场景用 |
|
LoRA 秩(rank)— 越大容量越高 |
克隆说话人用 32;风格/语言适配用 64 |
|
缩放因子( |
通常取 |
|
LoRA 层上的 Dropout |
除非过拟合,否则 |
启动
# Single GPU
python scripts/train_voxcpm_finetune.py --config_path conf/your_lora_config.yaml
# Multi-GPU
CUDA_VISIBLE_DEVICES=0,1,2,3 torchrun --nproc_per_node=4 \
scripts/train_voxcpm_finetune.py --config_path conf/your_lora_config.yaml
LoRA WebUI
VoxCPM 还提供基于 Gradio 的界面,将 LoRA 训练与推理集成在同一处:
python lora_ft_webui.py
训练观察¶
训练日志写入 TensorBoard。可用如下命令启动查看:
tensorboard --logdir /path/to/logs/lora
关注哪些指标
指标 |
含义 |
|---|---|
|
扩散损失 — 应持续下降后趋于平稳 |
|
停止预测损失 — 应较早稳定并保持较低 |
|
梯度范数 — 尖峰可能表示坏样本或学习率过高 |
|
学习率曲线 — 带 warm-up 的余弦衰减,可用于核对调度是否符合预期 |
若提供验证清单,脚本还会记录 val/loss,并在每个 valid_interval 在 TensorBoard 中生成样本音频与 mel 频谱。
何时停止
可把 epoch 数当作粗参考。 单说话人克隆通常 1–3 个 epoch 足够;再往后往往弊大于利 — TTS 微调的过拟合可能很早出现。
loss/diff进入平台期,不再有实质下降。TensorBoard 中的生成音频在目标音色/风格上听起来已经满意。
若模型开始忽略输入文本(无论输入什么都生成相似音频),即已过拟合 — 请回退到较早的 checkpoint。
小技巧
验证损失与主观听感未必完全一致。建议在收敛区间附近多存几个 checkpoint,用实际推理试听后再选定最佳。
Checkpoint 目录结构
checkpoints/lora/
├── step_0000500/
│ ├── lora_weights.safetensors
│ ├── lora_config.json
│ ├── optimizer.pth
│ ├── scheduler.pth
│ └── training_state.json
├── step_0001000/
│ └── ...
└── latest -> step_0001000/
若存在 latest/,训练会自动从中恢复;信号处理也会在 SIGTERM / SIGINT 时保存 checkpoint,避免中断丢进度。
推理¶
命令行
python scripts/test_voxcpm_lora_infer.py \
--lora_ckpt /path/to/checkpoints/lora/step_0002000 \
--text "Hello from the fine-tuned model." \
--output output.wav
Python API
from voxcpm import VoxCPM
model = VoxCPM.from_pretrained(
"openbmb/VoxCPM2",
lora_weights_path="/path/to/checkpoints/lora/latest",
)
wav = model.generate(text="Hello from the fine-tuned model.")
运行时热切换 LoRA
无需重启模型即可加载、卸载或切换 LoRA 权重:
# Load a LoRA
model.load_lora("/path/to/lora_a")
# Disable LoRA temporarily (base model only)
model.set_lora_enabled(False)
# Re-enable
model.set_lora_enabled(True)
# Switch to a different LoRA
model.unload_lora()
model.load_lora("/path/to/lora_b")
所有热切换操作均与 torch.compile 兼容。
Full Fine-Tuning¶
全量微调会更新全部参数。当 LoRA 容量不足时使用 — 常见于新语言或 500+ 条片段的大规模定制。
Training¶
配置
pretrained_path: /path/to/VoxCPM2/
train_manifest: /path/to/train.jsonl
val_manifest: /path/to/val.jsonl
sample_rate: 16000 # AudioVAE encoder input rate (NOT the 48kHz output rate)
out_sample_rate: 48000 # AudioVAE decoder output rate; only used at inference, not during training
batch_size: 16
grad_accum_steps: 1
num_workers: 2
num_iters: 1000
log_interval: 10
valid_interval: 500
save_interval: 500
learning_rate: 0.00001 # 10x smaller than LoRA
weight_decay: 0.01
warmup_steps: 100
max_steps: 1000
max_batch_tokens: 8192
save_path: /path/to/checkpoints/full
tensorboard: /path/to/logs/full
lambdas:
loss/diff: 1.0
loss/stop: 1.0
注意配置中不含 lora 键 — 脚本据此执行全量微调。
与 LoRA 的主要区别
learning_rate建议约为 LoRA 的 1/10(1e-5对1e-4),以避免灾难性遗忘。因全部参数都参与求导,显存占用明显更高。
checkpoint 更大(完整权重对比仅 LoRA 增量)。
启动
# Single GPU
python scripts/train_voxcpm_finetune.py --config_path conf/your_full_config.yaml
# Multi-GPU
CUDA_VISIBLE_DEVICES=0,1,2,3 torchrun --nproc_per_node=4 \
scripts/train_voxcpm_finetune.py --config_path conf/your_full_config.yaml
训练观察¶
TensorBoard 指标与 LoRA 相同(loss/diff、`` loss/stop``、`` grad_norm``、`` lr`` 及验证音频)。
全量微调比 LoRA 更易过拟合。实践中常在 1–2 个 epoch 内达到较优;继续训练可能反而变差。需格外留意:
验证损失与训练损失背离 — 过拟合信号。应停止训练,并采用背离前最后一个 checkpoint。
文本被忽略 — 最常见的过拟合表现。请保持
training_cfg_rate=0.1(不要设为 0)与 `` weight_decay=0.01``,并在每个 `` save_interval`` 关注 checkpoint。小数据集更快过拟合。 样本较少时,最优 checkpoint 可能出现在几百步内。
新语言微调: 混入部分中英数据(例如 10–20%),以减轻对原有能力的遗忘。
更多数据未必更好。 超过某一点后边际收益递减;更应重视数据质量与多样性。
Checkpoint 目录结构
checkpoints/full/
├── step_0000500/
│ ├── model.safetensors
│ ├── config.json
│ ├── audiovae.pth
│ ├── tokenizer.json
│ ├── tokenizer_config.json
│ ├── special_tokens_map.json
│ ├── optimizer.pth
│ ├── scheduler.pth
│ └── training_state.json
└── latest -> step_0000500/
每个 checkpoint 都是可直接加载的完整模型目录。
推理¶
命令行
python scripts/test_voxcpm_ft_infer.py \
--ckpt_dir /path/to/checkpoints/full/step_0002000 \
--text "Hello from the fine-tuned model." \
--output output.wav
# With voice cloning
python scripts/test_voxcpm_ft_infer.py \
--ckpt_dir /path/to/checkpoints/full/latest \
--text "Cloned voice with full fine-tuning." \
--prompt_audio reference.wav \
--prompt_text "Exact transcript of reference.wav" \
--output cloned.wav
Python API
该目录即完整模型 — 可直接加载:
from voxcpm import VoxCPM
model = VoxCPM.from_pretrained("/path/to/checkpoints/full/latest")
wav = model.generate(text="Hello from the fine-tuned model.")
常见训练问题(OOM、生成停不下来、LoRA 效果差、checkpoint 报错等)请参阅 微调常见问题。