Fit_generator () Keras для предсказаний двоичной классификации всегда 50% - PullRequest
0 голосов
/ 15 ноября 2018

Я настроил модель для тренировки классификации того, является ли изображение определенной видеоигрой или нет.Я pre-scaled мои изображения в 250x250 пикселей и разделить их на две папки (два двоичных класса) с пометкой 0 и 1.Количество обоих классов находится в пределах ~100 друг от друга, и у меня всего около 3500 изображений.

Вот фотографии тренировочного процесса, настроенной модели и некоторые прогнозы: https://imgur.com/a/CN1b6LV

train_datagen = ImageDataGenerator(
    rescale=1. / 255,
    shear_range=0,
    zoom_range=0,
    horizontal_flip=True,
    width_shift_range=0.1,
    height_shift_range=0.1,
    validation_split=0.2)
train_generator = train_datagen.flow_from_directory(
    'data\\',
    batch_size=batchsize,
    shuffle=True,
    target_size=(250, 250),
    subset="training",
    class_mode="binary")
val_generator = train_datagen.flow_from_directory(
    'data\\',
    batch_size=batchsize,
    shuffle=True,
    target_size=(250, 250),
    subset="validation",
    class_mode="binary")
pred_datagen = ImageDataGenerator(
    rescale=1. / 255,
    shear_range=0,
    zoom_range=0,
    horizontal_flip=False,
    width_shift_range=0.1,
    height_shift_range=0.1)
pred_generator = pred_datagen.flow_from_directory(
    'batch_pred\\',
    batch_size=30,
    shuffle=False,
    target_size=(250, 250))


model = Sequential()
model.add(Conv2D(input_shape=(250, 250, 3), filters=25, kernel_size=3, activation="relu", padding="same"))
model.add(Conv2D(filters=32, kernel_size=3, activation="relu", padding="same"))
model.add(Conv2D(filters=32, kernel_size=3, activation="relu", padding="same"))
model.add(MaxPooling2D(pool_size=2,  padding="same", strides=(2, 2)))
model.add(BatchNormalization())
model.add(Conv2D(filters=64, kernel_size=3, activation="relu", padding="same"))
model.add(Conv2D(filters=64, kernel_size=3, activation="relu", padding="same"))
model.add(Conv2D(filters=64, kernel_size=3, activation="relu", padding="same"))
model.add(MaxPooling2D(pool_size=2, padding="same", strides=(2, 2)))
model.add(BatchNormalization())
model.add(Conv2D(filters=128, kernel_size=3, activation="relu", padding="same"))
model.add(Conv2D(filters=128, kernel_size=3, activation="relu", padding="same"))
model.add(Conv2D(filters=128, kernel_size=3, activation="relu", padding="same"))
model.add(MaxPooling2D(pool_size=2, padding="same", strides=(2, 2)))
model.add(Conv2D(filters=256, kernel_size=3, activation="relu", padding="same"))
model.add(Conv2D(filters=256, kernel_size=3, activation="relu", padding="same"))
model.add(Conv2D(filters=256, kernel_size=3, activation="relu", padding="same"))
model.add(MaxPooling2D(pool_size=2, padding="same", strides=(2, 2)))
model.add(BatchNormalization())
dense = False
if dense:
    model.add(Flatten())
    model.add(Dense(250, activation="relu"))
    model.add(BatchNormalization())
    model.add(Dense(50, activation="relu"))
else:
    model.add(GlobalAveragePooling2D())
model.add(Dense(1, activation="softmax"))
model.compile(loss='binary_crossentropy',
              optimizer=Adam(0.0005), metrics=["acc"])
callbacks = [EarlyStopping(monitor='val_acc', patience=200, verbose=1),
             ModelCheckpoint(filepath="model_checkpoint.h5py",
                             monitor='val_acc', save_best_only=True, verbose=1)]
model.fit_generator(
      train_generator,
      steps_per_epoch=train_generator.samples // batchsize,
      validation_data=val_generator,
      validation_steps=val_generator.samples // batchsize,
      epochs=500,
      callbacks=callbacks)

Кажется, что все работает правильно с точки зрения model итерации данных по эпохам, определения правильного количества изображений и т. Д. Однако мои прогнозы всегда 50%, несмотря на хорошую точность проверки,малые потери, высокая точность и т. д.

Я не уверен, что делаю неправильно, и любая помощь будет признательна.

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

Проблема в том, что вы используете softmax на плотном слое с одной единицей. Функция Softmax нормализует свой вход так, что сумма его элементов становится равной единице. Таким образом, если он имеет одну единицу, то выход будет всегда 1. Вместо этого, для двоичной классификации вам нужно использовать функцию sigmoid в качестве функции активации последнего слоя.

0 голосов
/ 15 ноября 2018

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

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