Python 检查目标时出错:预期密集_3具有形状(3),但获得具有形状(1)的数组

Python 检查目标时出错:预期密集_3具有形状(3),但获得具有形状(1)的数组,python,python-3.x,tensorflow,keras,Python,Python 3.x,Tensorflow,Keras,我正在Keras中培训一个类似VGG16的模型,使用Places205中的3个类子集,遇到以下错误: ValueError: Error when checking target: expected dense_3 to have shape (3,) but got array with shape (1,) 我读了很多类似的文章,但到目前为止没有一篇对我有帮助。错误出现在最后一层,我在那里放了3,因为这是我现在正在尝试的类的数量 代码如下: import keras from keras.

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

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)

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

Keras希望y数据是(N,3)形状,而不是(N,)如您可能提供的那样,这就是它产生错误的原因


使用例如将标签数据转换为一种热编码形式。

也有同样的问题。要解决这个问题,您只需在validation_generator中更改,并将类模式从“binary”训练为“Category”——这是因为您有3个非二进制的类。

如其他人所述,Keras希望在多类问题中使用“one hot”编码

Keras提供了一个方便的重新编码标签的功能:

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

print(train_labels.shape)
(2000,)
使用
对标签重新编码,以获得正确的输入形状:

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'
在多类中更改/检查的其他重要内容(与二进制分类相比):

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

print(train_labels.shape)
(2000,)
generator()
函数中设置
class\u mode='classifical'

不要忘记,最后一个密集层必须指定标签(或类)的数量:


确保选择了
activation=
loss=
以适合多类问题,通常这意味着
activation='softmax'
loss='classifical\u crossentropy'
问题:预期稠密的\u 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时,它工作正常。

这样做的原因是,对于多类问题,您应该在fit_generator()方法中使用“binary”class_模式。将其更改为“分类”,错误就会出现。

如果以这些错误为例,您只需要指定最后一个类的数量>作为示例,您有6个类,您必须这样做:

model.add(Dense(6, activation='softmax'))
你可以用这个

num_classes=...
最后一层是

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

我还得到了相同的错误,并通过将
class\u模式设置为
category
而不是
binary
解决了它。问题在于数据“Y”的标签形状。
标签的形状为(m,),这不适用于:

loss = "binary_crossentropy"
我相信,如果您不想玩弄标签的形状,请使用:

loss = "sparse_categorical_crossentropy"
对我来说,这很有效

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)

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

我倾向于认为输入的训练数据可能是罪魁祸首。您可以包括训练数据的大小,也可以包括错误堆栈跟踪中的行吗?@putonspectacles,数据是256x256,导致错误的行是“validation\u steps=validation\u samples//batch\u size”。我的问题解决了,因为我错误地为最后一个密集层提供了输出形状。非常感谢你!(3而不是2表示二进制分类)fit_generator()没有关键字参数“class_mode”,我想你是指从_目录()开始的流,直接传递值或通过变量传递值有什么区别?没有,显然不是问题所在。