Как решить Value Error в отношении обучения CNN - PullRequest
0 голосов
/ 23 октября 2019

ВЫПУСК:

Итак, у меня есть эта ошибка, которая случается, когда я пытаюсь обучить свой cnn.

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

И я не знаю, что это значит. этот код, кстати, не на 100% мой, я просто взял код CNN и изменил его, чтобы он соответствовал тому, что мне нужно. Хотя мои знания в области кодирования CNN очень ограничены, и у меня нет надлежащего обучения программированию на Python.

Может кто-нибудь объяснить мне, что происходит с ошибкой, и я хочу знать, что ее вызывает. И можете ли вы, ребята, сказать мне, что то, что я до сих пор делал над кодом, является правильным?

Я планирую создать CNN, который сможет классифицировать изображения, содержащие сексуальное содержание, насилие, ужасы, наркотики. Так что это мультикласс CNN с входным изображением, а выходной будет классифицировать категорию, к которой принадлежит изображение.

Вот остаток кода CNN:

from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Dense, Dropout, Flatten
from keras.callbacks import ModelCheckpoint

IMAGE_LENGHT = 300
EPOCH_COUNT = 10
MODEL_PATH = 'model.hdf5'
WEIGHTS_PATH = 'weights.hdf5'

model = Sequential()

model.add(Conv2D(32, (9, 9),  input_shape = (IMAGE_LENGHT,IMAGE_LENGHT, 3), activation = 'relu'))
model.add(MaxPooling2D(pool_size = (2, 2)))

model.add(Conv2D(32, (9, 9), activation = 'relu'))
model.add(MaxPooling2D(pool_size = (2, 2)))

model.add(Conv2D(64, (9, 9), activation = 'relu'))
model.add(MaxPooling2D(pool_size = (2, 2)))

model.add(Flatten())

model.add(Dense(64, activation = 'relu'))
model.add(Dropout(rate = 0.5))
model.add(Dense(32, activation = 'softmax'))

model.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['binary_accuracy'])

from keras.preprocessing.image import ImageDataGenerator

train_datagen = ImageDataGenerator()

test_datagen = ImageDataGenerator()

training_set = train_datagen.flow_from_directory(
        'TRAIN_SET',
        target_size = (IMAGE_LENGHT,IMAGE_LENGHT),
        batch_size = 100,
        class_mode = 'binary')

test_set = test_datagen.flow_from_directory(
        'TEST_SET',
        target_size = (IMAGE_LENGHT,IMAGE_LENGHT),
        batch_size = 100,
        class_mode = 'binary')

checkpoint = ModelCheckpoint(WEIGHTS_PATH, monitor='val_acc', verbose=1, save_best_only=True, mode='max')
model.fit_generator(
        training_set,
        steps_per_epoch=60,
        epochs = EPOCH_COUNT,
        validation_data = test_set,
        validation_steps =20,
        callbacks = [checkpoint])
model.save(MODEL_PATH, True, True)

Любая помощьбыть оцененным! Спасибо!

Ответы [ 2 ]

0 голосов
/ 23 октября 2019

Ваш последний слой состоит из 32 единиц, и вы используете Softmax. Таким образом, вы должны иметь более 2 классов. Нейронная сеть ожидает цель из 32 измерений, поэтому вам придется в одно касание кодировать форму цели (1,), выполнив:

import pandas as pd
y_train=pd.get_dummies(target)

После этого проверьте размерность данных (количество классов) поrunning:

y_train.shape[1]

Это выходное измерение - это количество классов в целевой переменной. Таким образом, у вас будет:

model.add(Dense(y_train.shape[1], activation = 'softmax'))

Я бы также изменил:

metrics = ['accuracy']

Если у вас действительно есть двоичная цель, последний уровень должен быть:

model.add(Dense(2, activation = 'sigmoid'))

В этом случае вы также должны в горячем виде кодировать целевую переменную в (batch_size,number_classes).

0 голосов
/ 23 октября 2019

Причина здесь

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

и здесь

class_mode = 'binary'

Причиной ошибки является то, что вашей модели требуется, чтобы выходная форма была (batch_size, 32), но по class_mode = 'binary' вы получилитолько (batch_size, 1).

Во-первых, вам нужно знать, сколько классов составляют ваши изображения, сколько папок в TRAIN_SET в этом случае, и поместить его в Dense(). Например, если у вас есть 7 классов, тогда вам понравится

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

и изменится class_mode = 'binary' на class_mode = 'categorical'. Для классификации нескольких классов вы не можете маркировать как 0 это собака 1 это кошка 2 это утка и 3 это лошадь, вы не можете разрезать утку пополам и получить кошку или минус лошадьна лошади и получить собаку. Вам нужна кодировка one-hot.

Во-вторых, о классах binary, если ваши данные только о 2 классах, таких как кошка и собака, тогда вы можете просто получить ответ модели, как "это изображение собака"тогда, если это правда, это собака или если это ложь, это кошка.

В этом случае вы можете использовать

model.add(Dense(1, activation = 'sigmoid'))  # beware, it's 'sigmoid' here, not 'softmax'
model.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])  # binary_crossentropy here, not categorical

и

class_mode = 'binary'

Редактировать

Один горячий похож, позволяетопределите наркотики = 0, ужас = 1, насилие = 2 и сексуальное = 3, если ответ violence, тогда целевые данные будут [0, 0, 1, 0]. Модель будет предсказывать как [0.1, 0.05, 0.8, 0.05], вероятность каждого класса вместо фактического числа 2. Как я уже сказал, вы не можете добавить horror с violence и получить sexual в качестве результата, поэтому вам нужно определить их отдельно, иметьмодель предсказывает, какой класс наиболее вероятен здесь.

Редактировать 2

Двоичная точность используется, когда каждое ваше изображение может быть более чем одним классом, как Эмма Уотсон может быть обеими актрисами,человек или женщина, ни классы не ошибаются. Выходной результат может быть как [1, 0, 1, 1, 0], суммирование не должно быть 1. Но в вашем случае здесь это categorical classification, а не binary, каждое изображение, сгенерированное из flow_from_directory, будет помечено как categorical, есливы хотите, чтобы он был мультиклассовым, вы все равно можете использовать binary_accuracy и получить тот же результат, но это не для этой цели, кто-то может почесать голову при чтении вашего кода позже, поэтому я думаю, что лучше использовать accuracy,

...