☰
PaddleSpeech 音频分类数据集基类 AudioClassificationDataset 深度解析:从数据加载到特征提取的完整实践
2026/9/25 11:33:12 网站建设 项目流程
  • 人工智能
  • 语音
  • 音频

【免费下载链接】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 仓库中paddleaudio.datasets.dataset模块展开,深入剖析音频分类任务中统一数据集基类AudioClassificationDataset的设计原理、特征提取机制与数据切分策略,并结合 ESC-50、GTZAN、TESS、UrbanSound8K、HeySnips、VoxCeleb 等真实数据集实现,说明如何基于该基类构建、使用和扩展音频分类数据集。读者读完后,将掌握 PaddleSpeech 中音频数据管线的完整调用链、feat_type五种特征模式的选型要点,以及训练集/开发集切分的底层逻辑。

一、模块定位:音频分类数据集的统一基类

1.1 文档入口与模块结构

docs/source/audio_api/paddleaudio.datasets.dataset.rst是 PaddleSpeech 文档系统中paddleaudio.datasets.dataset模块的 API 文档入口,通过 Sphinx 的automodule指令自动生成该模块的完整成员文档:

.. automodule:: paddleaudio.datasets.dataset :members: :undoc-members: :show-inheritance:

该模块的实体代码位于 audio/paddleaudio/datasets/dataset.py,核心交付物是一个面向音频分类任务的通用数据集基类AudioClassificationDataset,它继承自 Paddle 框架的paddle.io.Dataset,为所有音频分类数据集子类提供了统一的"文件列表 + 标签列表 + 特征提取"骨架。

在 PaddleSpeech 中,该基类被两个位置复用:

  • PaddleAudio 独立音频库:audio/paddleaudio/datasets/dataset.py;
  • PaddleSpeech 主包:paddlespeech/audio/datasets/dataset.py。

两个位置的类定义保持同构,子类通过 audio/paddleaudio/datasets/init.py 统一导出,当前注册的数据集包括ESC50、GTZAN、HeySnips、OpenRIRNoise、TESS、UrbanSound8K、VoxCeleb。

1.2 继承体系与整体调用链

从源码结构看,AudioClassificationDataset的继承与调用链可以归纳为:

paddle.io.Dataset └── AudioClassificationDataset # 基类:files + labels + 特征提取 ├── ESC50 # 环境声音分类(50 类) ├── GTZAN # 音乐流派分类(10 类) ├── TESS # 情感语音识别(7 类) ├── UrbanSound8K # 城市声音分类(10 类) └── HeySnips # 唤醒词检测(kaldi_fbank 特征) paddle.io.Dataset └── OpenRIRNoise # 数据增强用 RIR/噪声(独立实现) └── VoxCeleb # 说话人验证(独立实现)

其中HeySnips、OpenRIRNoise、VoxCeleb直接使用基类模块中定义的feat_funcs特征函数注册表,共享同一套特征提取能力。

二、基类核心实现:构造参数与数据获取

2.1 构造函数参数说明

AudioClassificationDataset.__init__接收四个核心参数(dataset.py):

参数类型默认值含义
filesList[str]必填音频文件的绝对路径列表
labelsList[int]必填与files一一对应的类别标签
feat_typestr'raw'特征类型,决定对每段音频做何种特征提取
sample_rateintNone采样率;为None时保持音频原始采样率,否则统一重采样
**kwargsdict{}额外的特征提取配置,透传给对应的特征函数

构造函数在实例化时会先校验feat_type是否在feat_funcs注册表中,若传入未知类型会抛出RuntimeError:

if feat_type not in feat_funcs.keys(): raise RuntimeError( f"Unknown feat_type: {feat_type}, it must be one in {list(feat_funcs.keys())}" )

2.2 特征函数注册表 feat_funcs

基类模块顶部定义了五种特征模式的注册表,是整个数据管线的特征分发中枢(dataset.py):

feat_funcs = { 'raw': None, 'melspectrogram': melspectrogram, 'mfcc': mfcc, 'kaldi_fbank': kaldi_fbank, 'kaldi_mfcc': kaldi_mfcc, }

各模式对应的实现与适用场景:

