检查目标时出错:预期 dense_3 的形状为 (3,) 但得到的数组的形状为 (1,)

Posted

技术标签:

【中文标题】检查目标时出错:预期 dense_3 的形状为 (3,) 但得到的数组的形状为 (1,)【英文标题】:Error when checking target: expected dense_3 to have shape (3,) but got array with shape (1,) 【发布时间】:2018-08-29 18:49:25 【问题描述】:

我正在使用来自 Places205 的 3 个类子集在 Keras 中训练类似 VGG16 的模型,但遇到以下错误:

ValueError: Error when checking target: expected dense_3 to have shape (3,) but got array with shape (1,)

我阅读了多个类似的问题,但到目前为止没有一个对我有帮助。错误出现在最后一层,我放了 3,因为这是我现在正在尝试的类数。

代码如下:

import keras from keras.datasets
import cifar10 from keras.preprocessing.image 
import ImageDataGenerator from keras.models 
import Sequential 
from keras.layers import Dense, Dropout, Activation, Flatten from keras.layers import Conv2D, MaxPooling2D 
from keras import backend as K import os


# Constants used  
img_width, img_height = 224, 224  
train_data_dir='places\\train'  
validation_data_dir='places\\validation'  
save_filename = 'vgg_trained_model.h5'  
training_samples = 15  
validation_samples = 5  
batch_size = 5  
epochs = 5


if K.image_data_format() == 'channels_first':
    input_shape = (3, img_width, img_height) else:
    input_shape = (img_width, img_height, 3)

model = Sequential([
    # Block 1
    Conv2D(64, (3, 3), activation='relu', input_shape=input_shape, padding='same'),
    Conv2D(64, (3, 3), activation='relu', padding='same'),
    MaxPooling2D(pool_size=(2, 2), strides=(2, 2)),
    # Block 2
    Conv2D(128, (3, 3), activation='relu', padding='same'),
    Conv2D(128, (3, 3), activation='relu', padding='same'),
    MaxPooling2D(pool_size=(2, 2), strides=(2, 2)),
    # Block 3
    Conv2D(256, (3, 3), activation='relu', padding='same'),
    Conv2D(256, (3, 3), activation='relu', padding='same'),
    Conv2D(256, (3, 3), activation='relu', padding='same'),
    MaxPooling2D(pool_size=(2, 2), strides=(2, 2)),
    # Block 4
    Conv2D(512, (3, 3), activation='relu', padding='same'),
    Conv2D(512, (3, 3), activation='relu', padding='same'),
    Conv2D(512, (3, 3), activation='relu', padding='same'),
    MaxPooling2D(pool_size=(2, 2), strides=(2, 2)),
    # Block 5
    Conv2D(512, (3, 3), activation='relu', padding='same',),
    Conv2D(512, (3, 3), activation='relu', padding='same',),
    Conv2D(512, (3, 3), activation='relu', padding='same',),
    MaxPooling2D(pool_size=(2, 2), strides=(2, 2)),
    # Top
    Flatten(),
    Dense(4096, activation='relu'),
    Dense(4096, activation='relu'),
    Dense(3, activation='softmax') ])

model.summary()

model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

# no augmentation config train_datagen = ImageDataGenerator() validation_datagen = ImageDataGenerator()
     train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')

validation_generator = validation_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')

