我刚刚发布了另一个使用相同代码的问题,但是由于我对自己的工作了解得很少,所以进展非常缓慢。上一个问题的链接在这里: 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个神经元,但我真的不知道这是否成立,也不知道如何调试代码。
如果有人能帮助我,我将非常感激。
答案 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)