IEMOCAP数据集预处理实战用Python和Librosa搞定语音情感识别的数据准备语音情感识别SER作为人机交互领域的重要研究方向其核心挑战之一是如何从原始音频中提取有效的特征表示。本文将手把手带你完成IEMOCAP数据集的预处理全流程从数据统计分析到梅尔频谱图生成为后续ResNet18等模型的训练打下坚实基础。1. IEMOCAP数据集解析与预处理策略IEMOCAPInteractive Emotional Dyadic Motion Capture是南加州大学收集的经典多模态情感数据集包含5个会话session中10位说话人5男5女的即兴表演和剧本朗读。原始数据中标注了9种情感标签但实际应用中通常采用四分类方案# 情感标签映射关系四分类方案 label_mapping { ang: 0, # 愤怒 exc: 1, # 兴奋与happy合并 hap: 1, # 快乐 neu: 2, # 中性 sad: 3 # 悲伤 }数据集分布存在明显不均衡问题各情感类别的样本数量如下表所示情感类别原始样本数处理后样本数ang11031103exchap16361636neu17081708sad10841084注意实际应用中建议对样本较少的类别进行过采样或采用加权损失函数来解决类别不平衡问题。2. 说话人独立SI的数据划分方案为保证模型对未见说话人的泛化能力我们采用说话人独立Speaker Independent的5折交叉验证策略。具体实现要点会话划分将5个session划分为5折每次留出1个session2位说话人作为测试集目录结构预处理后的数据应按以下结构组织IEMOCAP_processed/ ├── fold1/ │ ├── train/ │ │ ├── ang/ │ │ ├── hap/ │ │ ├── neu/ │ │ └── sad/ │ └── test/ │ ├── ang/ │ ├── hap/ │ ├── neu/ │ └── sad/ ├── fold2/ │ ...实现代码示例from sklearn.model_selection import KFold import shutil sessions [Session1, Session2, Session3, Session4, Session5] kf KFold(n_splits5) for fold, (train_idx, test_idx) in enumerate(kf.split(sessions), 1): # 创建目录结构 os.makedirs(fIEMOCAP_processed/fold{fold}/train, exist_okTrue) os.makedirs(fIEMOCAP_processed/fold{fold}/test, exist_okTrue) # 复制训练集数据 for idx in train_idx: session sessions[idx] for emotion in [ang, hap, neu, sad]: src fraw_data/{session}F/{emotion} dst fIEMOCAP_processed/fold{fold}/train/{emotion} shutil.copytree(src, dst, dirs_exist_okTrue) src fraw_data/{session}M/{emotion} shutil.copytree(src, dst, dirs_exist_okTrue) # 复制测试集数据同上略3. 音频特征提取全流程3.1 音频分段与预加重语音信号通常需要分割为固定长度的片段进行处理。我们采用2秒长度、1.6秒重叠的滑动窗口import numpy as np def segment_audio(waveform, sr16000, seg_length2.0, overlap1.6): 音频分段处理 参数 waveform: 原始音频波形 sr: 采样率默认16kHz seg_length: 分段长度秒 overlap: 重叠长度秒 返回 分段后的音频列表 seg_samples int(seg_length * sr) hop_samples int((seg_length - overlap) * sr) segments [] for start in range(0, len(waveform), hop_samples): end start seg_samples segment waveform[start:end] # 不足补零 if len(segment) seg_samples: segment np.pad(segment, (0, seg_samples - len(segment))) segments.append(segment) return segments预加重处理可增强高频分量补偿语音信号受到声门激励和口鼻辐射的影响def pre_emphasis(signal, coefficient0.97): 预加重处理 参数 signal: 输入信号 coefficient: 预加重系数通常0.9-1.0 返回 预加重后的信号 return np.append(signal[0], signal[1:] - coefficient * signal[:-1])3.2 梅尔频谱图生成梅尔频谱图是语音情感识别中最常用的特征表示之一其生成流程包括短时傅里叶变换STFT幅度平方计算梅尔滤波器组应用对数幅度转换完整实现代码import librosa import librosa.display import matplotlib.pyplot as plt def generate_mel_spectrogram(y, sr16000, n_fft1024, hop_length512, n_mels64): 生成梅尔频谱图 参数 y: 音频信号 sr: 采样率 n_fft: FFT窗口大小 hop_length: 帧移 n_mels: 梅尔带数量 返回 梅尔频谱图dB刻度 # 计算STFT stft librosa.stft(y, n_fftn_fft, hop_lengthhop_length) # 幅度平方 power np.abs(stft)**2 # 梅尔滤波器组 mel_basis librosa.filters.mel(sr, n_fft, n_melsn_mels) # 应用梅尔滤波器组 mel np.dot(mel_basis, power) # 转换为dB刻度 mel_db librosa.power_to_db(mel, refnp.max) return mel_db def save_spectrogram_image(mel_db, save_path): 保存梅尔频谱图为图像 plt.figure(figsize(3, 3)) librosa.display.specshow(mel_db, y_axismel, x_axistime) plt.axis(off) # 关闭坐标轴 plt.savefig(save_path, bbox_inchestight, pad_inches0) plt.close()3.3 批量处理与优化技巧实际处理大规模数据集时需要注意以下性能优化点并行处理使用multiprocessing或joblib加速内存管理及时清理不再需要的变量增量保存每处理完一个文件立即保存避免内存溢出优化后的批量处理代码框架from tqdm import tqdm from joblib import Parallel, delayed def process_single_file(wav_path, output_dir): try: # 加载音频 y, sr librosa.load(wav_path, sr16000) # 分段 segments segment_audio(y, sr) # 处理每个分段 for i, seg in enumerate(segments): # 预加重 seg pre_emphasis(seg) # 生成梅尔谱 mel_db generate_mel_spectrogram(seg, sr) # 保存图像 base_name os.path.basename(wav_path).replace(.wav, f_{i}.png) save_path os.path.join(output_dir, base_name) save_spectrogram_image(mel_db, save_path) except Exception as e: print(fError processing {wav_path}: {str(e)}) def batch_process(input_dir, output_dir, n_jobs4): 批量处理目录下的所有音频文件 wav_files [] for root, _, files in os.walk(input_dir): for f in files: if f.endswith(.wav): wav_files.append(os.path.join(root, f)) # 创建输出目录 os.makedirs(output_dir, exist_okTrue) # 并行处理 Parallel(n_jobsn_jobs)( delayed(process_single_file)(wav, output_dir) for wav in tqdm(wav_files) )4. 常见问题与解决方案在实际预处理过程中开发者常会遇到下典型问题音频长度不一致解决方案统一截断或补零建议先分析音频长度分布# 分析音频长度分布 durations [librosa.get_duration(filenamef) for f in wav_files] plt.hist(durations, bins50)梅尔谱图颜色范围不一致解决方案统一设置dB范围librosa.display.specshow(mel_db, vmin-20, vmax40)数据泄露风险关键点确保同一说话人的所有分段都在同一折训练或测试集存储空间不足优化策略调整图像分辨率通常64x64足够使用PNG压缩plt.savefig(..., dpi100, quality90)特征标准化最佳实践在训练集上计算均值和方差然后统一应用到所有数据train_mean np.mean(train_spectrograms) train_std np.std(train_spectrograms) normalized (spectrogram - train_mean) / train_std对于希望进一步优化模型性能的开发者可以尝试以下进阶技巧数据增强添加噪声、时间拉伸、音高变换多特征融合结合MFCC、chroma等特征注意力机制对重要时间段赋予更高权重
IEMOCAP数据集预处理实战:用Python和Librosa搞定语音情感识别的数据准备
IEMOCAP数据集预处理实战用Python和Librosa搞定语音情感识别的数据准备语音情感识别SER作为人机交互领域的重要研究方向其核心挑战之一是如何从原始音频中提取有效的特征表示。本文将手把手带你完成IEMOCAP数据集的预处理全流程从数据统计分析到梅尔频谱图生成为后续ResNet18等模型的训练打下坚实基础。1. IEMOCAP数据集解析与预处理策略IEMOCAPInteractive Emotional Dyadic Motion Capture是南加州大学收集的经典多模态情感数据集包含5个会话session中10位说话人5男5女的即兴表演和剧本朗读。原始数据中标注了9种情感标签但实际应用中通常采用四分类方案# 情感标签映射关系四分类方案 label_mapping { ang: 0, # 愤怒 exc: 1, # 兴奋与happy合并 hap: 1, # 快乐 neu: 2, # 中性 sad: 3 # 悲伤 }数据集分布存在明显不均衡问题各情感类别的样本数量如下表所示情感类别原始样本数处理后样本数ang11031103exchap16361636neu17081708sad10841084注意实际应用中建议对样本较少的类别进行过采样或采用加权损失函数来解决类别不平衡问题。2. 说话人独立SI的数据划分方案为保证模型对未见说话人的泛化能力我们采用说话人独立Speaker Independent的5折交叉验证策略。具体实现要点会话划分将5个session划分为5折每次留出1个session2位说话人作为测试集目录结构预处理后的数据应按以下结构组织IEMOCAP_processed/ ├── fold1/ │ ├── train/ │ │ ├── ang/ │ │ ├── hap/ │ │ ├── neu/ │ │ └── sad/ │ └── test/ │ ├── ang/ │ ├── hap/ │ ├── neu/ │ └── sad/ ├── fold2/ │ ...实现代码示例from sklearn.model_selection import KFold import shutil sessions [Session1, Session2, Session3, Session4, Session5] kf KFold(n_splits5) for fold, (train_idx, test_idx) in enumerate(kf.split(sessions), 1): # 创建目录结构 os.makedirs(fIEMOCAP_processed/fold{fold}/train, exist_okTrue) os.makedirs(fIEMOCAP_processed/fold{fold}/test, exist_okTrue) # 复制训练集数据 for idx in train_idx: session sessions[idx] for emotion in [ang, hap, neu, sad]: src fraw_data/{session}F/{emotion} dst fIEMOCAP_processed/fold{fold}/train/{emotion} shutil.copytree(src, dst, dirs_exist_okTrue) src fraw_data/{session}M/{emotion} shutil.copytree(src, dst, dirs_exist_okTrue) # 复制测试集数据同上略3. 音频特征提取全流程3.1 音频分段与预加重语音信号通常需要分割为固定长度的片段进行处理。我们采用2秒长度、1.6秒重叠的滑动窗口import numpy as np def segment_audio(waveform, sr16000, seg_length2.0, overlap1.6): 音频分段处理 参数 waveform: 原始音频波形 sr: 采样率默认16kHz seg_length: 分段长度秒 overlap: 重叠长度秒 返回 分段后的音频列表 seg_samples int(seg_length * sr) hop_samples int((seg_length - overlap) * sr) segments [] for start in range(0, len(waveform), hop_samples): end start seg_samples segment waveform[start:end] # 不足补零 if len(segment) seg_samples: segment np.pad(segment, (0, seg_samples - len(segment))) segments.append(segment) return segments预加重处理可增强高频分量补偿语音信号受到声门激励和口鼻辐射的影响def pre_emphasis(signal, coefficient0.97): 预加重处理 参数 signal: 输入信号 coefficient: 预加重系数通常0.9-1.0 返回 预加重后的信号 return np.append(signal[0], signal[1:] - coefficient * signal[:-1])3.2 梅尔频谱图生成梅尔频谱图是语音情感识别中最常用的特征表示之一其生成流程包括短时傅里叶变换STFT幅度平方计算梅尔滤波器组应用对数幅度转换完整实现代码import librosa import librosa.display import matplotlib.pyplot as plt def generate_mel_spectrogram(y, sr16000, n_fft1024, hop_length512, n_mels64): 生成梅尔频谱图 参数 y: 音频信号 sr: 采样率 n_fft: FFT窗口大小 hop_length: 帧移 n_mels: 梅尔带数量 返回 梅尔频谱图dB刻度 # 计算STFT stft librosa.stft(y, n_fftn_fft, hop_lengthhop_length) # 幅度平方 power np.abs(stft)**2 # 梅尔滤波器组 mel_basis librosa.filters.mel(sr, n_fft, n_melsn_mels) # 应用梅尔滤波器组 mel np.dot(mel_basis, power) # 转换为dB刻度 mel_db librosa.power_to_db(mel, refnp.max) return mel_db def save_spectrogram_image(mel_db, save_path): 保存梅尔频谱图为图像 plt.figure(figsize(3, 3)) librosa.display.specshow(mel_db, y_axismel, x_axistime) plt.axis(off) # 关闭坐标轴 plt.savefig(save_path, bbox_inchestight, pad_inches0) plt.close()3.3 批量处理与优化技巧实际处理大规模数据集时需要注意以下性能优化点并行处理使用multiprocessing或joblib加速内存管理及时清理不再需要的变量增量保存每处理完一个文件立即保存避免内存溢出优化后的批量处理代码框架from tqdm import tqdm from joblib import Parallel, delayed def process_single_file(wav_path, output_dir): try: # 加载音频 y, sr librosa.load(wav_path, sr16000) # 分段 segments segment_audio(y, sr) # 处理每个分段 for i, seg in enumerate(segments): # 预加重 seg pre_emphasis(seg) # 生成梅尔谱 mel_db generate_mel_spectrogram(seg, sr) # 保存图像 base_name os.path.basename(wav_path).replace(.wav, f_{i}.png) save_path os.path.join(output_dir, base_name) save_spectrogram_image(mel_db, save_path) except Exception as e: print(fError processing {wav_path}: {str(e)}) def batch_process(input_dir, output_dir, n_jobs4): 批量处理目录下的所有音频文件 wav_files [] for root, _, files in os.walk(input_dir): for f in files: if f.endswith(.wav): wav_files.append(os.path.join(root, f)) # 创建输出目录 os.makedirs(output_dir, exist_okTrue) # 并行处理 Parallel(n_jobsn_jobs)( delayed(process_single_file)(wav, output_dir) for wav in tqdm(wav_files) )4. 常见问题与解决方案在实际预处理过程中开发者常会遇到下典型问题音频长度不一致解决方案统一截断或补零建议先分析音频长度分布# 分析音频长度分布 durations [librosa.get_duration(filenamef) for f in wav_files] plt.hist(durations, bins50)梅尔谱图颜色范围不一致解决方案统一设置dB范围librosa.display.specshow(mel_db, vmin-20, vmax40)数据泄露风险关键点确保同一说话人的所有分段都在同一折训练或测试集存储空间不足优化策略调整图像分辨率通常64x64足够使用PNG压缩plt.savefig(..., dpi100, quality90)特征标准化最佳实践在训练集上计算均值和方差然后统一应用到所有数据train_mean np.mean(train_spectrograms) train_std np.std(train_spectrograms) normalized (spectrogram - train_mean) / train_std对于希望进一步优化模型性能的开发者可以尝试以下进阶技巧数据增强添加噪声、时间拉伸、音高变换多特征融合结合MFCC、chroma等特征注意力机制对重要时间段赋予更高权重