如何循环提取多音频文件MFCC特征并保存以输入CNN模型?
音频MFCC特征保存与CNN适配问题解决方案
一、解决MFCC数据无法全部保存的问题
你当前代码里每次循环都会用新的MFCC矩阵覆盖mfcc1变量,所以最后只能拿到最后一个文件的结果。要保存所有文件的MFCC,只需要初始化一个列表来逐个存储:
修改后的核心代码
import numpy as np # 初始化列表存储所有MFCC mfcc_list = [] # 同步收集对应年代标签(需根据你的文件名/元数据规则提取) labels = [] for file in audio_files: x, sr = librosa.load(file) # 计算MFCC mfcc = librosa.feature.mfcc(y=x, sr=22050) # 把当前MFCC加入列表 mfcc_list.append(mfcc) # 示例:假设文件名格式是"1980_songname.mp3",提取年代作为标签 # year = int(os.path.basename(file).split('_')[0]) # labels.append(year) # 统一所有MFCC的时间步长度(不同音频时长不同,MFCC时间步会不一致,CNN要求输入形状统一) max_time_steps = max([mfcc.shape[1] for mfcc in mfcc_list]) # 用补零方式统一形状,最终得到(样本数, 特征数, 时间步)的数组 mfcc_features = np.array([np.pad(mf, ((0,0), (0, max_time_steps - mf.shape[1])), mode='constant') for mf in mfcc_list])
二、你的两个疑问解答
1. 是否需要用CSV或数据框管理MFCC数据?
不需要必须用。如果只是为了给CNN提供训练特征,直接用numpy数组效率最高、处理速度更快。但如果需要同时管理元数据(比如歌曲名、年代、采样率等),用pandas数据框会更方便查看和筛选,这属于辅助管理手段,不是训练CNN的必要步骤。
2. numpy.ndarray格式的MFCC能否直接用于CNN?
可以,但需要调整维度适配CNN的输入要求:
- 常规CNN输入是4维张量:
(样本数, 特征数, 时间步, 通道数) - 当前得到的MFCC数组是
(样本数, 特征数, 时间步),需要增加一个单通道维度(音频为单通道):
# 增加通道维度,最终形状为(样本数, 20, max_time_steps, 1),20是librosa默认的MFCC特征数 mfcc_features = mfcc_features[..., np.newaxis]
调整后就可以直接输入到CNN模型中。
完整示例代码
import librosa import numpy as np import os from glob import glob from sklearn.preprocessing import minmax_scale audio_files = glob('/Users/wt56/Downloads/522 Dataset/*.mp3') # 初始化存储容器 mfcc_list = [] labels = [] # 遍历处理所有音频 for file in audio_files: print(f"处理文件: {file}") x, sr = librosa.load(file) # 计算MFCC mfcc = librosa.feature.mfcc(y=x, sr=22050) # 可选:归一化特征,提升模型训练稳定性 mfcc = minmax_scale(mfcc, axis=1) mfcc_list.append(mfcc) # 提取年代标签(请根据你的实际文件名规则修改) filename = os.path.basename(file) year = int(filename.split('_')[0]) labels.append(year) # 统一MFCC时间步长度 max_len = max(m.shape[1] for m in mfcc_list) # 补零统一形状 mfcc_features = np.array([np.pad(m, ((0,0), (0, max_len - m.shape[1])), mode='constant') for m in mfcc_list]) # 增加通道维度 mfcc_features = mfcc_features[..., np.newaxis] # 标签转numpy数组 labels = np.array(labels) # 查看最终数据形状 print(f"最终特征形状: {mfcc_features.shape}") print(f"标签形状: {labels.shape}")
内容的提问来源于stack exchange,提问作者wangowango
相关产品推荐
相关产品推荐

