Вопрос или проблема
Я пытаюсь вывести предсказанные метки для моих тестовых данных, но функция predict_generator() возвращает пустой массив.
Моя модель:
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Dense, Flatten
train_directory = 'D:\D_data\Rock_Paper_Scissors\Train'
training_datgagen = ImageDataGenerator(rescale = 1./255)
training_generator = training_datgagen.flow_from_directory(
train_directory,
target_size = (28,28),
class_mode="categorical")
validation_directory = 'D:\D_data\Rock_Paper_Scissors\Test'
validation_datagen = ImageDataGenerator(rescale= 1./255)
validation_generator = validation_datagen.flow_from_directory(
validation_directory,
target_size = (28,28),
class_mode="categorical"
)
filenames = validation_generator.filenames
nb_samples = len(filenames)
model = Sequential()
model.add(Flatten(input_shape = (28,28,3)))
model.add(Dense(128,activation = 'relu'))
model.add(Dense(64, activation = 'relu'))
model.add(Dense(16, activation = 'relu'))
model.add(Dense(3, activation = 'softmax'))
model.compile(optimizer="adam", loss="categorical_crossentropy",metrics = ['accuracy'],)
model.fit_generator(training_generator,epochs=20,validation_data = validation_generator)
predict = model.predict_generator(validation_generator,steps = nb_samples)
print(predict)
Вывод:
Найдено 1748 изображений, относящихся к 3 классам.
Найдено 0 изображений, относящихся к 0 классам.
Эпоха 1/20
55/55 [==============================] - 4с 64мс/шаг - потери: 0.9951 - точность: 0.4908
Эпоха 2/20
55/55 [==============================] - 4с 73мс/шаг - потери: 0.7280 - точность: 0.7248
Эпоха 3/20
55/55 [==============================] - 6с 109мс/шаг - потери: 0.5783 - точность: 0.7895
Эпоха 4/20
55/55 [==============================] - 5с 85мс/шаг - потери: 0.4649 - точность: 0.8387
Эпоха 5/20
55/55 [==============================] - 4с 71мс/шаг - потери: 0.3955 - точность: 0.8707
Эпоха 6/20
55/55 [==============================] - 4с 74мс/шаг - потери: 0.3595 - точность: 0.8804
Эпоха 7/20
55/55 [==============================] - 4с 70мс/шаг - потери: 0.3247 - точность: 0.8919
Эпоха 8/20
55/55 [==============================] - 4с 66мс/шаг - потери: 0.3435 - точность: 0.8827
Эпоха 9/20
55/55 [==============================] - 4с 65мс/шаг - потери: 0.2740 - точность: 0.9102
Эпоха 10/20
55/55 [==============================] - 3с 60мс/шаг - потери: 0.2141 - точность: 0.9336
Эпоха 11/20
55/55 [==============================] - 3с 61мс/шаг - потери: 0.1836 - точность: 0.9462
Эпоха 12/20
55/55 [==============================] - 3с 63мс/шаг - потери: 0.1722 - точность: 0.9416
Эпоха 13/20
55/55 [==============================] - 3с 62мс/шаг - потери: 0.1788 - точность: 0.9394
Эпоха 14/20
55/55 [==============================] - 3с 63мс/шаг - потери: 0.1331 - точность: 0.9571
Эпоха 15/20
55/55 [==============================] - 4с 68мс/шаг - потери: 0.1343 - точность: 0.9537
Эпоха 16/20
55/55 [==============================] - 4с 65мс/шаг - потери: 0.1033 - точность: 0.9680
Эпоха 17/20
55/55 [==============================] - 3с 62мс/шаг - потери: 0.1001 - точность: 0.9651
Эпоха 18/20
55/55 [==============================] - 3с 62мс/шаг - потери: 0.1209 - точность: 0.9565
Эпоха 19/20
55/55 [==============================] - 3с 61мс/шаг - потери: 0.1187 - точность: 0.9559
Эпоха 20/20
55/55 [==============================] - 3с 63мс/шаг - потери: 0.0834 - точность: 0.9737
[]
Код выглядит нормально для меня… Я только могу предположить, что вы каким-то образом исчерпали объект ImageDataGenerator, потому что вы используете тот же самый во время обучения, а затем для предсказания. (Я понимаю, что этого никогда не должно происходить).
Чтобы исключить это, вы можете создать отдельный генератор для тестирования.
Это также даст вам возможность использовать часть ваших данных для тестового набора, так что ваши окончательные предсказания будут вне выборки, что даст вам лучшее представление о производительности 🙂
Например, вы можете изменить ваш код, чтобы он выглядел так:
validation_directory = 'D:\D_data\Rock_Paper_Scissors\Test'
holdout_directory = 'D:\D_data\Rock_Paper_Scissors\Holdout' # создайте этот новый каталог
Переместите, например, 10 файлов в новый каталог holdout
validation_datagen = ImageDataGenerator(rescale= 1./255)
validation_generator = validation_datagen.flow_from_directory(
validation_directory,
target_size = (28,28),
class_mode="categorical"
)
# новый генератор для предсказаний
holdout_generator = validation_datagen.flow_from_directory(
holdout_directory,
target_size = (28,28),
class_mode="categorical"
)
model.fit_generator(training_generator, epochs=20, validation_data=validation_generator)
Установите число N
соответствующим образом, например, к 10 файлам в новом каталоге
predict = model.predict_generator(holdout_generator, batch_size=N)
print(predict.shape) # это должно вернуть форму numpy массива: (N, H, W, C)
print(predict) # фактические предсказания
Ответ или решение
Причины, по которым функция predict_generator
возвращает пустой массив, могут быть связаны с несколькими аспектами. Давайте разберем вашу ситуацию шаг за шагом, чтобы выявить источник проблемы и предложить возможные решения.
1. Исходные данные
Проблема с загрузкой данных: Судя по вашему выводу, вы получаете сообщение Found 0 images belonging to 0 classes.
. Это означает, что генератор проверки не обнаружил изображения в указанной директории. Вероятно, каталог D:\D_data\Rock_Paper_Scissors\Test
не содержит папок с классами или изображения разного типа, которые не могут быть правильно обработаны ImageDataGenerator
.
2. Проверьте структуру каталогов
Чтобы flow_from_directory
работал правильно, структура каталогов должна соответствовать следующим требованиям:
Test/
Class1/
image1.jpg
image2.jpg
Class2/
image1.jpg
image2.jpg
...
Убедитесь, что в каталоге Test
существуют подкаталоги с именами классов, и они содержат соответствующие изображения.
3. Создание генератора для тестов
Вы также упомянули о возможном исчерпании оригинального генератора, который используется для тренировки модели. Это действительно может стать причиной проблемы. Лучше создать отдельный генератор для тестирования, чтобы избежать такой ситуации. Пример правильной реализации может выглядеть следующим образом:
holdout_directory = 'D:\D_data\Rock_Paper_Scissors\Holdout' # Новый подкаталог для holdout
# Убедитесь, что изображения перемещены в этот каталог
holdout_generator = validation_datagen.flow_from_directory(
holdout_directory,
target_size=(28, 28),
class_mode="categorical"
)
# Теперь используйте этот генератор для предсказания
N = len(holdout_generator.filenames) # Количество изображений в holdout генераторе
predict = model.predict_generator(holdout_generator, steps=N)
print(predict)
4. Использование правильных параметров
Обратите внимание, что в predict_generator
используется параметр steps
. Убедитесь, что количество шагов (steps) соответствует количеству образцов в вашем генераторе для предсказания. В вашем случае, вы установили steps = nb_samples
, но если в holdout директории меньше примеров, это также может вывести пустой массив.
5. Проверка кода
Если изменения выше не решили проблему, рассмотрите возможность перепроверки кода на наличие опечаток и ошибки, связанные с импортом и использованием функций. Также убедитесь, что используемые версии Keras и TensorFlow соответствуют последним обновлениям, так как изменения в API могут влиять на функциональность.
Заключение
Ваша проблема, скорее всего, связана с неправильной структурой данных или исчерпанием генераторов. Обратите внимание на вышеуказанные аспекты, и ваша функция predict_generator
должна вернуть ожидаемые результаты. Убедитесь, что ваши классы правильно обозначены и изображения загружаются без проблем.