feat_type底层实现输入形态输出典型场景
rawNonenumpy 波形原始波形端到端模型或下游自定义特征
melspectrogramlibrosa 兼容实现numpy 波形(n_mels, num_frames)音频分类、环境声音识别
mfcclibrosa 兼容实现numpy 波形(n_mfcc, num_frames)音乐流派、情感识别
kaldi_fbankKaldi 对齐实现Paddle Tensor(C, T)(num_frames, n_mels)唤醒词检测(HeySnips 默认)
kaldi_mfccKaldi 对齐实现Paddle Tensor(C, T)(num_frames, n_mfcc)ASR 前端特征

值得注意的是,两种 kaldi 系列特征输入的是paddle.Tensor((C, T)形状),输出帧优先的二维矩阵;而两种 librosa 系列特征与raw模式处理的是 numpy 波形。基类在_convert_to_record中对这一差异做了分支处理。

2.3 数据获取与记录转换流程

_convert_to_record完成"读音频 → 提特征 → 组装样本"的核心流程(dataset.py):

def _convert_to_record(self, idx): file, label = self.files[idx], self.labels[idx] if self.sample_rate is None: waveform, sample_rate = load_audio(file) else: waveform, sample_rate = load_audio(file, sr=self.sample_rate) feat_func = feat_funcs[self.feat_type] record = {} if self.feat_type in ['kaldi_fbank', 'kaldi_mfcc']: waveform = paddle.to_tensor(waveform).unsqueeze(0) # (C, T) record['feat'] = feat_func( waveform=waveform, sr=self.sample_rate, **self.feat_config) else: record['feat'] = feat_func( waveform, sample_rate, **self.feat_config) if feat_func else waveform record['label'] = label return record

流程要点:

  1. 音频读取:通过soundfile_load(audio/paddleaudio/backends/soundfile_backend.py)加载波形;该函数底层基于libsndfile,支持 WAV、FLAC、OGG/VORBIS、SPHERE 等格式,并内置单声道合并、线性/高斯归一化、kaiser 滤波重采样等处理;
  2. 特征分发:依据feat_type从注册表取出对应特征函数,把**kwargs中的feat_config作为特征参数透传;
  3. kaldi 系列特殊处理:将波形转为paddle.Tensor并增加通道维度到(C, T),与 Kaldi 特征函数fbank/mfcc的输入契约(waveform: Tensor,形状(C, T),C取值 0 或 1)对齐;
  4. 标签组装:把标签写入record['label'],供__getitem__返回。

__getitem__进一步区分返回格式(dataset.py):

  • 对kaldi_fbank/kaldi_mfcc,返回三元组(self.keys[idx], record['feat'], record['label']),其中keys由子类在_get_data中填充(如 HeySnips 的音频 id),供流式/对齐训练使用;
  • 其余特征类型返回(np.array(feat).transpose(), np.array(label, dtype=np.int64)),即转置后的特征矩阵与 int64 标签。

__len__直接返回files列表长度,保证与数据总量一致。

三、音频后端与特征实现:底层原理纵深

3.1 音频读取后端 soundfile_load

基类默认使用 soundfile 后端读取音频(from ..backends.soundfile_backend import soundfile_load as load_audio)。soundfile_load的核心处理链为:soundfile_load_(libsndfile 底层读取)→to_mono(多声道合并,支持ch0/ch1/random/average四种策略)→resample(基于 resampy,支持kaiser_best与kaiser_fast)→normalize(linear线性归一化到[-1, 1]或gaussian零均值单位方差)→depth_convert(按目标 dtype 转换)。

设计上的一个细节:resample在kaiser_best模式下会输出性能告警,提示大规模训练建议使用kaiser_fast,这与 PaddleSpeech 大规模音频训练的实际诉求一致。

3.2 两类特征实现的对齐语义

