Я учусь кодировать 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))
Ого, правда? Итак, если я хочу использовать CNN, который просматривает папку, содержащую сотни изображений любого типа, и возвращает мне только изображения, представляющие кошку, какой будет стратегия? Единственная стратегия, которую я могу придумать, - это иметь третью учебную папку, помимо «кошек» и «собак», это будет «другое». Поместите другие изображения в эту папку и обучите CNN с этими тремя папками. Но проблема в том, что «другое» очень велико. Потребовалось бы много снимков других животных, предметов, пейзажей, абстрактных картин ... это было бы массивно. Есть ли лучшая стратегия для этой проблемы?
Я считаю, что ваш код правильный. Он должен возвращать вероятность, а не точно 0 или 1. Возможная причина, по которой вы получаете 100% уверенность от модели, заключается в том, что она переобучена.
Это даже не переоборудовано. Чтобы убедиться, что проблема не в переобучении, я попробовал обучить CNN только на одной эпохе. И это по-прежнему дает мне 100% вероятность, даже если это неправильно. Я думаю, это так, как сказал Матиас Вальденегро. Это все еще открытая исследовательская проблема ...
Это не проблема программирования, а проблема открытого исследования. Дело не в простом добавлении кода или функции, но в целом не существует установленного способа обнаружения входных данных вне выборки.