Ошибка при проверке цели: ожидается, что dense_3 будет иметь форму (3,), но получит массив с формой (1,)
Я работаю над подготовкой VGG16-подобной модели в Keras, на подмножестве 3-х классов от Places205 и обнаружил следующую ошибку:
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)
Ответы
Ответ 1
Проблема связана с вашей формой данных метки. В мультиклассовой задаче вы предсказываете вероятность каждого возможного класса, поэтому должны предоставить данные меток в форме (N, m), где N - количество обучающих примеров, а m - количество возможных классов (3 в вашем случае),
Keras ожидает, что y-данные имеют форму (N, 3), а не (N,), как вы, вероятно, указали, поэтому возникает ошибка.
Используйте, например, OneHotEncoder, чтобы преобразовать данные метки в горячо закодированную форму.
Ответ 2
Как уже упоминалось, Керас ожидает "горячего" кодирования в мультиклассовых задачах.
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'
Другие важные вещи, которые нужно изменить/проверить в мультиклассе (по сравнению с двоичной классификацией):
Установите class_mode='categorical'
в функции() generator()
.
Не забывайте, что последний плотный слой должен указывать количество меток (или классов):
model.add(layers.Dense(3, activation='softmax'))
Убедитесь, что activation=
и loss=
выбрана так, чтобы удовлетворить проблемы мультикласса, обычно это означает, что activation='softmax'
и loss='categorical_crossentropy'
activation='softmax'
loss='categorical_crossentropy'
.
Ответ 3
Имел ту же проблему. Чтобы решить проблему, вы можете просто изменить в validation_generator и train_generator режим класса от "двоичного" до "категоричного" - потому что у вас есть 3 класса, которые не являются двоичными.
Ответ 4
Проблема: ожидается, что плотность_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
У меня есть одно требование: нам нужно извлечь текст из изображения, конечно, мы знаем, что мы можем сделать с OpenCV, но это не дает таких хороших результатов для ясности. Я просто добавляю ссылку на изображение здесь, введите описание изображения здесь причина, чтобы загрузить изображение здесь, если вы можете наблюдать взлеты на этом изображении, мне нужно извлечь этот текст.
так может кто-нибудь помочь в этом
Ответ 6
Причина этого заключается в том, что вы использовали бы "двоичный" class_mode в методе fit_generator() для решения нескольких классов. Измените это на "категорическое", и ошибка исчезнет.
Ответ 7
если принять эти ошибки, вам просто нужно указать последний с номерами классов> в качестве примера у вас есть 6 классов, вам нужно сделать это:
model.add(Dense(6, activation='softmax'))
ты можешь использовать это
num_classes=...
и последние слои будут
model.add(Dense(num_classes, activation='softmax'))