ValueError:形状 (None, 1) 和 (None, 2) 不兼容

Posted

技术标签:

【中文标题】ValueError:形状 (None, 1) 和 (None, 2) 不兼容【英文标题】:ValueError: Shapes (None, 1) and (None, 2) are incompatible 【发布时间】:2020-08-27 18:04:03 【问题描述】:

我正在训练一个面部表情(愤怒与快乐)模型。最后一个密集输出层以前是 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,
    
)

【问题讨论】:

好吧,如果你的输出是二进制的,你需要在最后一层使用 sigmoid 而不是 softmax 和 binary_crossentropy @Mike 我已经用 sigmoid 替换了 softmax 再次同样的错误 那么您是否将最后一个 Dense 层的参数从 2 调整为 1,因为只有一个输出变量? @Mike 我做到了,错误已消除,但预测的准确度始终为 60 %。 @Mike 哦,不,我没有,忘记了。我只是将其更改为 binary_crossentropy,它的工作精度为 90%。非常感谢你的帮助。我还是 keras 的新手。 【参考方案1】:

将分类交叉熵更改为二进制交叉熵,因为您的输出标签是二进制的。还要将 Softmax 更改为 Sigmoid,因为 Sigmoid 是二进制数据的正确激活函数

【讨论】:

您能否也添加关于使用正确激活函数的部分并附上解释?那么答案就完整了 太好了,赞成,@faiza 你能接受这个答案吗,因为这是解决你的错误的答案? loss='binary_crossentropy' activation='sigmoid' 这导致我另一个错误:ValueError: logits and labels must have the same shape ((None, 1) vs (None, 762)),与this SO question相关 检查@Muhammad Zakaria 的答案,它解决了“日志和标签错误”【参考方案2】:

您可以将标签从二进制值更改为分类值并继续使用相同的代码。例如,

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 激活函数的答案。

    分类交叉熵:
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'])
    二元交叉熵
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'])

【讨论】:

你能帮忙解决这个问题吗***.com/questions/68225332/…【参考方案3】:

即使我遇到了同样的问题,我在对我有用的 flow_from_directory 方法中更改了 class_mode='categorical' 而不是 class_mode='binary'

【讨论】:

【参考方案4】:

如果您的数据集使用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 答案是解决这类问题的好组合。 请注意第一个代码 sn-p 中的“分类”->“分类”。建议的编辑队列已满。【参考方案5】:

我也遇到了同样的问题 我的形状是

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"

它对我来说就像一个魅力

【讨论】:

【参考方案6】:

我自己也遇到了这个问题,就我而言,问题出在模型的声明中。我试图使用 VGG16 进行迁移学习,但我使用了错误的层来代替输出。我没有使用我创建的预测层,而是使用了另一个层。因此,如果您在遇到此错误时放错了任何层,请查看您的模型。

【讨论】:

【参考方案7】:

正如@Akash 指出的那样,应该将您的标签转换为一次性编码,如下所示:

y = keras.utils.to_categorical(y, num_classes=num_classes_in_your_case)

【讨论】:

以上是关于ValueError:形状 (None, 1) 和 (None, 2) 不兼容的主要内容,如果未能解决你的问题,请参考以下文章

ValueError:logits 和标签必须具有相同的形状 ((None, 23, 23, 1) vs (None, 1))

ValueError: 预期的 dense_1_input 具有形状 (None, 4) 但得到 (78,2)

ValueError:检查目标时出错:预期 model_2 的形状为 (None, 252, 252, 1) 但得到的数组的形状为 (300, 128, 128, 3)

ValueError:logits 和标签必须具有相同的形状

如何修复'ValueError:输入0与层simple_rnn_1不兼容:预期形状=(无,无,20),找到形状=(无,无,2,20)'

ValueError:尝试对 IMDB 评论进行分类时,logits 和标签必须具有相同的形状((无,1)与(无,10000))