Kaldi 对齐特征(kaldi_fbank / kaldi_mfcc):实现在 audio/paddleaudio/compliance/kaldi.py,目标是"输出与 Kaldi 完全一致"。以fbank为例(kaldi.py),完整复刻了 Kaldi 的参数体系:

  • 窗函数参数:frame_length=25.0(毫秒)、frame_shift=10.0、window_type="povey"、blackman_coeff=0.42;
  • 信号预处理:preemphasis_coefficient=0.97、remove_dc_offset=True、dither=0.0、snip_edges=True;
  • Mel 滤波:n_mels=23、low_freq=20.0、high_freq=0.0、use_power=True、use_log_fbank=True;
  • 输出修饰:subtract_mean=False、use_energy=False、htk_compat=False、vtln_warp=1.0。

计算管线依次为:分帧加窗(_get_waveform_and_window_properties+_get_window)→paddle.fft.rfft计算幅度谱 → 可选平方转功率谱 → 与 Kaldi Mel 滤波器组(_get_mel_banks,含 VTLN 分段线性扭曲)做矩阵乘法 → 取对数 → 可选拼接能量维 → 可选减列均值。mfcc在 fbank 基础上叠加 DCT 变换矩阵(_get_dct_matrix)与倒谱提升(cepstral_lifter=22.0),输出n_mfcc=13维系数。

