Keras ValueError:形状(32、2)和(32、4)不兼容

时间:2020-06-29 17:34:26

标签: python tensorflow machine-learning keras deep-learning

我刚刚发布了另一个使用相同代码的问题,但是由于我对自己的工作了解得很少,所以进展非常缓慢。上一个问题的链接在这里: Keras ValueError: No gradients provided for any variable

我目前正在尝试运行我的模型,以便对5000个不同的事件进行分类,这些事件是29x29值的2D numpy数组

我这样定义我的NN:

inputs = keras.Input(shape=(29,29,1))

x=inputs

x = keras.layers.Conv2D(16, kernel_size=(3,3), name='Conv_1')(x)
x = keras.layers.LeakyReLU(0.1)(x)      
x = keras.layers.MaxPool2D((2,2), name='MaxPool_1')(x)

x = keras.layers.Conv2D(16, kernel_size=(3,3), name='Conv_2')(x)
x = keras.layers.LeakyReLU(0.1)(x)
x = keras.layers.MaxPool2D((2,2), name='MaxPool_2')(x)

x = keras.layers.Conv2D(32, kernel_size=(3,3), name='Conv_3')(x)
x = keras.layers.LeakyReLU(0.1)(x)
x = keras.layers.MaxPool2D((2,2), name='MaxPool_3')(x)
x = keras.layers.Flatten(name='Flatten')(x)

x = keras.layers.Dense(64, name='Dense_1')(x)
x = keras.layers.ReLU(name='ReLU_dense_1')(x)
x = keras.layers.Dense(64, name='Dense_2')(x)
x = keras.layers.ReLU(name='ReLU_dense_2')(x)

outputs = keras.layers.Dense(4, activation='softmax', name='Output')(x)

model = keras.Model(inputs=inputs, outputs=outputs, name='VGGlike_CNN')
model.summary()

keras.utils.plot_model(model, show_shapes=True)

OPTIMIZER = tf.keras.optimizers.Adam(learning_rate=LR_ST)

model.compile(optimizer=OPTIMIZER,
              loss='categorical_crossentropy',
              metrics=['accuracy'],
              run_eagerly=False)

def lr_decay(epoch):
  if epoch < 10:
    return LR_ST
  else:
    return LR_ST * tf.math.exp(0.2 * (10 - epoch))

lr_scheduler = keras.callbacks.LearningRateScheduler(lr_decay)


model_checkpoint = keras.callbacks.ModelCheckpoint(
        filepath='mycnn_best',
        monitor='val_accuracy',
        save_weights_only=True, 
        save_best_only=True,
        save_freq='epoch')

callbacks = [ lr_scheduler, model_checkpoint ]    

print('X_train.shape = ',X_train.shape)

history = model.fit(X_train, Y_train epochs=50,
                    validation_data=X_test, shuffle=True, verbose=1,
                    callbacks=callbacks)

它现在给我一个错误:ValueError:形状(32,2)和(32,4)不兼容。

我想对每个具有1,2,3或4个簇的事件进行分类,但是在处理复杂的事物之前,我使用的事件只有1个簇,因此每个事件的标签为1

所有这些使我想到问题在于我的输出是4个神经元,但我真的不知道这是否成立,也不知道如何调试代码。

如果有人能帮助我,我将非常感激。

2 个答案:

答案 0 :(得分:1)

问题来自标签形状和模型输出形状之间的差异。由于您使用的是categorical_crossentropy,并且输出层有4个单位,因此您的模型期望标签采用一种热编码形式,并且是长度为4的向量。但是,标签是长度为2的向量。因此,标签是整数,你可以做

Y_train = tf.one_hot(Y_train, 4)

,结果形状将为(5000, 4)

答案 1 :(得分:1)

您的model.summary()清楚地显示了模型在每个步骤中的期望。特别是,您的模型需要的数据看起来像(batch_size,29,29,1)并输出看起来像(batch_size,4)的数据。如果您的标签数据不是(batch_size,4)格式,那么如果将这些数据与损失函数进行比较,则会产生错误。

不清楚如何标记数据。您说某些数据被标记为“ 1”。不确定那是什么意思。可以通过以下两种方式之一标记数据:

A -> 0
B -> 1
C -> 2
D -> 1

A -> (1,0,0)
B -> (0,1,0)
C -> (0,0,1)
D -> (0,1,0)

第二组称为标签的“一种热编码”。如果您使用“ sparse_categorical_crossentropy”损失函数,并且标签是整数(从0开始),Keras将自动对标签进行热编码。如果您自己手动对数据进行热编码,那么您将改为使用“ categorical_crossentropy”损失函数(听起来您可能已经这样做了)。

这些标记方法之间的差异来自于这样的事实,即标签不可避免地将整数放置在一个连续体上。例如,标签“ 2”比标签“ 0”更靠近标签“ 1”。因此,该算法自然不会认为标签“ 2”(对于“ 1”)和标签“ 2”(对于“ 0”)一样糟糕。通过对所有数据进行“一次热编码”,我们使所有标签之间的距离相等,因此标签之间没有偏爱。

我总是建议您对随机数据进行测试,以确保一切正常。例如,

import numpy as np
from tensorflow import keras

X = np.random.random((10000,29,29,1))
Y = np.random.randint(0,4,size=10000)
Y = keras.utils.to_categorical(Y)

print(f"Input: {X.shape}, Output: {Y.shape}")

model = keras.models.Sequential([
    keras.layers.Conv2D(16,(3,3),activation=keras.layers.LeakyReLU(0.1)),
    keras.layers.MaxPool2D((2,2)),
    keras.layers.Conv2D(16,(3,3),activation=keras.layers.LeakyReLU(0.1)),
    keras.layers.MaxPool2D((2,2)),
    keras.layers.Conv2D(32,(3,3),activation=keras.layers.LeakyReLU(0.1)),
    keras.layers.MaxPool2D((2,2)),
    keras.layers.Flatten(),
    keras.layers.Dense(64,'relu'),
    keras.layers.Dense(64,'relu'),
    keras.layers.Dense(4,'softmax'),
])

model.compile('adam','categorical_crossentropy')
model.fit(X,Y)