news 2026/9/25 3:21:15

PaddleSpeech 声纹识别实战:VoxCeleb 数据集准备与 ECAPA-TDNN 训练评测指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PaddleSpeech 声纹识别实战:VoxCeleb 数据集准备与 ECAPA-TDNN 训练评测指南
  • 人工智能
  • 语音
  • 音频

【免费下载链接】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.

项目地址:https://gitcode.com/gh_mirrors/pa/PaddleSpeech
点击查看免费下载

导读

本文以 PaddleSpeech 仓库中examples/voxceleb/示例为主线,系统讲解如何在 VoxCeleb1/VoxCeleb2 大规模说话人数据集上完成声纹识别(Speaker Verification / Speaker Identification)任务的完整链路:从 m4a 音频格式转换、manifest 与 CSV 数据整理,到 ECAPA-TDNN 声纹骨干网络的训练、余弦相似度打分与 EER 评测,以及预训练模型的使用。读完本文,你将掌握 VoxCeleb 数据集的标准化准备流程、run.sh分段执行机制、ecapa_tdnn.yaml全量配置参数含义,并能独立复现一个可用于说话人验证的 ECAPA-TDNN 系统。

一、VoxCeleb 示例总览:sv0 与 sv1 两条技术路线

PaddleSpeech 的examples/voxceleb/目录围绕 VoxCeleb 数据集提供声纹识别参考实现,并拆分为两个子示例:

  • sv0(纯 Python 实现):采用 softmax 分类后端(配合 Additive Angular Margin 损失)进行说话人识别训练,验证阶段使用余弦相似度打分。全部流程均为 Python 代码,不依赖 Kaldi,易于安装复现,详细说明见 sv0/README.md。
  • sv1(依赖 Kaldi):说话人验证后端基于 PLDA / score normalization(sc)实现,训练与打分流程依赖 Kaldi 工具链,适用于追求更强打分策略的场景。

从仓库源码看,sv0 是当前维护最完整的路线:它包含完整的数据处理脚本、训练/测试脚本、两套 YAML 配置和结果记录(RESULT.md)。本文后续内容以 sv0 为核心展开。

二、VoxCeleb 数据集概览

VoxCeleb 系列是声纹识别领域广泛使用的真实场景说话人数据集,语音采集自 YouTube 视频访谈等自然环境,包含大量背景噪声、笑声、重叠说话、不同信道与口音,非常考验声纹模型的泛化能力。examples/voxceleb/README.md给出了四个数据划分的规模统计:

数据集Vox1 - devVox1 - testVox2 - devVox2 - test
说话人数(spks)1211405994118
语音条数(utts)1486424874109200936273
时长(time, h)340.411.22360.279.9

可以看到,VoxCeleb2 的规模约为 VoxCeleb1 的 7 倍,dev 集合计覆盖 7205 个说话人(1211 + 5994),这正是 ecapa_tdnn.yaml 中num_speakers: 7205的由来——用 Vox1+Vox2 联合训练时分类头的类别数就是 7205。

三、VoxCeleb2 数据准备:m4a 转 wav

VoxCeleb2 的音频文件以 m4a 格式发布,而 PaddleSpeech 的音频前端统一按 wav 处理,因此在使用前必须将全部 m4a 文件转换为 16kHz 单声道 wav。examples/voxceleb/README.md给出了推荐的转换命令:

ffmpeg -y -i %s -ac 1 -vn -acodec pcm_s16le -ar 16000 %s

参数含义:-ac 1强制单声道,-vn丢弃视频流,-acodec pcm_s16le指定 16bit PCM 编码,-ar 16000统一重采样到 16kHz。这一步耗时数小时,且只需执行一次。

仓库内 local/convert.sh 提供了一个 32 路并行的批量转换实现(信号量并发控制),实际执行的 ffmpeg 命令为:

ffmpeg -loglevel panic -i "$f" -ar 16000 "${f%.*}.wav"

转换完成后,将所有 wav 文件放入名为wav的目录,目录结构应符合如下约定(data.sh与voxceleb2.py的 manifest 生成逻辑依赖该结构):

