Как интерпретировать результаты, возвращаемые model.predict? - PullRequest
2 голосов
/ 02 мая 2020

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

Для не кошек я загрузил набор случайных изображений.

Я добавил два генератора к коду из учебника:

test_data_gen = test_image_generator.flow_from_directory(batch_size=batch_size,
                                                               directory=test_dir,
                                                               target_size=(IMG_HEIGHT, IMG_WIDTH),
                                                               class_mode='binary')

pred_data_gen = pred_image_generator.flow_from_directory(batch_size=batch_size,
                                                                 directory=pred_dir,
                                                                 target_size=(IMG_HEIGHT, IMG_WIDTH),
                                                                 class_mode='binary')

И затем протестировал модель следующим образом:

print('\n# Evaluate on test data')
results = model.evaluate_generator(test_data_gen)
print('test loss, test acc:', results)

print('\n# Generate predictions')
predictions = model.predict(pred_data_gen)
print(len(predictions))
print(predictions)

Это вывод:

# Evaluate on test data
test loss, test acc: [0.45212748232815003, 0.9324082]
# Generate predictions for custom samples
256
[[ -8.023465  ]
 [ -7.781438  ]
 [ 50.281197  ]
 [-10.172492  ]
 [ -5.1096087 ]
 [ 43.0299    ]
 [ 21.416649  ]
 ...
 [-10.866359  ]
 [-14.797473  ]
 [ 84.72212   ]
 [ 23.712345  ]
 [ -6.4916744 ]
 [-18.384903  ]
 [ 33.10642   ]]

Точность теста очень высока, но я понятия не имею, что означают эти результаты. Я думал, что они должны быть между 0 и 1, но они даже имеют отрицательные значения. Как мне интерпретировать эти результаты?

РЕДАКТИРОВАТЬ:

Это моя модель (до добавления функции активации сигмоида в последний слой):

model = Sequential([
    Conv2D(16, 3, padding='same', activation='relu', input_shape=(IMG_HEIGHT, IMG_WIDTH, 3)),
    MaxPooling2D(),
    Conv2D(32, 3, padding='same', activation='relu'),
    MaxPooling2D(),
    Conv2D(64, 3, padding='same', activation='relu'),
    MaxPooling2D(),
    Flatten(),
    Dense(512, activation='relu'),
    Dense(1)
])

Я изменил последний слой равен Dense(1, activation='sigmoid'), и результат выглядит следующим образом:

# Evaluate on test data
test loss, test acc: [0.714477022488912, 0.5949367]

# Generate predictions for custom samples
256
[[1.]
 [1.]
 [1.]
 ...
 [1.]
 [1.]
 [1.]]

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

EDIT2:

Вот как я собираю и подгоняю модель:

model.compile(optimizer='adam',
              loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              metrics=['accuracy'])

model.summary()

history = model.fit_generator(
    train_data_gen,
    steps_per_epoch=total_train // batch_size,
    epochs=epochs,
    validation_data=val_data_gen,
    validation_steps=total_val // batch_size
)

Ответы [ 3 ]

2 голосов
/ 02 мая 2020

Последний слой в вашей модели - это слой Dense с одним нейроном. Поскольку в него не было передано ни одного параметра, по умолчанию он имеет линейную активацию. Пользователь @Code Pope указал, что это «сбой» (ошибка в документах Tensorflow?). Это не так, код в порядке.

Ваша функция потерь вычисляет двоичную кроссентропию, и она может легко работать с линейной активацией. На самом деле, вычисление сигмоида - это просто лишнее, которое не нужно. ANN будет выводить отрицательные значения для одного класса и положительные для другого. Они не нормированы, а являются так называемыми logits - поэтому вы говорите в своей функции потерь from_logits=True.

Как получить прогнозы:

from sklearn.metrics import accuracy_score

images, actual = next(train_data_gen)
predictions = model.predict(images)
predictions = (predictions > 0).flatten()
accuracy_score(results, pred)
1 голос
/ 02 мая 2020

В сэмпле, который вы связали ( здесь , произошел сбой. На последнем слое Dense должна быть сигмовидная функция, значение которой должно быть от 0 до 1. Исходный образец взят из книга Deep Learning for Python от Франсуа Шоле и образец из главы 5.2. Образец доступен на github, и я рекомендую вам использовать его: здесь . Я использовал образец, и он отлично работает. Ваше редактирование модель выглядит нормально, но я не уверен, что вы создали правильную структуру папок для ваших изображений и, следовательно, для вашего ImageDataGenerator. Я обучил модель и затем загрузил изображение для прогнозирования:

from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input, decode_predictions
import numpy as np
img_path = '/Users/CodePope/Downloads/catsdogs/cats_and_dogs_smalla/test/dogs/dog.1500.jpg'
img = image.load_img(img_path, target_size=(150,150))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x /=255.
model.predict(x)

В результате получается следующее:

array([[0.8290838]], dtype=float32)

, который выглядит хорошо, так как 0 для кошки и 1. для собаки. Для изображения кошки мы имеем:

from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input, decode_predictions
import numpy as np
img_path = '/Users/CodePope/Downloads/catsdogs/cats_and_dogs_smalla/test/cats/cat.1500.jpg'
img = image.load_img(img_path, target_size=(150,150))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x /=255.
model.predict(x)

Результат:

array([[0.15701984]], dtype=float32)

И это несмотря на то, что я только что обучил модель для пяти эпох с точностью проверки 0,67.

1 голос
/ 02 мая 2020

Вам необходимо использовать сигмовидную функцию для масштабных выходов до [0, 1]

https://www.tensorflow.org/api_docs/python/tf/math/sigmoid

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