SpeechBrain 声音分类实战:基于 ESC50 数据集的 CNN14 / Conv2D / FocalNet / ViT 多模型训练全解
2026/9/15 20:20:37 网站建设 项目流程

SpeechBrain 声音分类实战:基于 ESC50 数据集的 CNN14 / Conv2D / FocalNet / ViT 多模型训练全解

【免费下载链接】speechbrainA PyTorch-based Speech Toolkit项目地址: https://gitcode.com/GitHub_Trending/sp/speechbrain

本指南以 SpeechBrain 仓库中的 ESC50 声音分类 recipe(recipes/ESC50/classification/README.md)为骨架,系统讲解如何用该 recipe 在 50 类环境音数据集上训练音频分类器,涵盖数据自动下载与 fold 划分、特征提取管线(log-spectra 与 log-mel 双模式)、四种主流骨干网络(CNN14、Conv2D、FocalNet、ViT)的训练配置、WHAM! 噪声增强以及仅测试集评估。读完本文,你将能够直接复现表格中的公开结果,并深入理解每条配置背后的源码级实现原理。

ESC50 任务与数据集概览

ESC50 是一个多类别声音分类基准数据集,共包含50 个声音类别,每个类别 40 条样本,每条样本为 5 秒音频。recipe 的训练目标是让模型对输入音频正确判别其所属类别。50 个类别被划分为五个语义组:

  • Animals(动物):如狗吠、猫叫、鸡鸣等
  • Natural soundscapes and water sounds(自然声景与水声):如雨声、海浪、溪流
  • Human, non-speech sounds(人类非语音声音):如咳嗽、笑声、打鼾
  • Interior/domestic sounds(室内/居家声音):如敲门、电话铃、微波炉
  • Exterior/urban noises(室外/城市噪声):如直升机、警笛、钻孔

该 recipe 同时支持使用log-spectra(对数幅度谱)log-mel(对数梅尔谱)两种音频特征训练模型。前者直接对短时傅里叶变换(STFT)幅度谱取对数,后者在此基础上进一步通过梅尔滤波器组压缩频带。两种模式由 YAML 中的use_melspectra开关切换(详见下文配置解析)。

数据集下载:全自动还是手动?

运行 recipe 时,数据集会被自动下载到指定的--data_folder路径。若希望手动下载,可访问 ESC-50 数据集官方仓库(karolpiczak/ESC-50)获取原始压缩包。

自动下载的逻辑实现在 esc50_prepare.py 中。核心函数download_esc50(data_path)的执行流程如下:

  1. 检查目标目录下是否存在meta子目录,若不存在则判定数据集缺失;
  2. 通过 SpeechBrain 的speechbrain.utils.fetching.fetch工具从 ESC-50 官方发布地址下载master.zip(约 600MB,下载进度可在<data_folder>/temp_download中查看);
  3. shutil.unpack_archive解压,并将ESC-50-master目录下的所有文件上移一层到data_folder
  4. 清理临时目录与解压目录。

下载完成后,prepare_esc50()会进一步处理元数据:读取原始meta/esc50.csv,为每条样本生成ID列(去掉文件名后缀),并将category列重命名为 SpeechBrain 需要的class_string字段,生成修改版元数据meta/esc50_speechbrain.csv;随后据此为 train / valid / test 三个集合分别生成 JSON manifest 文件,默认输出到<data_folder>/manifest/{train,valid,test}.json

每个 manifest 条目包含wav(文件名)、classID(整数类别编号)、class_string(类别名)、fold(所属折编号)与duration(时长,通过audio_io.info读取真实采样率计算得出)。若个别文件读取失败,该样本会被跳过而不是中断流程。

安装额外依赖

在运行 recipe 之前,需要先安装额外的 Python 依赖。直接执行:

pip install -r extra_requirements.txt

