Классификация изображений с помощью Keras: «ожидаемая активация_1 будет иметь форму (2,), но получит массив с (1,)» - PullRequest
0 голосов
/ 01 мая 2018

Я тренирую классификатор изображений, чтобы отличать кошек и собак от набора Kaggle.

Вот мой соответствующий код:

FINAL_ACTIVATION = "softmax"
OPTIMIZER = keras.optimizers.Adamax()
STRIDES = (2, 2)
DROPOUT = 0.5

model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape = INPUT_SHAPE))
model.add(keras.layers.ELU())
model.add(MaxPooling2D(pool_size = (2, 2), strides = STRIDES))

model.add(Conv2D(64, (3, 3)))
model.add(keras.layers.ELU())
model.add(MaxPooling2D(pool_size = (2, 2), strides = STRIDES))

model.add(Conv2D(128, (3, 3)))
model.add(keras.layers.ELU())
model.add(MaxPooling2D(pool_size = (2, 2), strides = STRIDES))

model.add(Conv2D(128, (3, 3)))
model.add(keras.layers.ELU())
model.add(MaxPooling2D(pool_size = (2, 2), strides = STRIDES))

model.add(Flatten())

model.add(Dense(100))
model.add(keras.layers.ELU())
model.add(Dropout(DROPOUT))

model.add(Dense(50))
model.add(keras.layers.ELU())
model.add(Dropout(DROPOUT))

model.add(Dense(2))
model.add(Activation(FINAL_ACTIVATION))

model.compile(
    loss="categorical_crossentropy",
    optimizer = OPTIMIZER,
    metrics = ["accuracy"]
)

train_datagen = ImageDataGenerator(
    rescale = 1./255,
    shear_range = 0.2,
    zoom_range = 0.2,
    horizontal_flip = True
)

train_generator = train_datagen.flow(
    x_train,
    y_train,
    batch_size = BATCH_SIZE
)

model.summary()

model.fit_generator(
    train_generator,
    steps_per_epoch = x_train.shape[0] // BATCH_SIZE,
    epochs = EPOCHS
)

Из-за большого количества обучающих файлов набор для тестирования отсутствует. Однако, когда я пытаюсь обучить эту сеть, я получаю сообщение об ошибке «ValueError: Ошибка при проверке цели: ожидалось, что для Activation_1 задан shape (2,), но получен массив с shape (1,)». Что я здесь не так делаю?

Сверточные нейронные сети для меня все еще немного чёрной магии, так что, возможно, я допускаю здесь некоторые ошибки новичка. Я полагаю, что, вероятно, я.

Вот моя модель:

_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
conv2d_1 (Conv2D)            (None, 98, 98, 32)        896
_________________________________________________________________
elu_1 (ELU)                  (None, 98, 98, 32)        0
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 49, 49, 32)        0
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 47, 47, 64)        18496
_________________________________________________________________
elu_2 (ELU)                  (None, 47, 47, 64)        0
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 23, 23, 64)        0
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 21, 21, 128)       73856
_________________________________________________________________
elu_3 (ELU)                  (None, 21, 21, 128)       0
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 10, 10, 128)       0
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 8, 8, 128)         147584
_________________________________________________________________
elu_4 (ELU)                  (None, 8, 8, 128)         0
_________________________________________________________________
max_pooling2d_4 (MaxPooling2 (None, 4, 4, 128)         0
_________________________________________________________________
flatten_1 (Flatten)          (None, 2048)              0
_________________________________________________________________
dense_1 (Dense)              (None, 100)               204900
_________________________________________________________________
elu_5 (ELU)                  (None, 100)               0
_________________________________________________________________
dropout_1 (Dropout)          (None, 100)               0
_________________________________________________________________
dense_2 (Dense)              (None, 50)                5050
_________________________________________________________________
elu_6 (ELU)                  (None, 50)                0
_________________________________________________________________
dropout_2 (Dropout)          (None, 50)                0
_________________________________________________________________
dense_3 (Dense)              (None, 2)                 102
_________________________________________________________________
activation_1 (Activation)    (None, 2)                 0
=================================================================
Total params: 450,884
Trainable params: 450,884
Non-trainable params: 0
_________________________________________________________________

1 Ответ

0 голосов
/ 01 мая 2018

Из-за большого количества обучающих файлов набор для тестирования отсутствует.

Хотя это не ваш вопрос, я чувствую, что это нужно решить: я понимаю, что есть некоторые группы, следующие совершенно другому подходу и не соблюдающие действительные / тестовые наборы, но для меня это звучит очень неортодоксально и неуверенно. Лично я редко вижу статьи без тестовых тестов или какой-либо проверки после поезда.

Наборы тестов полезны, поскольку они являются эмпирическим доказательством того, что ваша модель работает для невидимых образцов. Используя их + статистическую значимость / доверительные тесты, вы можете на статистической основе утверждать, что ваша модель - это не только очень сложная машина if-else.

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

По поводу вашей проблемы: Что такое y_train.shape? Я полагаю, что у вас текут разреженные метки ([1., 0., 1., 2., 3., ..., 4.]) вместо закодированных в горячем виде:

[[0. 1.]
 [1. 0.]
 [0. 1.]
 ...
 [1. 0.]]

Где argmax(x, axis=1) дает вам истинный индекс класса.

Как ее решить:

Заменить loss="categorical_crossentropy" на sparse_categorical_crossentropy. Это экономит память, но требует, чтобы каждый образец был связан с одной меткой.

OR

Однократное кодирование y_train перед передачей его на ImageDataGenerator#flow:

from keras.utils import to_categorical

y_train = to_categorical(y_train)
train_datagen = ImageDataGenerator(...)
train_generator = train_datagen.flow(x_train, y_train, ...)
...

Это занимает больше памяти, но позволяет связать один образец с более чем одной меткой:

[[1. 1. 0.]
 [0. 0. 1.]
 ...
 [1. 0. 1.]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...