Почему я продолжаю иметь класс "1" в качестве предсказанного класса? - PullRequest
0 голосов
/ 07 января 2019

У меня есть следующая Сверточная Нейронная Сеть (CNN) в Керасе, но у меня есть прогноз на тестовых изображениях как класс "1", при условии, что данные обучения сбалансированы. Любые идеи о том, как я могу решить эту проблему? Спасибо.

from keras import layers
from keras import models
from keras import optimizers
from keras.preprocessing.image import ImageDataGenerator
from sklearn.metrics import roc_curve
from sklearn.metrics import auc
import cv2
import numpy as np
import os

train_directory = '/train'
validation_directory = '/valid'
test_directory = '/test'
results_directory = '/results'
correct_classification = 0
number_of_test_images = 0
labels = []
prediction_probabilities = []

model = models.Sequential()

model.add(layers.Conv2D(32,(3,3),activation='relu',input_shape=(512,512,3)))
model.add(layers.MaxPooling2D(2,2))
model.add(layers.Conv2D(64,(3,3),activation='relu'))
model.add(layers.MaxPooling2D(2,2))
model.add(layers.Conv2D(128,(3,3),activation='relu'))
model.add(layers.MaxPooling2D(2,2))
model.add(layers.Conv2D(256,(3,3),activation='relu'))
model.add(layers.MaxPooling2D(2,2))
model.add(layers.Conv2D(512,(3,3),activation='relu'))
model.add(layers.MaxPooling2D(2,2))

model.add(layers.Flatten())
model.add(layers.Dense(1024,activation='relu'))
model.add(layers.Dense(1,activation='sigmoid'))

model.compile(loss='binary_crossentropy',optimizer='rmsprop',metrics=['acc'])

train_data = ImageDataGenerator(rescale=1.0/255)
validation_data = ImageDataGenerator(rescale=1.0/255)

train_generator = train_data.flow_from_directory(train_directory,target_size=(512,512),batch_size=20,class_mode='binary')
validation_generator = validation_data.flow_from_directory(validation_directory,target_size=(512,512),batch_size=20,class_mode='binary')

history = model.fit_generator(train_generator,
    steps_per_epoch=10,
    epochs=10,
    validation_data=validation_generator,
    validation_steps=5)

model.save('my_model.h5')

for root, dirs, files in os.walk(test_directory):
    for file in files:
        img = cv2.imread(root + '/' + file)
        img = cv2.resize(img,(512,512),interpolation=cv2.INTER_AREA)
        img = np.expand_dims(img, axis=0)
        img = img/255.0
        if os.path.basename(root) == 'nevus':
            label = 1
        elif os.path.basename(root) == 'melanoma':
            label = 0
        labels.append(label)
        img_class = model.predict_classes(img)
        img_class_probability = model.predict(img)
        prediction_probability = img_class_probability[0]
        prediction_probabilities.append(prediction_probability)
        prediction = img_class[0]
        if prediction == label:
            correct_classification = correct_classification + 1

1 Ответ

0 голосов
/ 07 января 2019

Выход вашей сети является причиной постоянного предсказания «1». Вам нужно иметь два выходных блока в вашем последнем слое. Подобный вопрос задают здесь , и я привел объяснение Матиаса ниже для удобства.

Softmax нормализуется по сумме экспонент каждого выхода. Поскольку имеется один выход, единственным возможным выходом является 1,0.

Для двоичного классификатора вы можете либо использовать сигмовидную активацию с потерей «binary_crossentropy», либо поставить два выходных блока на последнем слое, продолжать использовать softmax и изменить потерю на categoryorical_crossentropy.

...