extra_requirements.txt 中列出的依赖包括:matplotlib(混淆矩阵绘图)、pandas(元数据 CSV 处理)、scikit-learn(混淆矩阵计算)、torchvision(ViT/FocalNet 输入预处理与图像 resize)、transformers(加载 Hugging Face 上的 FocalNet / ViT 预训练骨干)以及wget。其中torchvisiontransformers仅在训练 FocalNet / ViT 骨干时严格必需,但统一安装可避免后续报错。

支持的四种模型与训练命令

recipe 提供四套超参配置文件,分别对应四种骨干网络。训练命令统一为python train.py hparams/<config>.yaml --data_folder /yourpath/ESC50,数据会在指定目录自动下载。

CNN14(cnn14.yaml)

CNN14 是 Audio Set 论文(《PANNs: Large-Scale Pretrained Audio Neural Networks》,arXiv:1912.10211)中提出的 14 层卷积网络,是音频事件分类的经典强基线。运行:

python train.py hparams/cnn14.yaml --data_folder /yourpath/ESC50

在 SpeechBrain 中的实现位于 speechbrain/lobes/models/Cnn14.py,Cnn14类由 6 个ConvBlock级联构成,通道数依次为 1→64→128→256→512→1024→emb_dim(本配置为 2048),每个卷积块内部还支持bn(BatchNorm)、in(InstanceNorm)、ln(LayerNorm/GroupNorm)三种归一化方式,默认使用bncompute_forward中会通过全局平均池化把输出的 4D 特征图压成 2048 维向量,再送入线性分类头。

该配置默认启用log-mel 特征use_melspectra: Trueuse_log1p_mel: True,80 个梅尔频带),并预训练初始化:通过speechbrain.utils.parameter_transfer.Pretrainer从 Hugging Face 加载speechbrain/cnn14-esc50embedding_model.ckpt

Conv2D(conv2d.yaml)

一个轻量级卷积分类器,适合快速验证管线或算力受限场景。运行:

python train.py hparams/conv2d.yaml --data_folder /yourpath/ESC50

(原文档此处命令末尾多打了一个反引号,实际命令与其余配置一致。)该配置使用 speechbrain/lobes/models/PIQ.py 中的Conv2dEncoder_v2(输出维度dim: 256)作为骨干,分类头采用 speechbrain/lobes/models/ECAPA_TDNN.py 中的Classifier(输入 256 维、输出 50 类、1 个线性块,其内部还带可选的全局统计池化与 BatchNorm)。Conv2D 配置默认使用log-spectra 特征use_melspectra: False),同时保留mean_var_norm(句子级输入归一化)模块,并加载speechbrain/PIQ-ESC50的预训练编码器。注意其学习率lr: 0.00002比 CNN14 低一个数量级。

FocalNet(focalnet.yaml)

FocalNet(Focal Modulation Networks)是 2022 年提出的视觉骨干,用焦点调制替代自注意力,在 speechbrain/lobes/models/Cnn14.py 之外的实现中通过transformers库直接加载 Hugging Face 上的microsoft/focalnet-base预训练权重(!apply:transformers.FocalNetBackbone.from_pretrained)。运行:

python train.py hparams/focalnet.yaml --data_folder /yourpath/ESC50

FocalNet 分类头输入维度为 1024。由于预训练模型期望的图像输入是 224×224×3,compute_forward中会先用torchvision.transforms.functional.resize把特征图缩放到配置的image_size,再扩展为 3 通道;随后取feature_maps[-1]做全局平均得到嵌入。该配置还首次引入了时域数据增强DropFreq+DropChunk,75% 概率触发,详见下文)。

ViT(vit.yaml)

Vision Transformer(ViT)骨干,通过transformers加载google/vit-base-patch16-224预训练模型,分类头输入维度为 768。运行:

python train.py hparams/vit.yaml --data_folder /yourpath/ESC50

与 FocalNet 类似,输入先 resize 到 224×224 并扩展为 3 通道;compute_forward中取last_hidden_state并转置后做均值池化得到 768 维嵌入。ViT 配置同样附带DropFreq+DropChunk增强。

四种配置的公共参数速览

