Python Keras Image Recognition получить точную вероятность (Не [[0.]] или [[1.]])

Я учусь кодировать CNN с помощью keras. Учебник, которому я следую, основан на этот учебник, и все работает очень хорошо.

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

Поскольку модель обучается только на изображениях собак и кошек, она может сказать мне только, является ли изображение собакой или кошкой. Таким образом, я решил использовать model.predict_proba, чтобы получить точную вероятность, поэтому я хотел, чтобы модель говорила мне в случае изображения стула: «Вероятность 7%, это собака». Но модель дает мне [[0.]], то есть модель на 100% уверена, что стул - это собака.

Затем я начал модифицировать CNN и поместил 2 выходных нейрона в полностью связанные слои, чтобы иметь вероятность, что это кошка, и вероятность того, что это собака. Я использовал class_mode='categorical' вместо class_mode='binary' при подготовке данных, чтобы убедиться, что он работает с двумя выходными нейронами, и я не использовал softmax, чтобы быть уверенным, что у меня нет probaDog + probaCat = 1, потому что, если вход представляет собой изображение что-то еще, кроме собаки или кошки, я не хочу получать ложные вероятности ... Когда я набирал model.predict_proba("iamge_path"), я хотел увидеть что-то вроде этого [[0.213 0.639]]. Затем я захотел определить некоторые условия и использовать их так:

if result[0][0] < 0.5 AND result[0][1] < 0.5:
    print("This is neither a dog nor a cat!")
elif result[0][0] > result[0][1] + 0.5:
    print("This is a dog!")
elif result[0][1] > result[0][0] + 0.5:
    print("This is a cat!")
else:
    print("This is neither a dog nor a cat!")

Но вместо этого каждый ответ, который я получаю, - это [[0. 1.]] или [[1. 0.]].

Я пробовал тренировать свой CNN только на 1 эпоху. Я представил этому CNN 13 фотографий кошки, и он 7 раз сказал мне, что это собаки. Но был уверен на 100%, что это собаки ...

Итак, как нам получить истинную вероятность?

Вот мой код CNN:

model = Sequential()

model.add(Convolution2D(filters=32, kernel_size=3, strides=1, input_shape=(128, 128, 3), activation = "relu"))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Convolution2D(filters=32, kernel_size=3, strides=1, activation = "relu"))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Convolution2D(filters=32, kernel_size=3, strides=1, activation = "relu"))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Convolution2D(filters=32, kernel_size=3, strides=1, activation = "relu"))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Flatten())

model.add(Dense(units=128, activation = "relu"))
model.add(Dropout(rate=0.2))
model.add(Dense(units=128, activation = "relu"))
model.add(Dropout(rate=0.2))
model.add(Dense(units=128, activation = "relu"))
model.add(Dropout(rate=0.2))
model.add(Dense(units=2, activation = "sigmoid")) # 2 neurones de sorties

model.compile(optimizer = "adam", loss = "binary_crossentropy", metrics = ["accuracy"])

Вот мой код подготовки данных:

training_set = train_datagen.flow_from_directory(
        'dataset/training_set',
        target_size=(128, 128),   
        batch_size=32,
        class_mode='categorical')

test_set = test_datagen.flow_from_directory(
        'dataset/test_set',
        target_size=(128, 128),
        batch_size=32,
        class_mode='categorical')

Код обучения:

model.fit_generator(
                        training_set,
                        steps_per_epoch=250, 
                        epochs=50,
                        validation_data=test_set,
                        validation_steps=63)

Код для тестирования на одном изображении:

test_image = image.load_img(image_path, target_size=(128, 128)) 
test_image = image.img_to_array(test_image) 
test_image = np.expand_dims(test_image, axis = 0) 
result = model.predict(test_image)
print(model.predict_proba(test_image))

Это не проблема программирования, а проблема открытого исследования. Дело не в простом добавлении кода или функции, но в целом не существует установленного способа обнаружения входных данных вне выборки.

Dr. Snoopy 13.09.2018 16:21

Ого, правда? Итак, если я хочу использовать CNN, который просматривает папку, содержащую сотни изображений любого типа, и возвращает мне только изображения, представляющие кошку, какой будет стратегия? Единственная стратегия, которую я могу придумать, - это иметь третью учебную папку, помимо «кошек» и «собак», это будет «другое». Поместите другие изображения в эту папку и обучите CNN с этими тремя папками. Но проблема в том, что «другое» очень велико. Потребовалось бы много снимков других животных, предметов, пейзажей, абстрактных картин ... это было бы массивно. Есть ли лучшая стратегия для этой проблемы?

vdlmrc 13.09.2018 17:05

Я считаю, что ваш код правильный. Он должен возвращать вероятность, а не точно 0 или 1. Возможная причина, по которой вы получаете 100% уверенность от модели, заключается в том, что она переобучена.

Kota Mori 13.09.2018 17:29

Это даже не переоборудовано. Чтобы убедиться, что проблема не в переобучении, я попробовал обучить CNN только на одной эпохе. И это по-прежнему дает мне 100% вероятность, даже если это неправильно. Я думаю, это так, как сказал Матиас Вальденегро. Это все еще открытая исследовательская проблема ...

vdlmrc 14.09.2018 00:02
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
4
83
0

Другие вопросы по теме