- 人工智能
- 语音
- 音频
- 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.
本篇文章以 examples/voxceleb/sv0/RESULT.md 为核心主体,结合 PaddleSpeech 的 VoxCeleb 说话人验证示例工程(数据准备、训练、测试全流程)与paddlespeech/vector源码,系统讲解 ECAPA-TDNN 说话人验证模型的实验结果、评价指标(EER、等错误率阈值)以及 S-Norm 评分归一化方法的实现原理。读完本文,你将能够复现该实验结果、读懂其评估指标,并理解评分归一化为何能显著降低 EER。
一、实验背景:VoxCeleb 数据集上的说话人验证任务
说话人验证(Speaker Verification)的任务是判断一段语音是否由指定说话人说出,是声纹识别(Voiceprint Recognition)的核心任务之一。VoxCeleb 是由牛津大学视觉几何组(VGG)发布的真实世界说话人识别数据集,包含 VoxCeleb1 与 VoxCeleb2 两个子集,语音均采集自自然环境(访谈、演讲等),噪声与信道差异大,是评测说话人验证系统的主流基准。
PaddleSpeech 的说话人验证示例位于examples/voxceleb/sv0目录,其完整流程由run.sh中的多个 stage 组成:
| Stage | 功能 |
|---|---|
| 0 | 数据准备:下载 VoxCeleb1/VoxCeleb2 数据集、将 VoxCeleb2 的 m4a 格式转为 wav、生成 train/dev/test 的 manifest 文件、下载 RIR Noise 数据集并生成用于数据增强的噪声 manifest |
| 1 | 训练说话人识别模型 |
| 2 | 使用 VoxCeleb trial 文件测试说话人验证(当前仅支持用余弦相似度打分) |
可以在 examples/voxceleb/sv0/run.sh 中看到这三个 stage 的实际调用:stage 0 调用./local/data.sh,stage 1 调用./local/train.sh,stage 2 调用./local/test.sh。
二、实验结果总览:ECAPA-TDNN 在 VoxCeleb 测试集上的 EER
RESULT.md记录的是 PaddleSpeech 0.2.1 版本发布的 ECAPA-TDNN 模型在 VoxCeleb test 集上的说话人验证结果,结果如下表:
| Model | Number of Params | Release | Config | dim | Test set | Cosine | Cosine + S-Norm |
|---|---|---|---|---|---|---|---|
| ECAPA-TDNN | 85M | 0.2.1 | conf/ecapa_tdnn.yaml | 192 | test | 0.8188 | 0.7815 |
表中各列含义:
- Number of Params:模型参数量为 85M(约 8500 万参数),属于大规模说话人编码器。
- Release:该模型随 PaddleSpeech 0.2.1 版本发布,对应压缩包名为
sv0_ecapa_tdnn_voxceleb12_ckpt_0_2_1.tar.gz。 - Config:模型与训练配置为
conf/ecapa_tdnn.yaml。 - dim:说话人嵌入(Speaker Embedding)维度为 192,即每条语音被映射为 192 维的声纹向量。
- Test set:测试集为 VoxCeleb 官方 test 划分(
data/vox1/veri_test2.txttrial 文件)。 - Cosine / Cosine + S-Norm:EER 分别为 0.8188% 与 0.7815%,单位为百分比,即等错误率。
该表同时对比了 SpeechBrain 的 ECAPA-TDNN 参考结果(voxceleb1 + voxceleb2 训练):不使用 S-Norm 时 EER 为 0.90%,使用 S-Norm 后降至 0.80%。可以直观看到:
- PaddleSpeech 复现的 ECAPA-TDNN 在纯余弦相似度打分下(0.8188%)已优于 SpeechBrain 的 0.90% 参考值;
- 引入 S-Norm 评分归一化后,EER 进一步从 0.8188% 降至 0.7815%(相对下降约 4.6%),再次验证了评分归一化对说话人验证性能的稳定增益。
三、ECAPA-TDNN 模型结构与源码实现
3.1 模型架构概述
ECAPA-TDNN(Emphasized Channel Attention, Propagation and Aggregation in TDNN Based Speaker Verification)是在传统 TDNN(时延神经网络)说话人嵌入网络基础上改进的骨干模型,论文发表于 2020 年(arXiv:2005.07143)。其核心创新点包括:
- SE-Res2Net 模块:在 Res2Net 多尺度卷积基础上引入 Squeeze-and-Excitation 通道注意力,强调说话人相关的特征通道;
- 多层特征聚合(Multi-layer Feature Aggregation, MFA):将多个 SE-Res2Net 层的输出拼接后送入聚合模块,实现不同感受野信息的传播与聚合;
- 注意力统计池化(Attentive Statistics Pooling, ASP):利用自注意力加权计算语音帧的均值与标准差,替代简单的均值池化,提取更稳健的句子级统计量。
3.2 源码级模块拆解
PaddleSpeech 的 ECAPA-TDNN 实现在 paddlespeech/vector/models/ecapa_tdnn.py 中,通过组合以下类构建完整网络:
TDNNBlock:单层 TDNN 块,由一维卷积 + ReLU 激活 + BatchNorm 组成,默认使用 reflect 模式的 "same" 填充(Conv1d._manage_padding动态计算填充量);Res2NetBlock:将输入按通道切分为scale(默认 8)个子块,逐块做 3×1 卷积并逐级累加,最后拼接回原始通道数,形成多尺度特征;SEBlock:全局平均池化(支持按lengths掩码)→ 1×1 卷积降维 → ReLU → 1×1 卷积升维 → Sigmoid,得到通道权重并乘回原特征;SERes2NetBlock:即 "TDNN1 → Res2Net → TDNN2 → SE" 的残差组合,输入输出通道不一致时自动引入 1×1 卷积捷径(shortcut);AttentiveStatisticsPooling:将 x 与其全局均值、标准差拼接以引入全局上下文,经 TDNN、Tanh、1×1 卷积生成注意力权重,softmax 后对 x 加权求均值与标准差,输出 2 倍通道数的统计特征;EcapaTdnn:主干网络,依次为初始 TDNN 块、若干 SERes2Net 块、多层特征聚合 TDNN、ASP 池化(后接 BatchNorm)与最终的 1×1 卷积线性层,输出形状为(N, emb_size, 1)的说话人嵌入。
EcapaTdnn.forward的实现中,各层输出被收集到xl列表,随后执行paddle.concat(xl[1:], axis=1)完成多层特征聚合,这正是 ECAPA-TDNN "Propagation and Aggregation" 思想的直接体现。
3.3 配置项逐字段解读
RESULT.md中的 85M 参数、192 维嵌入模型,其完整配置定义在 examples/voxceleb/sv0/conf/ecapa_tdnn.yaml 中,主要配置段如下:
数据与增强
augment: True # 是否启用 RIR/噪声数据增强 batch_size: 32 num_workers: 2 num_speakers: 7205 # 训练说话人数:1211 vox1 + 5994 vox2;测试说话人 41 shuffle: True split_ratio: 0.9 # 说话人语音按 9:1 划分(enroll/test) chunk_duration: 3.0 # 训练语音随机截取 3 秒片段 random_chunk: True verification_file: data/vox1/veri_test2.txt # 官方测试 trial 文件特征提取
sr: 16000 # 采样率 16kHz n_mels: 80 # 80 维 FBank 特征 window_size: 400 # 25ms 窗长(25 * 16000 / 1000 = 400) hop_size: 160 # 10ms 帧移(10 * 16000 / 1000 = 160)模型结构(对应EcapaTdnn构造参数)
model: input_size: 80 channels: [1024, 1024, 1024, 1024, 3072] # 各块通道数(含聚合层) kernel_sizes: [5, 3, 3, 3, 1] dilations: [1, 2, 3, 4, 1] # 空洞卷积膨胀率,扩大感受野 attention_channels: 128 # ASP 注意力通道数 lin_neurons: 192 # 最终嵌入维度(对应表中 dim=192)训练超参数
seed: 1986 # 与 SpeechBrain 配置保持一致 epochs: 10 save_interval: 10 log_interval: 10 learning_rate: 1e-8 # 循环学习率(Cyclic LR)的最小值 max_lr: 1e-3 # 循环学习率峰值 step_size: 140000 # 学习率循环步数训练阶段采用说话人识别(Speaker Identification)目标:以 AAM-Softmax(Additive Angular Margin Softmax)为损失,配置中的margin: 0.2、scale: 30即为角度间隔与缩放因子,其实现位于 paddlespeech/vector/modules/loss.py 的AngularMargin/AdditiveAngularMargin/LogSoftmaxWrapper类。训练出的模型随后在验证阶段仅使用 backbone(ECAPA-TDNN)提取嵌入,不再使用分类头。
四、评估指标解读:EER 与等错误率阈值
说话人验证系统的常用评价指标是等错误率(Equal Error Rate, EER)。其计算过程为:对 trial 中的每个测试对计算相似度得分,将得分从高到低排序并遍历阈值,在某个阈值下**误接受率(FAR,把非目标说话人判为目标)与误拒绝率(FRR,把目标说话人判为非目标)**相等,此时的错误率即为 EER,对应的得分即为等错误率阈值。
PaddleSpeech 的 EER 计算实现在 paddlespeech/vector/exps/ecapa_tdnn/test.py 的compute_eer函数中:
def compute_eer(labels: np.ndarray, scores: np.ndarray) -> List[float]: fpr, tpr, threshold = roc_curve(y_true=labels, y_score=scores) fnr = 1 - tpr eer_threshold = threshold[np.nanargmin(np.absolute((fnr - fpr)))] eer = fpr[np.nanargmin(np.absolute((fnr - fpr)))] return eer, eer_threshold实现思路是:借助sklearn.metrics.roc_curve得到不同阈值下的假阳性率(FPR)与真阳性率(TPR),令 FNR = 1 - TPR,找到 |FNR - FPR| 最小时对应的阈值作为 EER 阈值,该点的 FPR 即为 EER。测试脚本最终输出格式为EER of verification test: {EER*100:.4f}%, score threshold: {threshold:.5f}。
RESULT.md表中的 0.8188 / 0.7815 即为该测试流程(local/test.sh→test.py)在上述 trial 文件上计算得到的 EER(百分比形式)。verification_file指向data/vox1/veri_test2.txt,其中每一行形如label enroll_id test_id,1 表示同一说话人(目标),0 表示不同说话人(非目标)。
五、S-Norm 评分归一化:原理、实现与效果
5.1 为什么要做评分归一化
说话人验证中,注册语音与测试语音的余弦相似度得分受信道、噪声等条件影响存在系统性偏差,直接使用原始得分设定阈值会放大误判。评分归一化(Score Normalization)通过引入冒充者(imposter)集合统计得分的均值与标准差,将原始得分标准化后再比较,从而降低 EER、提升鲁棒性。常见的归一化方式包括 Z-Norm、T-Norm 和 S-Norm:
- Z-Norm:仅用注册(enroll)侧与冒充者集合的得分统计量归一化;
- T-Norm:仅用测试(test)侧与冒充者集合的得分统计量归一化;
- S-Norm(Symmetric Norm):对注册侧与测试侧两侧分别归一化后取平均,即 Z-Norm 与 T-Norm 的对称组合,效果更稳健。
5.2 源码实现
S-Norm 的实现在 paddlespeech/vector/exps/ecapa_tdnn/test.py 的compute_verification_scores函数中。核心逻辑为:
- 将注册嵌入与测试嵌入分别与整个冒充者集合(
train_cohort)逐行计算余弦相似度,得到得分向量; - 若配置了
cohort_size(conf/ecapa_tdnn.yaml中为 20000),则用paddle.topk仅保留相似度最高的前 k 个冒充者得分,再计算均值mean_e_c/mean_t_c与标准差std_e_c/std_t_c(取 top-k 是为了让统计量聚焦于"最像"的冒充者,避免无关低分样本稀释统计量); - 按配置的
score_norm类型归一化:
if config.score_norm == "s-norm": score_e = (score - mean_e_c) / std_e_c score_t = (score - mean_t_c) / std_t_c score = 0.5 * (score_e + score_t) elif config.score_norm == "z-norm": score = (score - mean_e_c) / std_e_c elif config.score_norm == "t-norm": score = (score - mean_t_c) / std_t_c可见 S-Norm 就是 Z-Norm 与 T-Norm 得分的平均。conf/ecapa_tdnn.yaml中对应配置为:
score_norm: s-norm cohort_size: 20000 # 归一化用冒充者集合的大小(取相似度最高的 2 万条) n_train_snts: 400000 # 从训练集抽取出用于归一化统计的语音条数测试流程中(test.py的main函数),冒充者集合取自data/vox/csv/train.csv训练集,并按n_train_snts限制条数;之后compute_dataset_embedding(train_loader, model, None, config, train_embeddings)计算训练集嵌入(不做均值/方差归一化,即传入mean_var_norm_emb=None),堆叠为train_cohort后送入打分函数。
5.3 效果分析
从RESULT.md可见:S-Norm 将 EER 从 0.8188% 降至 0.7815%,相对下降约 4.6%。这与 SpeechBrain 参考实现中 S-Norm 带来的增益方向一致(0.90% → 0.80%)。需要注意的是,S-Norm 需要额外的冒充者语料与计算开销,属于测试阶段的"锦上添花"手段,不影响训练过程。
六、实验复现:从数据准备到结果输出
6.1 一键式运行(推荐)
进入示例目录后,依次执行三个 stage 即可端到端复现实验:
# 数据准备 + 训练 + 测试(使用默认 4 卡 GPU:0,1,2,3) bash run.sh --stage 0 --stop_stage 2 # 只跑某一阶段,例如仅数据准备: bash run.sh --stage 0 --stop_stage 0 # 仅训练: bash run.sh --stage 1 --stop_stage 1run.sh中的本地变量均可通过--variable value方式覆盖,例如:
bash run.sh --gpus 0,1 # 指定 GPU 卡号 bash run.sh --conf_path conf/ecapa_tdnn_small.yaml # 换用小型模型配置其中gpus=(置空)表示仅使用 CPU 训练。
6.2 手动分步执行
首先设置环境变量(run.sh与各 local 脚本均依赖):
source path.sh source ${MAIN_ROOT}/utils/parse_options.sh # 支持 --variable value 风格的参数解析然后依次执行:
# 数据准备(生成 data/vox 下的 csv 与 manifest) 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 # 测试(输出 EER 与阈值) CUDA_VISIBLE_DEVICES=0 bash ./local/test.sh ./data/ exp/ecapa-tdnn-vox12-big/ conf/ecapa_tdnn.yaml数据准备完成后,data目录结构如下(详见 examples/voxceleb/sv0/README.md):
data/ ├── rir_noise # RIR 与噪声数据集及增强 manifest ├── vox │ ├── csv # train.csv / dev.csv / enroll.csv / test.csv │ └── meta/label2id.txt └── vox1 # veri_test2.txt trial 文件与 manifest.dev/test 等需要特别注意的是,VoxCeleb2 数据集原始音频为 m4a 格式,必须先使用local/convert.sh转为 wav 并放置到${MAIN_ROOT}/datasets/vox2,run.sh会从${MAIN_ROOT}/datasets/vox1/{dev,test}/wav与${MAIN_ROOT}/datasets/vox2/wav中查找音频。
6.3 使用官方预训练模型快速验证
如果不打算从零训练,可以直接下载 PaddleSpeech 发布的 0.2.1 版本 ECAPA-TDNN 预训练模型(即RESULT.md中记录结果对应的模型),解压后直接测试:
wget https://paddlespeech.cdn.bcebos.com/vector/voxceleb/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,可跳过 data 准备步骤 CUDA_VISIBLE_DEVICES= bash ./local/test.sh ./data sv0_ecapa_tdnn_voxceleb12_ckpt_0_2_1/model/ conf/ecapa_tdnn.yaml该模型同样收录于 docs/source/released_model.md 的说话人验证(Speaker Verification)模型列表中。local/test.sh最终调用 paddlespeech/vector/exps/ecapa_tdnn/test.py,加载model.pdparams检查点并输出 EER。
七、总结
PaddleSpeech 在 VoxCeleb 数据集上以 85M 参数、192 维嵌入的 ECAPA-TDNN 模型取得了 0.8188% 的 EER,配合 S-Norm 评分归一化进一步降至 0.7815%,达到并优于 SpeechBrain 参考实现的水平。这一结果背后是一套完整的工程链路:run.sh分阶段编排数据准备(含 m4a→wav 转换、RIR 噪声增强、trial 文件生成)、AAM-Softmax 说话人识别训练、嵌入提取与余弦打分、以及基于冒充者集合的 S-Norm 归一化与 EER 计算。读者既可以一键复现该实验,也可以通过 paddlespeech/vector/models/ecapa_tdnn.py 与 test.py 深入理解 ECAPA-TDNN 的模块化实现与评测细节,为构建自己的说话人验证系统提供可参照的基线。
- 人工智能
- 语音
- 音频
- 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.
相关推荐
PowerShell 7.0 发布周期全解:从 preview.1 到 7.0.13 的 LTS 长期服务版演进实录
PowerShell 7.0 发布周期全解:从 preview.1 到 7.0.13 的 LTS 长期服务版演进实录 本文基于仓库中的 CHANGELOG/7.
人工智能语音音频NLP媒体生成SpeechBrain 说话人识别与验证实战:基于 VoxCeleb 训练 X-Vector、ECAPA-TDNN 与 ResNet 嵌入
SpeechBrain 说话人识别与验证实战:基于 VoxCeleb 训练 X Vector、ECAPA TDNN 与 ResNet 嵌入 本篇技术指南以 Sp
人工智能深度学习语音音频NLP预训练PaddleSpeech 声纹识别(说话人验证)实战:用 ECAPA-TDNN 提取说话人嵌入并计算相似度
PaddleSpeech 声纹识别(说话人验证)实战:用 ECAPA TDNN 提取说话人嵌入并计算相似度 声纹识别(Speaker Verification)
人工智能语音音频NLP媒体生成
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考