voxceleb2/wav/id*/<视频ID>/*.wav # 例如 voxceleb2/wav/id00012/21Uxsk56VDQ/00001.wav

注意:convert.sh只做-ar 16000重采样,而 README 给出的通用命令还包含单声道与 PCM 编码参数,两者配合使用可保证 wav 与后续 fbank 特征提取(sr: 16000)完全对齐。

四、评测协议(trial)概览

说话人验证评测需要预定义的 trial 文件:每一行是一个"说话人对 + 标签"(1 表示同一说话人,0 表示不同说话人),模型对所有 trial 打分后计算等错误率(EER)。examples/voxceleb/README.md总结了 VoxCeleb 官方与清理版(cleaned)评测协议:

Trial文件名数量正样本负样本
VoxCeleb1veri_test.txt377201886018860
VoxCeleb1 (cleaned)veri_test2.txt376111880218809
VoxCeleb1-Hlist_test_hard.txt552536276270276266
VoxCeleb1-H (cleaned)list_test_hard2.txt550894275488275406
VoxCeleb1-Elist_test_all.txt581480290743290737
VoxCeleb1-E (cleaned)list_test_all2.txt579818289921289897

其中 VoxCeleb1-E 与 VoxCeleb1-H 分别是扩展与困难评测协议(官方数据划分),清理版剔除了与训练集说话人重叠的样本。sv0 的配置默认使用verification_file: data/vox1/veri_test2.txt,即 VoxCeleb1 cleaned 协议;这些 trial 文件会在数据处理阶段由 voxceleb1.py 自动下载并写入data/vox1/目录。

五、ECAPA-TDNN 示例(sv0)概览

sv0 的核心入口是 run.sh,它通过stage与stop_stage控制流水线执行范围,共分为三个阶段:

Stage功能
0数据处理:下载 VoxCeleb1、下载 VoxCeleb2、m4a 转 wav、生成 train/dev/test manifest、下载 RIR Noise 并生成增强用噪声 manifest
1训练声纹识别模型(说话人分类任务)
2使用余弦相似度对 VoxCeleb trial 打分并评测

只运行 stage 1 和 stage 2:

bash run.sh --stage 1 --stop_stage 2

只运行单个 stage(例如仅处理数据):

bash run.sh --stage 0 --stop_stage 0

从 run.sh 源码可以看到,该脚本同时支持通过--gpus、--dir、--exp_dir、--conf_path等命令行参数覆盖默认局部变量,例如指定 GPU:

bash run.sh --gpus 0,1

若将gpus置空(gpus=),则完全使用 CPU 执行。

六、环境准备:path.sh 与 parse_options.sh

任何脚本运行前都需要先加载 path.sh 设置环境变量:

source path.sh

其关键作用是:将MAIN_ROOT指向 PaddleSpeech 仓库根目录(realpath ${PWD}/../../../),把MAIN_ROOT与MAIN_ROOT/utils加入PATH,并设置PYTHONPATH,从而可以直接调用仓库内的train.py/test.py等模块。此外BIN_DIR被设置为${MAIN_ROOT}/paddlespeech/vector/exps/ecapa_tdnn,即声纹模型训练脚本所在目录。

run.sh内还会 source 仓库通用的参数解析脚本:

source ${MAIN_ROOT}/utils/parse_options.sh

它实现了--variable value风格的命令行参数解析,这是整个 PaddleSpeech 示例体系统一采用的脚本参数约定。

局部变量说明

变量含义默认值
gpus使用的 GPU 编号,置空表示仅用 CPU0,1,2,3
stage起始阶段编号0
stop_stage结束阶段编号50
dir数据信息(manifest/csv/meta)存放目录data/
exp_dir实验输出目录(checkpoint 等)exp/ecapa-tdnn-vox12-big/
conf_path模型配置文件路径conf/ecapa_tdnn.yaml

七、Stage 0:数据处理详解

数据处理由 local/data.sh 完成,内部又细分为 8 个子阶段(stage 1–8),每个子阶段对应独立的 Python 脚本调用:

子阶段动作调用脚本
1下载 VoxCeleb1 并生成manifest.dev/manifest.test及 meta、trial 文件voxceleb1.py
2下载 VoxCeleb2(m4a 压缩包)voxceleb2.py
3将 VoxCeleb2 的 m4a 批量转为 wavconvert.sh
4扫描 wav 目录生成manifest.vox2voxceleb2.py
5将 manifest(json 格式)转为训练所需 CSV,并切分 train/dev/enroll/testmake_vox_csv_dataset_from_json.py
6下载 RIR Noise 数据集并生成 manifestrir_noise.py
7生成噪声增强用 CSVmake_rirs_noise_csv_dataset_from_json.py

两个下载脚本均以${MAIN_ROOT}/dataset为TARGET_DIR,即原始音频存放在dataset/voxceleb/vox1/{dev,test}与dataset/voxceleb/vox2/;而 manifest 与 CSV 等轻量索引文件写入dir(默认data/)。这也解释了examples/voxceleb/README.md中"VoxCeleb2 的 wav 需自行转换后放入wav目录"的原因——转换逻辑由 convert.sh 负责,训练脚本只消费 wav 索引。

数据处理完成后,data/目录结构如下(与 sv0/README.md 描述一致):

data/ ├── rir_noise │ ├── csv │ │ ├── noise.csv │ │ └── rir.csv │ ├── manifest.pointsource_noises │ ├── manifest.real_rirs_isotropic_noises │ └── manifest.simulated_rirs ├── vox │ ├── csv │ │ ├── dev.csv │ │ ├── enroll.csv │ │ ├── test.csv │ │ └── train.csv │ └── meta │ └── label2id.txt └── vox1 ├── list_test_all2.txt ├── list_test_all.txt ├── list_test_hard2.txt ├── list_test_hard.txt ├── manifest.dev ├── manifest.test ├── veri_test2.txt ├── veri_test.txt ├── voxceleb1.dev.meta └── voxceleb1.test.meta

其中data/vox/csv/train.csv由split_ratio: 0.9控制从 dev 集切分(90% 训练、10% 内部验证),enroll.csv与test.csv供验证阶段构建 enrollment/test 嵌入。label2id.txt是说话人标签到数字 id 的映射,对应训练分类头的类别索引。

八、Stage 1:模型训练

训练由 local/train.sh 驱动,最终调用 train.py。脚本根据CUDA_VISIBLE_DEVICES自动判断设备:多卡时通过paddle.distributed.launch启动分布式训练,单 CPU 时直接单进程运行:

# GPU(4 卡) CUDA_VISIBLE_DEVICES=0,1,2,3 bash ./local/train.sh ./data/ exp/ecapa-tdnn-vox12-big/ conf/ecapa_tdnn.yaml # 仅 CPU CUDA_VISIBLE_DEVICES= bash ./local/train.sh ./data/ exp/ecapa-tdnn-vox12-big/ conf/ecapa_tdnn.yaml

从 train.py 源码可以看到训练主流程的关键步骤:

  1. paddle.set_device(args.device)设置设备;
  2. paddle.distributed.init_parallel_env()初始化并行环境,随后用seed_everything(config.seed)固定随机种子——这是多进程训练可复现的必要措施;
  3. 特征侧采用paddlespeech.audio.compliance.librosa.melspectrogram提取 80 维 fbank(对应配置中sr: 16000, n_mels: 80);
  4. 数据读取使用 CSVDataset,训练时还会通过 build_augment_pipeline 加载 Stage 0 生成的 RIR/噪声 CSV 做语音增强;
  5. 模型封装为SpeakerIdetification(backbone=EcapaTdnn(...), num_class=7205),训练目标为 AAM-softmax 说话人分类损失。

训练产生的 checkpoint 存放在exp_dir下(如exp/ecapa-tdnn-vox12-big/),日志写入exp/log目录。

九、Stage 2:模型测试与 EER 评测

测试由 local/test.sh 驱动,调用 test.py 计算说话人验证指标:

CUDA_VISIBLE_DEVICES=0 bash ./local/test.sh ./data/ exp/ecapa-tdnn-vox12-big/ conf/ecapa_tdnn.yaml

测试流程分四步(对应 test.py 中的函数):

  1. 嵌入提取:对 enrollment/test 数据集的每个音频提取 192 维说话人嵌入(model.backbone(feats, lengths)输出(N, emb_size, 1),squeeze(-1)后得到(N, emb_size));
  2. 全局嵌入归一化:若配置global_embedding_norm: True,使用 InputNormalization 对全部嵌入做均值方差归一化——源码注释指出该操作可相对降低约 10% 的 EER;
  3. 余弦打分:遍历 trial 文件,对每对"说话人-语音"计算嵌入余弦相似度,并支持 s-norm 分数归一化(使用cohort_size: 20000的冒名者 cohort 与n_train_snts: 400000条训练句计算归一化统计量);
  4. EER 计算:compute_eer基于sklearn.metrics.roc_curve求得等错误率(EER,越低越好)。

十、配置文件详解:ecapa_tdnn.yaml

conf/ecapa_tdnn.yaml 是完整的实验配置,按功能划分为六个区块。仓库还提供了一份轻量版 conf/ecapa_tdnn_small.yaml(模型通道数减半、仅用 VoxCeleb1 训练、epochs 提升到 100),适合快速验证。

10.1 数据配置

参数默认值说明
augmentTrue是否使用 RIR/噪声数据做语音增强
batch_size32训练 batch 大小
num_workers2DataLoader 子进程数
num_speakers7205训练说话人类别数(Vox1 1211 + Vox2 5994)
shuffleTrue是否打乱数据
skip_prepFalse是否跳过数据预处理
split_ratio0.9dev 集按 9:1 切分训练/验证
chunk_duration3.0每条语音随机截取的时长(秒)
random_chunkTrue是否随机截取 chunk
verification_filedata/vox1/veri_test2.txt评测 trial 文件

10.2 特征提取配置

参数默认值说明
sr16000采样率
n_mels80Mel 滤波器组数量(fbank 维度)
window_size400窗长,25ms × 16000 / 1000 = 400 采样点
hop_size160帧移,10ms × 16000 / 1000 = 160 采样点

配置注释明确说明当前特征仅支持 fbank。

10.3 模型配置

参数默认值说明
model.input_size80输入 fbank 维度
model.channels[1024, 1024, 1024, 1024, 3072]各 TDNN 块的通道数
model.kernel_sizes[5, 3, 3, 3, 1]一维卷积核大小
model.dilations[1, 2, 3, 4, 1]各块膨胀率
model.attention_channels128注意力统计池化中的注意力维度
model.lin_neurons192最终说话人嵌入维度

对应 EcapaTdnn 的构造函数签名。从源码可以确认 ECAPA-TDNN 的完整结构:初始 TDNN 层 → 多个 SE-Res2Net 块 → 多层特征聚合(MFA,将中间层输出 concat 后经 TDNN 块)→ 注意力统计池化(Attentive Statistics Pooling + BatchNorm)→ 1×1 卷积投影到lin_neurons维嵌入。该实现忠实还原了论文 "ECAPA-TDNN: Emphasized Channel Attention, Propagation and Aggregation in TDNN Based Speaker Verification" 中强调的三大设计:通道注意力(SE-Res2Net)、特征传播(多层特征聚合)与特征聚合(注意力统计池化)。

10.4 训练配置

参数默认值说明
seed1986随机种子(与 SpeechBrain 官方配置一致)
epochs10训练轮数
save_interval10checkpoint 保存间隔
log_interval10日志打印间隔
learning_rate1e-8循环学习率下界
max_lr1e-3循环学习率上界
step_size140000循环学习率周期步数

训练侧使用 CyclicLRScheduler(循环学习率调度),learning_rate与max_lr构成其上下界,这也是 SpeechBrain 复现该模型时的标准设置。

10.5 损失函数配置

参数默认值说明
margin0.2AAM-softmax 角度余量
scale30AAM-softmax 缩放因子

对应源码 loss.py 中的AdditiveAngularMargin与LogSoftmaxWrapper:在 softmax 分类头上施加角度间隔,显著增强类间可分性,是当前声纹识别的主流训练范式。

10.6 测试与分数归一化配置

参数默认值说明
global_embedding_normTrue全局嵌入归一化(相对降 EER 约 10%)
embedding_mean_normTrue嵌入减均值归一化
embedding_std_normFalse嵌入除标准差归一化
score_norms-norm打分归一化方式
cohort_size20000归一化 cohort 中冒名者语音数量
n_train_snts400000计算归一化统计量使用的训练句数

十一、使用预训练模型

官方在 released_model.md 中发布声纹模型。以sv0_ecapa_tdnn_voxceleb12_ckpt_0_2_1.tar.gz为例,使用方式如下:

tar -xvf sv0_ecapa_tdnn_voxceleb12_ckpt_0_2_1.tar.gz source path.sh # 若已处理数据并生成 manifest,可直接执行: CUDA_VISIBLE_DEVICES= bash ./local/test.sh ./data sv0_ecapa_tdnn_voxceleb12_ckpt_0_2_1/model/ conf/ecapa_tdnn.yaml

test.sh的--load-checkpoint参数会从解压目录加载模型权重完成评测,因此无需重新训练即可在 VoxCeleb1 协议上复现官方结果。

十二、实验结果参考

RESULT.md 记录了官方发布模型的性能:

模型参数量嵌入维度测试集Cosine EERCosine + S-Norm EER
ECAPA-TDNN85M192VoxCeleb1 test0.8188%0.7815%

作为对照,SpeechBrain 官方实现(Vox1+Vox2 联合训练)在相同协议上的 EER 为 0.90%(无 s-norm)与 0.80%(有 s-norm),PaddleSpeech 的实现处于同一水平量级,验证了该复现流程的有效性。

十三、如何从零跑通整个示例

综合上述各节,从零复现的推荐路径是:

# 1. 进入示例目录 cd examples/voxceleb/sv0 # 2. 加载环境 source path.sh # 3. 完整流水线:数据处理 + 训练 + 测试(使用 run.sh 的默认 4 卡 GPU 设置) bash run.sh --stage 0 --stop_stage 2 # 或者手动分步执行: bash ./local/data.sh ./data/ conf/ecapa_tdnn.yaml CUDA_VISIBLE_DEVICES=0,1,2,3 bash ./local/train.sh ./data/ exp/ecapa-tdnn-vox12-big/ conf/ecapa_tdnn.yaml CUDA_VISIBLE_DEVICES=0 bash ./local/test.sh ./data/ exp/ecapa-tdnn-vox12-big/ conf/ecapa_tdnn.yaml

几点实用建议:

  • 磁盘与时间:VoxCeleb2 原始 m4a 转 wav 耗时数小时且占用大量磁盘,转换仅需一次,转换完成后 m4a 可保留备查(convert.sh不会删除原文件);
  • 硬件:完整 Vox1+Vox2 训练(epochs: 10、85M 参数)建议使用多卡 GPU;仅做验证可改用 ecapa_tdnn_small.yaml(通道数减半、单数据集);
  • 评测细节:EER 计算依赖sklearn,打分支持余弦与余弦+s-norm 两种模式,可通过score_norm参数切换。

结语

通过examples/voxceleb/示例,PaddleSpeech 提供了一条从原始 VoxCeleb 音频到生产级声纹系统的完整可复现链路:标准化的 m4a→wav 数据转换、manifest/CSV 索引生成、基于 AAM-softmax 的 ECAPA-TDNN 说话人分类训练、余弦打分与 EER 评测,以及官方预训练模型。无论是入门声纹识别还是在此基础上做工程化改造(如替换骨干网络、切换打分后端),本文梳理的配置参数与源码调用关系都可以作为直接的落地参考。

  • 人工智能
  • 语音
  • 音频

【免费下载链接】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.

项目地址:https://gitcode.com/gh_mirrors/pa/PaddleSpeech
点击查看免费下载

相关推荐

上一篇:深度学习历史重现:如何在90秒内复现LeCun 1989年卷积神经网络论文
下一篇:Fooocus AI绘画工具:3分钟快速上手指南与核心价值解析

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 3:15:26

基于Web的网上汽车租赁系统毕设全解析:从需求到部署全程

说实话&#xff0c;每年毕业季看到最多的选题就是“XX管理系统”&#xff0c;但“基于web的网上汽车租赁系统”这个题目在同类毕设里算是非常典型、也非常能体现完整度的方向。它不只是一个简单的增删改查网站&#xff0c;里面涉及的角色权限、订单流转、计费规则、车辆状态管理…

作者头像 李华
网站建设 2026/9/25 3:14:45

C++新手学习网站推荐:cppreference、learncpp、菜鸟教程与w3school对比

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华