librosa 对齐特征(melspectrogram / mfcc):实现在 audio/paddleaudio/compliance/librosa.py,用于在无 librosa 依赖的环境下复现其计算语义。melspectrogram(librosa.py)的关键参数为:

  • 帧参数:window_size=512、hop_length=320、window='hann'、center=True、pad_mode='reflect';
  • Mel 参数:n_mels=64、fmin=50.0、fmax=None(None 时取sr//2)、power=2.0;
  • 刻度转换:to_db=True、ref=1.0、amin=1e-10、top_db=None。

计算流程为 STFT(stft)→ 功率谱np.abs(s)**power→ 乘以 Mel 滤波器组矩阵compute_fbank_matrix→ 可选power_to_db转 dB 刻度。mfcc则在其上施加 scipy DCT(dct_type=2, norm='ortho')并支持倒谱提升lifter。

这种"双套特征实现"的设计使得同一份数据既能为 Kaldi 生态的 ASR/唤醒词模型提供严格对齐的帧级特征,也能为基于 librosa 语义的分类模型提供频谱类特征,是feat_type设计意图的直接体现。

四、经典数据集子类实现:从基类到真实数据

基类的_get_data以NotImplementedError占位,强制子类实现"文件-标签"对的生产逻辑。以下按子类逐一分析。

4.1 ESC50:环境声音分类(50 类)

audio/paddleaudio/datasets/esc50.py 实现 ESC-50 数据集:2000 段 5 秒环境录音,覆盖 50 个语义类别(每类 40 条),源自论文ESC: Dataset for Environmental Sound Classification。

  • 归档与校验:archives指向 PaddleAudio 镜像的ESC-50-master.zip,附带 md5 校验;首次使用时_get_data检测DATA_HOME下缺少音频目录或元数据文件meta/esc50.csv,自动调用download_and_decompress下载解压;
  • 元数据解析:meta_info为 7 字段 namedtuple('filename', 'fold', 'target', 'category', 'esc10', 'src_file', 'take'),逐行读取 CSV 跳过表头;
  • 折切分:ESC-50 官方预定义 5 折(fold 1-5),mode='train'时取fold != split的全部样本,mode != 'train'(即 dev)时取fold == split的样本,无需随机种子即可保证训练/开发集不相交。

4.2 GTZAN:音乐流派分类(10 类)

audio/paddleaudio/datasets/gtzan.py 实现 GTZAN 数据集:1000 段 30 秒音乐片段,10 种流派各 100 条,是音乐流派识别(MGR)领域使用最广的公开数据集。

  • 构造参数在基类之上增加了seed=0、n_folds=5、split=1,并断言split <= n_folds;
  • 与 ESC50 依赖官方 fold 不同,GTZAN 采用随机折切分:读取genres/input.mf元数据后先random.seed(seed)再random.shuffle(meta_info),随后按n_samples_per_fold = len(meta_info) // n_folds均匀划分为 n 折,第split折作为 dev、其余作为 train——同样的 seed 可以复现出完全一致的切分;
  • 文件路径按DATA_HOME/genres/{label}/{filename}组织,标签通过label_list.index(label)转为整数索引。

4.3 TESS:情感语音识别(7 类)

audio/paddleaudio/datasets/tess.py 实现 TESS(Toronto Emotional Speech Set):两位女演员(26 岁与 64 岁)在载句 "Say the word ____" 中朗读 200 个目标词,录制 7 种情感(angry、disgust、fear、happy、neutral、pleasant surprise、sad),共 2800 条刺激样本。

  • 不依赖外部元数据文件,而是从文件名解析信息:_get_meta_info取文件去掉扩展名的 basename 按_拆分出(speaker, word, emotion)三元组;
  • 情感标签通过self.label_list.index(emotion)转换;
  • 同样采用seed+n_folds+split的随机折切分策略,切分前先os.walk收集全部.wav文件。

4.4 UrbanSound8K:城市声音分类(10 类)

audio/paddleaudio/datasets/urban_sound.py 实现 UrbanSound8K:8732 段不超过 4 秒的城市声音片段,10 个类别(air_conditioner、car_horn、children_playing、dog_bark、drilling、engine_idling、gun_shot、jackhammer、siren、street_music)。

  • 元数据文件为metadata/UrbanSound8K.csv,namedtuple 含 8 字段('filename', 'fsid', 'start', 'end', 'salience', 'fold', 'class_id', 'label');
  • 与 ESC50 一致采用官方预定义 fold 切分,音频按audio/fold{fold}/目录组织;
  • 归档来自 Zenodo 官方发布,同样附带 md5 校验与自动下载。

4.5 HeySnips:唤醒词检测(kaldi_fbank)

audio/paddleaudio/datasets/hey_snips.py 实现 HeySnips 唤醒词数据集,是基类"非默认特征 + 定制返回格式"的典型:

  • 构造函数要求显式传入data_dir,feat_type默认为kaldi_fbank,sample_rate=16000;
  • 元数据来自{mode}.json(JSON 逐条包含id、is_hotword、duration、audio_file_path),is_hotword == 1的样本标签为 0,其余为 -1(负样本);
  • _get_data额外填充self.keys与self.durations,配合基类__getitem__中 kaldi 分支返回(key, feat, label)三元组,供流式唤醒词模型的帧级训练使用。

五、独立数据集实现:OpenRIRNoise 与 VoxCeleb

这两个数据集直接继承paddle.io.Dataset,但复用了基类导出的feat_funcs注册表,并在基类之上增加了**音频切块(chunking)**能力,服务数据增强与说话人验证场景。

5.1 OpenRIRNoise:RIR 与噪声数据增强

audio/paddleaudio/datasets/rirs_noises.py 提供 OpenSLR 28 号资源(rirs_noises.zip)的封装,subsets仅含['rir', 'noise'],默认subset='rir',统一sample_rate=16000。

关键设计与参数:

  • chunk_duration=3.0(秒):_get_audio_info中若音频时长超过该值,按_get_chunks切分为等长片段,并调用soundfile_save落盘为_chunk_XX.wav,同时记录每个切片的起止时间戳;random_chunk=True时随机选取片段;
  • target_dir:可通过该参数重定向 CSV 生成目录,便于数据预处理到指定磁盘;
  • prepare_data读取 RIR 与噪声的 list 文件生成rir.csv/noise.csv,generate_csv表头为["id", "duration", "wav"];
  • _convert_to_record遍历 namedtuple 字段组装 record,并按feat_type经feat_funcs提取特征,__getitem__返回该 record。

该数据集典型的用途是数据增强:用rir子集做房间冲击响应卷积、用noise子集做加噪,从而提升模型在远场、嘈杂环境下的鲁棒性。

5.2 VoxCeleb:说话人验证

audio/paddleaudio/datasets/voxceleb.py 实现 VoxCeleb1 的完整数据管线,subsets为['train', 'dev', 'enroll', 'test'],默认subset='train'、sample_rate=16000、num_speakers=1211(代码注释说明:vox1 1211 人、vox2 5994 人、vox1+vox2 共 7205 人,测试集 41 人)。

  • 多分卷下载与拼接:archives_audio_dev包含vox1_dev_wav_partaa~partad四个分卷(各带 md5),下载后通过cat拼接为vox1_dev_wav.zip再解压;archives_audio_test直接下载vox1_test_wav.zip;archives_meta下载验证协议veri_test2.txt;
  • 数据准备:prepare_data从veri_test2.txt提取 enroll/test 文件集合与对应说话人,将其从训练池中排除,再以split_ratio=0.9把剩余音频随机切分为 train/dev,分别生成train.csv/dev.csv,enroll/test 则不切块直接生成 CSV;说话人 id 经排序后写入spk_id2label.txt完成类别编码;
  • 特征与切块:_convert_to_record中random_chunk=True时在每段音频内随机选取chunk_duration秒窗口,否则使用元数据记录的起止采样点;仅train/dev子集附带label;
  • 并行预处理:generate_csv使用pathos.multiprocessing.Pool(cpu_count())并行计算各音频的信息与切块信息,适配大规模说话人数据。

六、环境变量与数据目录约定

所有数据集子类通过DATA_HOME定位本地数据,该约定定义在 audio/paddleaudio/utils/env.py:

PPAUDIO_HOME --> 根目录,默认 ~/.paddleaudio,可用环境变量 PPAUDIO_HOME 覆盖 ├── models --> MODEL_HOME,存放模型文件 └── datasets --> DATA_HOME,存放自动下载的数据集

DATA_HOME为PPAUDIO_HOME/datasets,首次使用某数据集时若本地缺少对应音频目录与元数据,子类会通过download_and_decompress自动下载并解压(如 ESC50 的ESC-50-master.zip、GTZAN 的genres.tar.gz等,均带 md5 完整性校验)。这在实践上意味着:训练脚本首次运行会自动完成数据准备,无需手工搬运数据。

七、实践要点与选型建议

综合基类与各子类的源码实现,落地使用时建议关注以下几点:

  1. 特征选型与模型匹配:端到端模型选raw(返回原始波形);频谱类分类模型选melspectrogram或mfcc;需要与 Kaldi 生态严格对齐(如流式唤醒词、ASR 前端)时选kaldi_fbank/kaldi_mfcc,此时__getitem__返回(key, feat, label)三元组,且输入须为(C, T)的 Paddle Tensor。
  2. 特征参数透传:通过**kwargs可覆盖特征函数默认参数,例如AudioClassificationDataset(..., feat_type='melspectrogram', n_mels=80, fmin=0),但需注意参数名必须与对应特征函数签名一致,否则会抛类型错误。
  3. 切分复现:依赖官方 fold 的 ESC50 / UrbanSound8K 用split参数即可精确复现;依赖随机折切分的 GTZAN / TESS,必须固定seed以保证训练/开发集一致,TESS/GTZAN 还要求split <= n_folds(构造函数内已断言)。
  4. 采样率统一:sample_rate=None时保留原始采样率;传入目标值后统一走 resampy 重采样(默认kaiser_fast),多数据集混合训练时应显式统一采样率。
  5. 自定义数据集:继承AudioClassificationDataset后只需实现_get_data(mode, ...) -> (files, labels),即可自动获得特征提取、__len__、__getitem__等能力;若需返回帧级key,在_get_data中填充self.keys并选用 kaldi 系特征即可。

八、结语

paddleaudio.datasets.dataset模块以AudioClassificationDataset基类 +feat_funcs特征注册表为核心,向下对接 soundfile 音频后端与两套(Kaldi/librosa)特征实现,向上支撑 ESC50、GTZAN、TESS、UrbanSound8K、HeySnips 等分类数据集,并与 OpenRIRNoise、VoxCeleb 共享特征提取与数据准备能力,构成了 PaddleSpeech 音频分类任务统一、可扩展的数据管线。理解这一模块的继承关系、特征分发机制与折切分逻辑,是高效使用 PaddleSpeech 音频分类与相关语音任务的第一步。

  • 人工智能
  • 语音
  • 音频

【免费下载链接】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
点击查看免费下载

相关推荐

上一篇:终极指南:如何免费无限重置IDM试用期 - 完整技术实现方案
下一篇:如何用跨平台资源下载工具轻松获取无水印视频?新手完整指南

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

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

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

立即咨询