我正在使用Places205在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)
答案 0 :(得分:8)
问题在于您的标签数据形状。在多类问题中,您正在预测每个可能类的可能性,因此必须提供(N,m)形状的标签数据,其中N是训练样本的数量,m是可能类的数量(在您的情况下为3)
Keras希望y数据采用(N,3)形状,而不是(N,),因为它可能会提供错误。这就是它引发错误的原因。
使用例如OneHotEncoder将您的标签数据转换为单热编码形式。
答案 1 :(得分:7)
有同样的问题。要解决该问题,您只需在validation_generator和train_generator中将类模式从“二进制”更改为“分类”,这是因为您有3个类(不是二进制)。
答案 2 :(得分:3)
问题:预期density_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时,它可以正常工作。
答案 3 :(得分:2)
这样做的原因是,您将在fit_generator()方法中使用“二进制” class_mode来解决多类问题。将其更改为“类别”,错误就会消失。
答案 4 :(得分:1)
如果遇到这些错误,您只需要用类编号指定最后一个>例如,您必须使用6个类:
model.add(Dense(6, activation='softmax'))
u可以使用
num_classes=...
最后一层将是
model.add(Dense(num_classes, activation='softmax'))
答案 5 :(得分:1)
我也遇到了同样的错误,并通过将class_mode
设置为categorical
而不是binary
来解决了该问题
答案 6 :(得分:1)
问题在于数据“ Y”的标签形状。
标签的形状为(m,),不适用于
<field name="vehicules" widget="one2many_list" context="{ 'default_problems':(6,0, problems)}">
我相信,如果您不想使用标签的形状,请使用:
loss = "binary_crossentropy"
答案 7 :(得分:0)
正如其他人所提到的,Keras期望在多类问题中使用“一个热门”编码。
Keras带有方便的功能来重新编码标签:
<?xml version="1.0" encoding="UTF-8"?>
<breakfast_menu>
<food>
<food>Belgian Waffles</food>
<price>$5.95</price>
<description>Two of our famous Belgian Waffles with plenty of real maple
syrup</description>
<calories>650</calories>
</food>
<food>
<food>Strawberry Belgian Waffles</food>
<price>$7.95</price>
<description>Light Belgian waffles covered with strawberries and whipped
cream</description>
<calories>900</calories>
</food>
<food>
<food>Berry-Berry Belgian Waffles</food>
<price>$8.95</price>
<description>Light Belgian waffles covered with an assortment of fresh
berries and whipped cream</description>
<calories>900</calories>
</food>
<food>
<food>French Toast</food>
<price>$4.50</price>
<description>Thick slices made from our homemade sourdough
bread</description>
<calories>600</calories>
</food>
<food>
<food>Homestyle Breakfast</food>
<price>$6.95</price>
<description>Two eggs, bacon or sausage, toast, and our ever-popular hash
browns</description>
<calories>950</calories>
</food>
</breakfast_menu>
使用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'
函数中设置class_mode='categorical'
。
别忘了 last 密集层必须指定标签(或类)的数量:
generator()
请确保选择model.add(layers.Dense(3, activation='softmax'))
和activation=
以适合多类问题,通常意味着loss=
和activation='softmax'
。
答案 8 :(得分:0)
对我来说,这行得通。
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)
在对标签进行分类编码时,指定标签的数量作为参数有助于在训练集上进行有效训练。