Je travaille actuellement à la formation d'un modèle de type VGG16 à Keras, sur un sous-ensemble de 3 classes de Places205, et j'ai rencontré l'erreur suivante:
ValueError: Error when checking target: expected dense_3 to have shape (3,) but got array with shape (1,)
J'ai lu plusieurs numéros similaires, mais aucun ne m'a aidé jusqu'à présent. L'erreur est sur la dernière couche, où j'ai mis 3 parce que c'est le nombre de classes que j'essaie en ce moment.
Le code est le suivant:
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)
Le problème vient de votre forme de données d'étiquette. Dans un problème multiclass, vous prédisez la probabilité de chaque classe possible. Vous devez donc fournir des données d'étiquette sous la forme (N, m), où N est le nombre d'exemples d'apprentissage et m le nombre de classes possibles (3 dans votre cas). .
Keras s'attend à ce que les données y soient en forme (N, 3) et non pas (N,) comme vous l'avez probablement fourni, c'est pourquoi une erreur est générée.
Utilisez par exemple OneHotEncoder pour convertir vos données d'étiquette en une forme encodée à chaud.
Comme mentionné par d'autres, Keras s'attend à un encodage "à chaud" dans les problèmes multiclass.
Keras est livré avec une fonction pratique pour recoder les étiquettes:
print(train_labels)
[1. 2. 2. ... 1. 0. 2.]
print(train_labels.shape)
(2000,)
Recodez les étiquettes en utilisant to_categorical
Pour obtenir la forme correcte des entrées:
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'
Autres éléments importants à modifier/vérifier en multiclass (par rapport à la classification binaire):
Définissez class_mode='categorical'
Dans la (les) fonction (s) generator()
.
N'oubliez pas que la dernière couche dense doit spécifier le nombre d'étiquettes (ou de classes):
model.add(layers.Dense(3, activation='softmax'))
Assurez-vous que activation=
Et loss=
Sont choisis de manière à répondre aux problèmes multiclass, cela signifie généralement activation='softmax'
Et loss='categorical_crossentropy'
.
Avait le même problème. Pour résoudre le problème, vous pouvez simplement changer dans validation_generator et train_generator le mode de classe de "binaire" à "catégorique" - c'est parce que vous avez 3 classes, ce qui n'est pas binaire.
Problème: dense_3 devrait avoir une forme (3,) mais un tableau avec une forme (1,)
Si vous l'utilisez pour la classification, le nombre de variables doit être correct dans le paramètre permettant d'ajouter une couche dense.
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)])
Pour le rendre plus clair. Comme je me servais du LSTM pour prédire la catégorie de nouvelles et les catégories 5 à 5: affaires, technologie, politique, sports, divertissement
Dans cette fonction dense quand je mets 5 cela a fonctionné correctement.