配置骨干(预训练来源)特征模式epochbatch_sizelr分类头输入维
cnn14.yamlCnn14(speechbrain/cnn14-esc50)log-mel200322e-42048
conv2d.yamlConv2dEncoder_v2(speechbrain/PIQ-ESC50)log-spectra200322e-5256
focalnet.yamlFocalNetBase(microsoft/focalnet-base)log-spectra100162e-41024
vit.yamlViTBase(google/vit-base-patch16-224)log-spectra100162e-4768

配置文件核心参数解析

以 hparams/cnn14.yaml 为例,逐段解读关键配置:

  • 基础设置seed: 1234通过speechbrain.utils.seed_everything固定全局随机种子;data_folder: !PLACEHOLDER是必填占位符,运行时用--data_folder覆盖;audio_data_folder指向<data_folder>/audio
  • 输出目录output_folder: ./results/cnn14-esc50/<seed>save_folder存放检查点,train_log.txt记录训练日志。
  • 数据 manifesttrain_annotation/valid_annotation/test_annotation分别指向<data_folder>/manifest/{train,valid,test}.json
  • fold 划分train_fold_nums: [1, 2, 3]valid_fold_nums: [4]test_fold_nums: [5]。ESC50 官方把 2000 条样本预分为 5 折,recipe 默认用前 3 折训练、第 4 折验证、第 5 折测试。prepare_esc50会对 fold 编号做合法性校验(必须属于 1–5),并检查三组 fold 互斥,重叠会直接报错返回。
  • 训练参数number_of_epochs: 200batch_size: 32dataloader_optionsnum_workers: 0shuffle: True(配置注释特别强调"shuffle 这里很重要")。
  • 特征参数n_mels: 80use_melspectra: Trueuse_log1p_mel: True;预处理链路由compute_stft(STFT,n_fft: 1024spec_mag_power: 0.5的幅度谱)与compute_fbank(80 维梅尔滤波、log_mel: False)组成。
  • 模型组件embedding_model(Cnn14,mel_bins: 80emb_dim: 2048)、classifiertorch.nn.Linear,2048→50)、out_n_neurons: 50(类别数)。
  • 损失与优化compute_cost采用LogSoftmaxWrapper+AdditiveAngularMargin(margin 0.2、scale 30),即 AM-Softmax 损失,将分类损失改为角度间隔形式以增强判别力;opt_class为 Adam(weight_decay: 2e-6);lr_annealing使用CyclicLRSchedulerbase_lr: 1e-8max_lr: 2e-4step_size: 65000)做循环学习率调度。
  • 日志与检查点FileTrainLogger写训练日志;Checkpointer每 15 分钟(ckpt_interval_minutes)落盘一次,恢复对象包括embedding_modelclassifierepoch_counter
  • 预训练use_pretrained: Trueembedding_model_path: speechbrain/cnn14-esc50/embedding_model.ckpt,由Pretrainer负责从 Hugging Face 收集并加载权重。若不想用预训练编码器,删除pretrained_encoder字段或将use_pretrained置为False即可。

focalnet.yamlvit.yaml额外引入了时域增强块:DropFreq(随机丢弃 0–1 归一化频率轴上 1–3 个、宽度 0.05 的频带)与DropChunk(随机丢弃 1–5 个、长度 1000–2000 采样点的音频片段),二者由Augmenter以 75% 概率组合触发(min_augmentations/max_augmentations均为 2,concat_original: False)。增强在训练阶段作用于原始波形(见compute_forwardstage == sb.Stage.TRAIN的分支),相当于对网络施加频谱与时间上的随机遮盖正则化,这也是这两个视觉骨干在小数据上能收敛的重要原因。

训练脚本源码级解析

recipes/ESC50/classification/train.py 是 recipe 的入口,整体遵循 SpeechBrain 的 Brain 类范式。

