数值错误:形状(无,1)和(无,2)不兼容。

65

我正在训练一个面部表情(愤怒 vs 快乐)模型。最后一个密集层的输出以前是1,但是当我预测一张图片时,它的输出总是1,准确率为64%。所以我改成了有2个输出的2。但现在我得到了这个错误:

Epoch 1/15

---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-54-9c7272c38dcb> in <module>()
     11     epochs=epochs,
     12     validation_data = val_data_gen,
---> 13     validation_steps = validation_steps,
     14 
     15 )

10 frames

/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/func_graph.py in wrapper(*args, **kwargs)
    966           except Exception as e:  # pylint:disable=broad-except
    967             if hasattr(e, "ag_error_metadata"):
--> 968               raise e.ag_error_metadata.to_exception(e)
    969             else:
    970               raise

ValueError: in user code:

    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:571 train_function  *
        outputs = self.distribute_strategy.run(
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:951 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:2290 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:2649 _call_for_each_replica
        return fn(*args, **kwargs)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:533 train_step  **
        y, y_pred, sample_weight, regularization_losses=self.losses)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/compile_utils.py:205 __call__
        loss_value = loss_obj(y_t, y_p, sample_weight=sw)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/losses.py:143 __call__
        losses = self.call(y_true, y_pred)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/losses.py:246 call
        return self.fn(y_true, y_pred, **self._fn_kwargs)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/losses.py:1527 categorical_crossentropy
        return K.categorical_crossentropy(y_true, y_pred, from_logits=from_logits)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/backend.py:4561 categorical_crossentropy
        target.shape.assert_is_compatible_with(output.shape)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/tensor_shape.py:1117 assert_is_compatible_with
        raise ValueError("Shapes %s and %s are incompatible" % (self, other))

    ValueError: Shapes (None, 1) and (None, 2) are incompatible

相关代码为:

    model = Sequential([
    Conv2D(32,3, activation='relu', input_shape=(48,48,1)),
    BatchNormalization(),
    MaxPooling2D(pool_size=(3, 3)),
  
    Flatten(),
    Dense(512, activation='relu'),
    Dense(2,activation='softmax')
])
model.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'])


model.summary()

