我正在尝试通过使用音频文件的MFCC来提取.wav文件的特征。当我尝试将MFCC列表转换为numpy数组时,遇到了一个错误。我相当确定这个错误是由于列表中包含不同形状的MFCC值而发生的(但我不确定如何解决这个问题)。
我查看了StackOverflow上的另外两个帖子,但这些帖子无法解决我的问题,因为它们针对的是特定任务。
ValueError: 无法将输入数组从形状 (128,128,3) 广播到形状 (128,128)
Value Error: 无法将输入数组从形状 (857,3) 广播到形状 (857)
完整的错误信息:
Traceback (most recent call last): File “/…./…/…../Batch_MFCC_Data.py”, line 68, in X = np.array(MFCCs) ValueError: 无法将输入数组从形状 (20,590) 广播到形状 (20)
代码示例:
all_wav_paths = glob.glob('directory_of_wav_files/**/*.wav', recursive=True)np.random.shuffle(all_wav_paths)MFCCs = [] #用于存储所有MFCC的数组labels = [] #用于存储所有标签的数组for i, wav_path in enumerate(all_wav_paths): individual_MFCC = MFCC_from_wav(wav_path) #MFCC_from_wav() -> 返回MFCC系数 label = get_class(wav_path) #get_class() -> 返回.wav文件的标签,0或1 #将特征和标签添加到数组中 MFCCs.append(individual_MFCC) labels.append(label)#必须将训练数据转换为Numpy数组,以便进行#train_test_split和保存到本地驱动器X = np.array(MFCCs) #这一行会导致上述错误#对标签进行二进制编码onehot_encoder = OneHotEncoder(sparse=False)Y = onehot_encoder.fit_transform(labels)#创建训练/测试数据from sklearn.cross_validation import train_test_splitX_train, X_test, y_train, y_test = train_test_split(MFCCs, Y, test_size=0.25, random_state=0)#将数据保存到本地驱动器np.save("LABEL_SAVE_PATH", Y)np.save("TRAINING_DATA_SAVE_PATH", X)
这是MFCCs数组中.wav文件的MFCC形状的快照
MFCCs数组包含以下形状:
...更多在上面...(20, 423) #来自一个.wav文件的返回MFCC的形状(20, 457)(20, 1757)(20, 345)(20, 835)(20, 345)(20, 687)(20, 774)(20, 597)(20, 719)(20, 1195)(20, 433)(20, 728)(20, 939)(20, 345)(20, 1112)(20, 345)(20, 591)(20, 936)(20, 1161)....更多在下面....
如您所见,MFCCs数组中的MFCC形状各不相同,这是因为录音的时间长度不同。这是否是我无法将数组转换为numpy数组的原因?如果这是问题所在,我该如何解决这个问题,使整个MFCC数组具有相同的形状?
任何用于解决此问题的代码片段和建议将不胜感激!
谢谢!
回答:
使用以下逻辑将数组降采样到min_shape
,即将较大的数组减少到min_shape
min_shape = (20, 345)MFCCs = [arr1, arr2, arr3, ...] for idx, arr in enumerate(MFCCs): MFCCs[idx] = arr[:, :min_shape[1]]batch_arr = np.array(MFCCs)
然后,您可以将这些数组堆叠在一个批处理数组中,如下面的最小示例所示:
In [33]: a1 = np.random.randn(2, 3) In [34]: a2 = np.random.randn(2, 5) In [35]: a3 = np.random.randn(2, 10)In [36]: MFCCs = [a1, a2, a3]In [37]: min_shape = (2, 2)In [38]: for idx, arr in enumerate(MFCCs): ...: MFCCs[idx] = arr[:, :min_shape[1]] ...: In [42]: batch_arr = np.array(MFCCs)In [43]: batch_arr.shapeOut[43]: (3, 2, 2)
现在,对于第二种策略,将较小的数组上采样到max_shape
,遵循类似的逻辑,但用您喜欢的零或nan
值填充缺失的值。
然后,您可以再次将数组堆叠为形状为(num_arrays, dim1, dim2)
的批处理数组;因此,对于您的情况,形状应该是(num_wav_files, 20, max_column
)