主流程(__main__

  1. sb.parse_arguments(sys.argv[1:])解析命令行(hparams_filerun_optsoverrides),--data_folder这类键值对会作为 overrides 注入;
  2. sb.utils.distributed.ddp_init_group初始化多卡 DDP(单卡无影响);
  3. load_hyperpyyaml加载 YAML 并实例化其中的!new:/!apply:对象;
  4. sb.create_experiment_directory创建实验目录并备份超参文件;
  5. run_on_main(prepare_esc50, ...)只在主进程执行一次数据准备(避免多卡重复下载);
  6. dataio_prep(hparams)构建数据集与标签编码器;
  7. 若配置了wham_folder,调用prepare_wham构建 WHAM! 噪声数据流;
  8. 实例化ESC50Brain,按需加载预训练编码器(pretrained_encoder.collect_files+load_collected);
  9. test_only时执行fit(),最后用evaluate()在测试集上评估。

数据管线(dataio_prep

audio_pipeline负责读音频:加载 wav 后 squeeze 维度、多声道取均值降混为单声道、必要时用torchaudio.transforms.Resample重采样到配置的sample_rate: 16000,最后归一化到sig / sig.max()label_pipeline通过sb.dataio.encoder.CategoricalEncoderclass_string编码为张量标签。三份 JSON 经DynamicItemDataset.from_json加载,输出键为["id", "sig", "class_string_encoded"]。标签编码器以save_folder/label_encoder.txt持久化,支持多卡 DDP 下的load_or_create

前向与目标计算(compute_forward/compute_objectives

compute_forward的完整链路为:波形 →(可选)增强 / WHAM! 混噪 → STFT 幅度谱(spec_mag_power: 0.5)→(可选)梅尔滤波 →log1p取对数 → 嵌入模型 → 全局平均池化 → 分类头 →(outputs, lens)。其中对 Hugging Face 骨干(有config属性)与 SpeechBrain 本地骨干(CNN14、Conv2D)走了两套分支:前者 resize + 扩三通道后按model_typefocalnet/vit)分别取feature_maps[-1]last_hidden_state池化;后者直接消费特征图,4D 输出按(-1, -2)均值池化。

compute_objectives将预测与标签做 one-hot 交叉熵(对增强后的批次按倍数复制标签),训练/验证阶段在on_batch_end触发循环学习率步进;同时在验证与测试阶段累计confusion_matrixsklearn.metrics),并通过self.acc_metric(基于speechbrain.utils.Accuracy)与error_stats统计精度与分类错误率。

阶段收尾与可视化

on_stage_end在验证结束时执行学习率退火、TensorBoard/文件日志记录,并用checkpointer.save_and_keep_only(min_keys=["error"])只保留验证错误率最优的检查点;验证阶段还会用 confusion_matrix_fig.py 中的create_cm_fig生成混淆矩阵图写入 TensorBoard(Validation Confusion Matrix)。测试阶段则输出逐类准确率与完整混淆矩阵到日志,便于定位易混淆类别。

使用 WHAM! 噪声增强训练

recipe 支持在训练时叠加 WHAM! 环境噪声,模拟真实嘈杂场景下的分类。步骤为:

  1. 从 WHAM! 官网下载噪声数据集(wham_noise);
  2. 运行训练命令并追加两个参数:
python train.py hparams/modelofchoice.yaml --data_folder /yourpath/ESC50 --add_wham_noise True --wham_folder /yourpath/wham_noise

底层实现在 wham_prepare.py:prepare_whamwham_folder为空时自动下载 WHAM! 噪声包;WHAMDataset是一个IterableDataset,无限随机采样噪声 wav,统一重采样到 16kHz 并裁剪/补零到signal_length_s秒;combine_batchescompute_forward中按0dB 信噪比混合干净信号与噪声(各自先做 L2 归一化再相加,最后整体归一化)。若开启该功能,train.py会断言signal_length_s == 5,即 5 秒的 ESC50 样本必须与 5 秒的噪声窗口对齐。注意:只要指定了--add_wham_noise True,就必须同时给出--wham_folder,否则prepare_wham会抛出异常提示。

仅运行测试集评估

若只想在测试集上评估已训练的模型(例如重新验证检查点),在命令末尾追加--test_only标志:

python train.py hparams/<config>.yaml --data_folder /yourpath/ESC50 --test_only

该标志对应 YAML 中的test_only: False。置为True后,train.py会跳过fit()训练阶段,直接从检查点目录恢复最优模型(evaluate时以min_key="error"选取检查点),并在测试集上输出整体准确率、错误率、逐类准确率与混淆矩阵。

公开实验结果

原文档给出的四套配置在各自数据集划分下的复现结果如下(准确率为测试集 Accuracy,训练时间为单 epoch 耗时,GPU 环境为训练时所用硬件):

超参文件准确率 (%)训练时间GPU
cnn14.yaml82.011 秒/epochRTX 3090
conv2d.yaml75.015 秒/epochRTX 3090
focalnet.yaml77.460 秒/epoch1×V100 32GB
vit.yaml73.656 秒/epoch1×V100 32GB

官方同时提供了各模型的 Hugging Face 权重与 Dropbox 备份链接,便于直接加载推理或微调。以上数据仅为该 recipe 在默认 fold 划分与配置下的复现值,不同随机种子、fold 组合或硬件环境下结果会有所波动。

使用注意事项

  • recipe 会自动下载 ESC50 数据集,你只需通过--data_folder指定期望的存放路径;数据已存在时不会重复下载。
  • 各训练脚本所需的预训练模型权重(CNN14/PIQ 编码器、FocalNet/ViT 骨干)均会自动下载,无需手动干预。
  • 若需自定义数据划分,可修改 YAML 中的train_fold_nums/valid_fold_nums/test_fold_nums,但需保证三者互斥且取值在 1–5 之间;skip_manifest_creation: True可跳过 manifest 重建步骤(适合数据集已就绪、仅改 fold 重训的场景)。

引用

如果本 recipe 对你有帮助,请引用以下工作。CNN14/Conv2D 路线对应的自监督表示学习工作:

@article{Wang_2022, doi = {10.1109/lsp.2022.3229643}, url = {https://doi.org/10.1109%2Flsp.2022.3229643}, year = 2022, publisher = {Institute of Electrical and Electronics Engineers ({IEEE})}, volume = {29}, pages = {2607--2611}, author = {Zhepei Wang and Cem Subakan and Xilin Jiang and Junkai Wu and Efthymios Tzinis and Mirco Ravanelli and Paris Smaragdis}, title = {Learning Representations for New Sound Classes With Continual Self-Supervised Learning}, journal = {{IEEE} Signal Processing Letters} }

FocalNet 在可解释声音分类上的工作:

@inproceedings{dellalibera2024focal, title={Focal Modulation Networks for Interpretable Sound Classification}, author={Luca Della Libera and Cem Subakan and Mirco Ravanelli}, booktitle={IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP) XAI-SA Workshop}, year={2024}, }

使用 SpeechBrain 请引用:

@misc{speechbrain, title={{SpeechBrain}: A General-Purpose Speech Toolkit}, author={Mirco Ravanelli and Titouan Parcollet and Peter Plantinga and Aku Rouhe and Samuele Cornell and Loren Lugosch and Cem Subakan and Nauman Dawalatabad and Abdelwahab Heba and Jianyuan Zhong and Ju-Chieh Chou and Sung-Lin Yeh and Szu-Wei Fu and Chien-Feng Liao and Elena Rastorgueva and François Grondin and William Aris and Hwidong Na and Yan Gao and Renato De Mori and Yoshua Bengio}, year={2021}, eprint={2106.04624}, archivePrefix={arXiv}, primaryClass={eess.AS}, note={arXiv:2106.04624} }

延伸阅读

  • 若对可解释性感兴趣,同一数据集的解释性变体见 recipes/ESC50/interpret(含 PIQ、NMF、LMAC 等可解释分类器)。
  • 与 ESC50 同源的 UrbanSound8k 分类 recipe 位于 recipes/UrbanSound8k/SoundClassification,本 recipe 的代码结构即基于它改写。

【免费下载链接】speechbrainA PyTorch-based Speech Toolkit项目地址: https://gitcode.com/GitHub_Trending/sp/speechbrain

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询