Почему вероятности прогнозирования так высоки для изображений без определенного класса?

#python #tensorflow #machine-learning #keras #conv-neural-network

#python #тензорный поток #машинное обучение #keras #conv-нейронная сеть

Вопрос:

Я пытаюсь создать CNN, который мог бы определять числа на изображении. Для этого я начал работать с набором данных Street View House Numbers (SVHN). Этот набор данных поставляется с предварительно обработанными изображениями, масштабированными до 32×32 цифр.Существует 10 классов для 10 чисел.

Я обучил сеть, и это дает приличную точность тестирования, близкую к ~ 0,93. Точность теста также рассчитывается на тестовом наборе, который представляет собой набор из 32×32 цифр.

Это все хорошо. Но проблема в том, что вероятность прогнозирования всегда равна единице. Вот как выглядит вывод одного из классов:

  array([[0.0000000e 00, 0.0000000e 00, 0.0000000e 00, 0.0000000e 00,
        1.0000000e 00, 8.5623318e-24, 0.0000000e 00, 0.0000000e 00,
        0.0000000e 00, 2.4716297e-28]], dtype=float32)
  

Как видно из вывода одного из примеров, вероятность класса для одного из классов равна 1 . Это нормально для изображения, которое содержит изображение нужного класса, но вероятность 1 возникает, даже если на изображении нет знака числа. Например, следующее изображение предсказывает класс 4 с вероятностью 1 . На самом деле приведенное выше распределение предназначено для следующего изображения.

Изображение:

введите описание изображения здесь

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

 val_split_length = 10623
num_train_samples = 73257
num_test_samples = 26032
total_classes = 10
model_prefix = "10c"

model = keras.Sequential()
# First Conv. Layer
model.add(keras.layers.Conv2D(filters = 96, kernel_size = (11,11), strides = (4,4), padding = "same", input_shape=(227,227,3)))
model.add(keras.layers.Activation("relu"))
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.MaxPooling2D(pool_size = (3,3), strides = (2,2), padding="same"))

# ##More Conv. Layers ###

# First Fully Connected Layer
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(4096))
model.add(keras.layers.Activation("relu"))
model.add(keras.layers.Dropout(0.5))

## More Fully Connected Layers ###

# Third Fully Connected Layer
model.add(keras.layers.Dense(total_classes))
model.add(keras.layers.Activation("softmax"))



train_optimizer_adam = tf.train.AdamOptimizer(learning_rate=1e-3)
train_optimizer_rmsProp = keras.optimizers.RMSprop(lr=0.0001)

#https://keras.io/optimizers/
model.compile(loss="categorical_crossentropy", optimizer=train_optimizer_rmsProp, metrics=['accuracy'])

batch_size = 128 * 3

data_generator = keras.preprocessing.image.ImageDataGenerator(rescale = 1./255)

# https://keras.io/preprocessing/image/#flow_from_directory
train_generator = data_generator.flow_from_directory(
        'train',
        target_size=(227, 227),
        batch_size=batch_size,
        color_mode='rgb',
        class_mode='categorical',
        #save_to_dir="logs"
)

validation_generator = data_generator.flow_from_directory(
        'validation',
        target_size=(227, 227),
        batch_size=batch_size,
        color_mode='rgb',
        class_mode='categorical')


# https://keras.io/models/model/#fit_generator
history = model.fit_generator(
    train_generator, 
    validation_data = validation_generator, 
    validation_steps = math.ceil(val_split_length / batch_size),
    epochs = 5, 
    steps_per_epoch = math.ceil(num_train_samples / batch_size), 
    use_multiprocessing = True, 
    workers = 8, 
    callbacks = model_callbacks, 
    verbose = 2
)
  

Для прогнозирования из модели выше:

 img = cv2.imread("image.png")
img = cv2.resize(img, (227,227))
loaded_model = keras.models.load_model("saved-model-12-0.96.hdf5")
prob = loaded_model.predict_proba(np.expand_dims(img, axis = 0))
print(prob)
  

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

Комментарии:

1. На самом деле это не вопрос программирования. Причина в том, что вероятности не откалиброваны, поэтому они не имеют никакого реального значения как вероятности. Модель всегда обучалась с вероятностями 1.0, поэтому ожидается, что она будет работать именно так.

2. @MatiasValdenegro Я хотел бы с вами не согласиться. Очень маловероятно, что вы получите такое уверенное предсказание (т. Е. Максимальную вероятность 1) в CNN, даже в очень хорошей модели. Проблема, скорее всего, связана с неправильной предварительной обработкой тестового изображения (т. Е. Не Используется тот же конвейер предварительной обработки, что и на этапе обучения). Вот почему модель выдает такой резкий пик выходных значений.

Ответ №1:

Проблема в том, что вы не применяете конвейер предварительной обработки, который вы использовали во время обучения модели. В частности, вы должны масштабировать значения пикселей изображения на 1/255. :

 img = img.astype('float32') / 255.
  

Действительно важно следовать тому же конвейеру предварительной обработки на этапе тестирования, который используется на этапе обучения; в противном случае ваша модель может запутаться и выдавать неправильные прогнозы.

Комментарии:

1. Это делается в генераторе 😉 data_generator = keras.preprocessing.image.ImageDataGenerator(rescale = 1./255)

2. @TheLoneDeranger Пожалуйста, внимательно прочитайте тестовый код! Генератор здесь неуместен.

3. Я не уверен, что вы имеете в виду, но я вижу, что прогноз не масштабируется, да.

4. @TheLoneDeranger Я имею в виду, что генератор не используется, когда OP использует свою модель для прогнозирования одного изображения (т. Е. Последнего блока кода в вопросе OP). Кроме того, это не имеет ничего общего с масштабированием прогнозирования ; скорее входные данные должны быть масштабированы. Вот почему это называется предварительной обработкой (а не последующей обработкой).

5. «Входные данные должны быть предсказаны», ваше величество.