model.fit_generator(
    train_generator,
    steps_per_epoch=training_samples // batch_size,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps=validation_samples // batch_size)

model.save_weights(save_filename)

【问题讨论】:

我倾向于相信输入训练数据可能是这里的罪魁祸首。您能否包括训练数据的大小,也可以包括错误堆栈跟踪中的行吗? @putonspectacles,数据为 256x256,导致错误的行是“validation_steps=validation_samples // batch_size)” 【参考方案1】:

问题在于您的标签数据形状。在多类别问题中,您要预测每个可能类别的概率,因此必须提供 (N, m) 形状的标签数据,其中 N 是训练示例的数量,m 是可能类别的数量(在您的情况下为 3) .

Keras 需要 (N, 3) 形状的 y 数据,而不是您可能提供的 (N,),这就是它引发错误的原因。

使用例如OneHotEncoder 将您的标签数据转换为 one-hot 编码形式。

【讨论】:

【参考方案2】:

正如其他人所提到的,Keras 期望在多类问题中使用“one hot”编码。

Keras 带有一个方便的功能来重新编码标签:

print(train_labels)
[1. 2. 2. ... 1. 0. 2.]

print(train_labels.shape)
(2000,)

使用to_categorical 重新编码标签以获得正确的输入形状:

from keras.utils import to_categorical
train_labels = to_categorical(train_labels)

print(train_labels)
[[0. 1. 0.]
 [0. 0. 1.]
 [0. 0. 1.]
 ...
 [0. 1. 0.]
 [1. 0. 0.]
 [0. 0. 1.]]

print(train_labels.shape)
(2000, 3)  # viz. 2000 observations, 3 labels as 'one hot'

在多类中更改/检查的其他重要事项(与二元分类相比):

generator() 函数中设置class_mode='categorical'

别忘了last密集层必须指定标签(或类)的数量:

model.add(layers.Dense(3, activation='softmax'))

确保选择activation=loss= 以适应多类问题,通常这意味着activation='softmax'loss='categorical_crossentropy'

【讨论】:

我的问题得到了解决,因为我错误地为最后一个密集层提供了输出形状。太感谢了! (二进制分类是 3 而不是 2)【参考方案3】:

有同样的问题。要解决这个问题,您可以简单地将validation_generator 和train_generator 中的类模式从“二进制”更改为“分类”——这是因为你有3 个类——它们不是二进制的。

【讨论】:

【参考方案4】:

问题:预期dense_3 的形状为(3,),但数组的形状为(1,)

如果您使用它进行分类,那么添加密集层的参数中的变量数量应该是正确的。

variables_for_classification=5 #change it as per your number of categories
model.add(Dense(variables_for_classification, activation='softmax'))

model.fit(X_train, Y_train, epochs=epochs, batch_size=batch_size,validation_split=0.1,callbacks=[EarlyStopping(monitor='val_loss', patience=3, min_delta=0.0001)])

为了更清楚。 当我使用 LSTM 预测新闻的类别时,类别是 5-商业、科技、政治、体育、娱乐

在我输入 5 的那个密集函数中,它工作正常。

【讨论】:

【参考方案5】:

这样做的原因是您会在 fit_generator() 方法中使用 'binary' class_mode 来解决多类问题。将其更改为“分类”,错误就会消失。

【讨论】:

fit_generator() 没有关键字参数 'class_mode',我认为您的意思是 flow_from_directory() 【参考方案6】:

如果出现这些错误,您只需指定最后一个类的编号 > 例如,您有 6 个类,您必须这样做:

model.add(Dense(6, activation='softmax'))

你可以用这个

num_classes=...

最后一层是

model.add(Dense(num_classes, activation='softmax'))

【讨论】:

直接传递值或通过变量传递值有什么区别?没有,所以显然不是问题。【参考方案7】:

我也遇到了同样的错误,并通过将class_mode 设置为categorical 而不是binary 来解决它

【讨论】:

【参考方案8】:

问题在于数据“Y”的标签形状。 标签的形状是 (m,),这不适用于:

loss = "binary_crossentropy"

我相信如果你不想玩标签的形状,那么使用:

loss = "sparse_categorical_crossentropy"

【讨论】:

【参考方案9】:

对我来说,这很有效。

from keras.utils import to_categorical

num_labels=10 #for my case

train_labels=to_categorical(train_labels,10)
test_labels=to_categorical(test_labels,10)

在分类编码我的标签时指定标签的数量作为参数有助于在我的训练集上进行有效的训练。

【讨论】:

以上是关于检查目标时出错:预期 dense_3 的形状为 (3,) 但得到的数组的形状为 (1,)的主要内容,如果未能解决你的问题,请参考以下文章

检查目标时出错:预期 dense_24 有 3 个维度,但得到了形状为 (3283, 1) 的数组

图像分类器ValueError:检查目标时出错:预期dense_31有2维,但得到的数组形状为(1463、224、224、3)

ValueError:检查目标时出错:预期dense_6的形状为(46,),但数组的形状为(1,)

值错误:检查目标时出错:预期dense_1具有形状(无,1)但得到的数组具有形状(6000,3)

ValueError:检查目标时出错:预期dense_4的形状为(4,)但得到的数组形状为(1,)

ValueError:检查时出错:预期dense_1_input的形状为(3,),但得到的数组形状为(1,)