Model: "sequential_4"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_6 (Conv2D)            (None, 46, 46, 32)        320       
_________________________________________________________________
batch_normalization_4 (Batch (None, 46, 46, 32)        128       
_________________________________________________________________
max_pooling2d_6 (MaxPooling2 (None, 15, 15, 32)        0         
_________________________________________________________________
flatten_4 (Flatten)          (None, 7200)              0         
_________________________________________________________________
dense_8 (Dense)              (None, 512)               3686912   
_________________________________________________________________
dense_9 (Dense)              (None, 2)                 1026      
=================================================================
Total params: 3,688,386
Trainable params: 3,688,322
Non-trainable params: 64
_________________________________________________________________


epochs = 15
steps_per_epoch = train_data_gen.n//train_data_gen.batch_size
validation_steps = val_data_gen.n//val_data_gen.batch_size



history = model.fit(
    x=train_data_gen,
    steps_per_epoch=steps_per_epoch,
    epochs=epochs,
    validation_data = val_data_gen,
    validation_steps = validation_steps,
    
)

5
对于这件事,如果您的输出是二进制,则需要在最后一层使用sigmoid而不是softmax,同时使用binary_crossentropy。 - Mike
2
@Mike,我已经将softmax替换为sigmoid,但仍然出现相同的错误。 - faiza rashid
4
你是否将最后一个密集层的参数从2调整为1,因为只有一个输出变量? - Mike
2
@Mike 我已经做了,错误已经解决了,但是预测始终是60%的准确率。 - faiza rashid
3
@Mike 哦不,我忘记了。我只是将其更改为binary_crossentropy,它的准确率达到了90%。非常感谢您的帮助。我对keras还很新。 - faiza rashid
显示剩余2条评论
8个回答

75

我曾经遇到同样的问题,我的形状是:

shape of X (271, 64, 64, 3)
shape of y (271,)
shape of trainX (203, 64, 64, 3)
shape of trainY (203, 1)
shape of testX (68, 64, 64, 3)
shape of testY (68, 1)

loss="categorical_crossentropy"

我把它改成了

loss="sparse_categorical_crossentropy"

对我来说,它像魔法一样奏效。


1
也适用于我,谢谢。 - Константин Прудников
22
如果您想使用“categorical_crossentropy”,则标签应该是one-hot编码的。当标签以整数形式给出时,需要更改为“sparse_categorical_crossentropy”。使用“categorical_crossentropy”的优点是它可以为您提供类概率,在某些情况下可能会有用。 - Sander N

73

由于您的输出标签是二进制的,请将分类交叉熵更改为二元交叉熵。同时,将 Softmax 更改为 Sigmoid,因为 Sigmoid 是二进制数据的适当激活函数。


1
你能否添加有关使用正确的激活函数及其解释的部分吗?这样答案就会更完整了。 - learner
2
太好了,已点赞。@faiza,请问您能否接受这个答案呢?因为它解决了您的错误。 - learner
3
loss='binary_crossentropy' 的意思是“二元交叉熵损失函数”,用于二分类问题中的模型训练。activation='sigmoid' 的意思是激活函数使用“sigmoid函数”,其将输入映射到0到1之间,常用于二分类问题中的输出层。 - gies0r
7
这导致了另一个错误:ValueError: logits and labels must have the same shape ((None, 1) vs (None, 762)),与此SO问题有关。 - gies0r
2
请检查 @Muhammad Zakaria 的答案,他解决了“logits and labels error”问题。 - Ajay Sant

31

如果使用了image_dataset_from_directory加载数据集,则需要使用label_mode='categorical'

train_ds = tf.keras.preprocessing.image_dataset_from_directory(
  path,
  label_mode='categorical'
)

或者使用flow_from_directoryflow_from_dataframe加载,然后使用class_mode='categorical'


train_ds = ImageDataGenerator.flow_from_directory(
  path,
  class_mode='categorical'
)

上面的答案对我有所帮助。这个答案和@mike的答案是一个很好的组合,可以思考如何解决这种问题。 - Raheel Shahzad
1
请注意第一个代码片段中的"categorial"应更改为"categorical"。 建议的编辑队列已满。 - Christopher Mills
标签模式不起作用,应该使用 class_mode - Engr Ali

10
你可以将标签从二进制值更改为分类值,并继续使用相同的代码。例如,
from keras.utils import to_categorical
one_hot_label = to_cateorical(input_labels)
# change to [1, 0, 0,..., 0]  --> [[0, 1], [1, 0], ..., [1, 0]]

您可以通过此链接更好地理解Keras API

如果您要使用用于两个类别的分类交叉熵,请使用softmax并进行一次热编码。对于二元分类,您可以像前面提到的那样使用sigmoid激活函数来使用二元交叉熵。

  1. 分类交叉熵:
model = Sequential([
    Conv2D(32,3, activation='relu', input_shape=(48,48,1)),
    BatchNormalization(),
    MaxPooling2D(pool_size=(3, 3)),

    Flatten(),
    Dense(512, activation='relu'),
    Dense(2,activation='softmax')  # activation change
])
model.compile(optimizer='adam',
              loss='categorical_crossentropy', # Loss
              metrics=['accuracy'])
  1. 二元交叉熵
model = Sequential([
    Conv2D(32,3, activation='relu', input_shape=(48,48,1)),
    BatchNormalization(),
    MaxPooling2D(pool_size=(3, 3)),

    Flatten(),
    Dense(512, activation='relu'),
    Dense(1,activation='sigmoid') #activation change
])
model.compile(optimizer='adam',
              loss='binary_crossentropy', # Loss
              metrics=['accuracy'])


你能帮忙解决这个问题吗?https://stackoverflow.com/questions/68225332/invalid-argument-in0-mismatch-in1-shape - user
这是对我有效的答案。应该被接受。 - Tim

6

在多标签分类的情况下,将'categorical_crossentropy'更换为'sparse_categorical_crossentropy'对我有用。


2
你是指 sparse_categorical_crossentropy 吗? - William Le

3
正如@Akash所指出的那样,应该将您的标签转换为单热编码,就像这样:
y = keras.utils.to_categorical(y, num_classes=num_classes_in_your_case)

3

我也遇到了同样的问题,我在flow_from_directory方法中使用class_mode='categorical'而不是class_mode='binary',这对我起作用了。


0
我自己也遇到了这个问题,在我的情况下,问题出在模型的声明上。我尝试使用VGG16进行迁移学习,但是我在输出层中使用了错误的层。我使用了另一个层而不是我创建的预测层。因此,当你遇到这个错误时,请检查你的模型是否错放了任何层。

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