数值错误:顺序层的输入与该层不兼容:期望最小维度为4,发现维度为2。完整形状接收到:[无,2584]。

13

我正在从一个音频项目中分离出人声部分。我使用了DSD100数据集,但为了进行测试,我使用了仅包含混音和人声的DSD100subset 数据集。我基于这篇文章进行工作。

首先,我处理音频以提取频谱图,并将其放入列表中,其中所有音频形成四个列表(trainMixed、trainVocals、testMixed、testVocals)。如下:

def to_spec(wav, n_fft=1024, hop_length=256):
    return librosa.stft(wav, n_fft=n_fft, hop_length=hop_length)

def prepareData(filename, sr=22050, hop_length=256, n_fft=1024):
  audio_wav = librosa.load(filename, sr=sr, mono=True, duration=30)[0]
  audio_spec=to_spec(audio_wav, n_fft=n_fft, hop_length=hop_length)
  audio_spec_mag = np.abs(audio_spec)
  maxVal = np.max(audio_spec_mag)

  return audio_spec_mag, maxVal


# FOR EVERY LIST (trainMixed, trainVocals, testMixed, testVocals)
trainMixed = []
trainMixedNum = 0
for (root, dirs, files) in walk('./Dev-subset-mix/Dev/'):
  for d in dirs:
    filenameMix = './Dev-subset-mix/Dev/'+d+'/mixture.wav'
    spec_mag, maxVal = prepareData(filenameMix, n_fft=1024, hop_length=256)
    trainMixed.append(spec_mag/maxVal)

接下来我构建模型:

import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D
from keras.optimizers import SGD
from keras.layers.advanced_activations import LeakyReLU

model = Sequential()
model.add(Conv2D(16, (3,3), padding='same', input_shape=(513, 25, 1)))
model.add(LeakyReLU())
model.add(Conv2D(16, (3,3), padding='same'))
model.add(LeakyReLU())
model.add(MaxPooling2D(pool_size=(3,3)))
model.add(Dropout(0.25))
model.add(Conv2D(16, (3,3), padding='same'))
model.add(LeakyReLU())
model.add(Conv2D(16, (3,3), padding='same'))
model.add(LeakyReLU())
model.add(MaxPooling2D(pool_size=(3,3)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(64))
model.add(LeakyReLU())
model.add(Dropout(0.5))
model.add(Dense(1, activation='sigmoid'))
sgd = SGD(lr=0.001, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss=keras.losses.binary_crossentropy, optimizer=sgd, metrics=['accuracy'])

运行模型:

model.fit(trainMixed, trainVocals,epochs=10, validation_data=(testMixed, testVocals))

但我得到的结果是:

ValueError: in user code:

    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:806 train_function  *
        return step_function(self, iterator)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:796 step_function  **
        outputs = model.distribute_strategy.run(run_step, args=(data,))
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:1211 run
        return self._extended.call_for_each_replica(fn, args=args, kwargs=kwargs)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:2585 call_for_each_replica
        return self._call_for_each_replica(fn, args, kwargs)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:2945 _call_for_each_replica
        return fn(*args, **kwargs)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:789 run_step  **
        outputs = model.train_step(data)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:747 train_step
        y_pred = self(x, training=True)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/base_layer.py:976 __call__
        self.name)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/input_spec.py:158 assert_input_compatibility
        ' input tensors. Inputs received: ' + str(inputs))

    ValueError: Layer sequential_1 expects 1 inputs, but it received 2 input tensors. Inputs received: [<tf.Tensor 'IteratorGetNext:0' shape=(None, 2584) dtype=float32>, <tf.Tensor 'IteratorGetNext:1' shape=(None, 2584) dtype=float32>]

我对这个主题比较陌生,提前感谢您的帮助。


每个处理过的音频都有这样的形状:(513,2584) - Jorge Ramón
请[编辑]您的问题,添加一些解释或代码,而不是像您现在这样使用注释。 - help-info.de
2个回答

12

可能是指定输入数据到Keras的fit()函数时出了问题。我建议像这样使用tf.data.Dataset作为fit()的输入:

这可能是由于在Keras的fit()函数中指定输入数据时出现了问题。我建议使用tf.data.Dataset作为fit()的输入,例如:

import tensorflow as tf

train_data = tf.data.Dataset.from_tensor_slices((trainMixed, trainVocals))
valid_data = tf.data.Dataset.from_tensor_slices((testMixed, testVocals))

model.fit(train_data, epochs=10, validation_data=valid_data)

然后,您还可以在TF数据集上使用shuffle()batch()等函数。

编辑:似乎您的输入形状不正确。您为第一层卷积层指定的input_shape(513, 25, 1),因此输入应该是一个批张量,其形状为(batch_size, 513, 25, 1),而您正在输入形状(batch_size, 2584)。因此,您需要重新整形和剪切输入以符合指定的形状,或者指定新形状。


1
嗨,感谢您的帮助。我尝试了您的代码,但错误变成了:ValueError: Input 0 of layer sequential is incompatible with the layer: : expected min_ndim=4, found ndim=2. Full shape received: [513, 2584] - Jorge Ramón
我已经更新了我的回答。问题在于形状不兼容,因此您需要将输入转换为Conv2D层所期望的形状。(513, 25, 1)的形状是从哪里来的? - Aaron Keesing
哦,是的,我忘了切片输入数据成那个形状的,谢谢回复。 - Jorge Ramón
你能否添加一些上下文信息,解释一下为什么要做出这个建议?将它们转换为 tf.data.Dataset 是如何解决问题的?作为一个对Tensorflow/Keras有点新的人,我正在努力理解它。谢谢。 - Danny Bullis
1
根据我的经验,使用TensorFlow数据管道可以最小化由于在NumPy数组、Python对象和张量之间进行转换而导致的不兼容性问题,同时还可用于异步操作数据和使用多个工作器等操作。 - Aaron Keesing

4

基本上,无论您如何定义Conv2D的形状是2D、3D等等,当您将输入X馈送给它时,它都需要4D,其中X.shape看起来像这样(batch,row,col,channel)。

下面的示例是关于Conv2D的澄清。

input_layer= layers.InputLayer(input_shape=(2,2,1))
conv1 = layers.Conv2D(3,(2,2))
X= np.ones((2,2))
X =X.reshape(1,X.shape[0],X.shape[1],1) # shape of X is 4D, (1, 2, 2, 1) 
conv1(input_layer(X))

简而言之:

现在让我们详细说明上述代码。

第1行定义了形状为3D的input_layer,但是在第4行中,X被重塑为4D形状,这根本不匹配。然而,为了将任何输入X馈送到input_layerConv2D中,必须将其传递为4D形状。


1
输入必须是4D形状,官方TF/Keras文档中是否有这样的声明?还是这是一种大家必须遵循的不成文规定? - akalanka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接