使用原始RAVDESS数据集训练语音情感识别模型遇librosa参数错误求助
解决RAVDESS原始数据集训练及预测问题
一、错误根源分析
你遇到的librosa.util.exceptions.ParameterError: Invalid shape for monophonic audio: ndim=2, shape=(172972, 2)错误,核心原因很明确:
- 教程使用的降采样RAVDESS子集已经将所有音频转为单声道(1通道);
- 而Zenodo上的原始RAVDESS数据集是立体声(2通道),代码中
X = sound_file.read(dtype="float32")读取后得到二维数组(shape为(采样点数, 2)),但librosa的音频处理函数(如stft、mfcc)默认要求输入单声道的一维数组,因此触发参数错误。
二、修复训练代码(适配原始数据集)
修改extract_feature函数,添加立体声转单声道的核心逻辑,同时优化参数传递避免潜在问题,完整代码如下:
import librosa import soundfile import os import glob import pickle import numpy as np from sklearn.model_selection import train_test_split from sklearn.neural_network import MLPClassifier from sklearn.metrics import accuracy_score from collections import Counter # 情感映射保持不变 emotions = { '01': 'neutral', '02': 'calm', '03': 'happy', '04': 'sad', '05': 'angry', '06': 'fearful', '07': 'disgust', '08': 'surprised' } observed_emotions = ['calm', 'happy', 'fearful', 'disgust'] def extract_feature(file_name, mfcc, chroma, mel): with soundfile.SoundFile(file_name) as sound_file: X = sound_file.read(dtype="float32") sample_rate = sound_file.samplerate # 关键修复:将立体声转为单声道(取两个通道的均值,也可直接取第一个通道X[:, 0]) if X.ndim > 1: X = np.mean(X, axis=1) # 可选但重要:统一采样率为RAVDESS原始的48kHz(避免预测时采样率不匹配) if sample_rate != 48000: X = librosa.resample(X, orig_sr=sample_rate, target_sr=48000) sample_rate = 48000 stft = np.abs(librosa.stft(X)) if chroma else None result = np.array([]) if mfcc: mfccs = np.mean(librosa.feature.mfcc(y=X, sr=sample_rate, n_mfcc=40).T, axis=0) result = np.hstack((result, mfccs)) if chroma: chroma = np.mean(librosa.feature.chroma_stft(S=stft, sr=sample_rate).T, axis=0) result = np.hstack((result, chroma)) if mel: # 显式指定y参数,避免librosa参数顺序歧义 mel = np.mean(librosa.feature.melspectrogram(y=X, sr=sample_rate).T, axis=0) result = np.hstack((result, mel)) return result def load_data(test_size=0.2): x, y = [], [] for file in glob.glob("C:\\Users\\raj.pandey\\Desktop\\speech-emotion-recognition\\Dataset\\Actor_*\\*.wav"): file_name = os.path.basename(file) emotion = emotions[file_name.split("-")[2]] if emotion not in observed_emotions: continue feature = extract_feature(file, mfcc=True, chroma=True, mel=True) x.append(feature) y.append(emotion) # 可选:打印训练集情感分布,检查是否均衡 print("训练集情感分布:", Counter(y)) return train_test_split(np.array(x), y, test_size=test_size, random_state=9) # 后续训练逻辑保持不变 x_train, x_test, y_train, y_test = load_data(test_size=0.20) # 添加class_weight='balanced'解决样本不均衡问题 model = MLPClassifier(alpha=0.01, batch_size=256, epsilon=1e-08, hidden_layer_sizes=(300,), learning_rate='adaptive', max_iter=500, class_weight='balanced') model.fit(x_train, y_train) y_pred = model.predict(x_test) accuracy = accuracy_score(y_true=y_test, y_pred=y_pred) print("Accuracy: {:.2f}%".format(accuracy * 100))
三、解决预测总是输出"fearful"的问题
这个问题通常由以下几个原因导致,对应解决方案:
1. 训练集情感分布不均衡
RAVDESS数据集的部分情感样本数可能偏少,导致模型偏向预测样本数量最多的类别(比如fearful)。
- 解决方案:我们已经在MLP初始化时添加了
class_weight='balanced'参数,让模型自动调整类别权重;也可以手动进行过采样/欠采样来平衡数据集。
2. 预测音频与训练数据格式不匹配
- 确保预测音频的采样率为48kHz(和训练数据一致),上面的
extract_feature函数已经添加了自动重采样逻辑; - 确保预测音频是单声道(函数也会自动处理);
- 避免使用情感表达不明显的TTS音频测试,建议先用RAVDESS数据集中已知情感的文件验证模型是否准确。
3. 模型训练不充分
可以尝试调整MLP的参数优化效果:
- 增加
hidden_layer_sizes(比如改为(500, 200)); - 提高
max_iter(比如改为1000); - 调整
alpha值(正则化参数)防止过拟合。
四、测试预测功能
修改后的代码可以直接处理.wav格式的预测文件,包括原始RAVDESS的立体声文件和转换后的音频:
# 测试预测 tar_file = "C:\\Users\\raj.pandey\\Desktop\\speech-emotion-recognition\\Dataset\\newactor\\pls-hold-while-try.wav" new_feature = extract_feature(tar_file, mfcc=True, chroma=True, mel=True) z_pred = model.predict(np.array([new_feature])) print("预测结果: ", z_pred)
内容的提问来源于stack exchange,提问作者El_Dorado




