Зачем Keras'sвести_генератор и оценить отчет о различной точности на одних и тех же данных? - PullRequest
0 голосов
/ 29 января 2020

Я использую Keras ImageDataGenerator и flow_from_directory для обучения нейронной сети. У меня проблема в том, что evaluate_generator и evaluate сообщают о разной точности для одних и тех же данных. Вот минимальный пример , который сообщает о точности 0,24 из evaluate_generator, но о точности 0,44 из evaluate:

import os
import numpy as np
import cv2
import keras
import tensorflow as tf

np.random.seed(1)
tf.set_random_seed(1)

test_data_path = os.path.join("data", "test")

def load_data_from_image_files(base_data_path):
    X = []
    y = []
    for data_folder in os.listdir(base_data_path):
        data_folder_path = os.path.join(base_data_path, data_folder)
        if os.path.isdir(data_folder_path):
            for filename in os.listdir(data_folder_path):
                if filename.endswith(".jpg"):
                    X.append(cv2.imread(os.path.join(data_folder_path, filename)))
                    if data_folder == "null":
                        y.append([0])
                    else:
                        y.append([1])
    return np.array(X).astype("float32") / 255.0, np.array(y)

with open("model.json", "r") as json_file:
    model = keras.models.model_from_json(json_file.read())
model.load_weights("model.h5")
model.compile(loss="binary_crossentropy", optimizer="adam", metrics=["accuracy"])

X_test, y_test = load_data_from_image_files(test_data_path)
test_datagen = keras.preprocessing.image.ImageDataGenerator(rescale=1./255)
test_generator = test_datagen.flow_from_directory(
    test_data_path,
    target_size=(96, 96),
    batch_size=1,
    shuffle=False,
    class_mode="binary")
_, generator_test_accuracy = model.evaluate_generator(generator=test_generator, steps=test_generator.samples)
_, test_accuracy = model.evaluate(X_test, y_test)
print("evaluate_generator: %.3f, evaluate: %.3f" % (generator_test_accuracy, test_accuracy))

(Это test.py из репозитория keras-generator-minimal-example.) Предварительно обученная модель, загруженная этим сценарием, определяется следующим образом:

model = keras.models.Sequential()
model.add(keras.layers.Flatten(input_shape=(96, 96, 3)))
model.add(keras.layers.Dense(4, activation="relu"))
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.Dense(1, activation="sigmoid"))
model.compile(loss="binary_crossentropy", optimizer="adam", metrics=["accuracy"])

Полный сценарий для настройки и обучения модели: здесь .

Мой вопрос: должны ли model.evaluate_generator и model.evaluate в приведенном выше примере сообщать с той же точностью, или я что-то напутал? Если бы я просто пропустил параметр или что-то еще, я был бы очень признателен за толчок в правильном направлении.


Примечание: эта проблема Github , возможно, связана, хотя Различные исправления, предложенные в комментариях к этой проблеме, не решают проблему для меня. Установка shuffle=False, workers=1 и / или max_queue_size=1 ничего не меняет, а установка use_multiprocessing=True вызывает в моем терминале кучу следующих ошибок, и скрипт зависает:

/home/jack/.local/lib/python3.6/site-packages/keras/utils/data_utils.py:616: UserWarning: The input 0 could not be retrieved. It could be because a worker has died.
  UserWarning)

Поскольку я не смог решить эту вторичную проблему, я не знаю, решит ли установка use_multiprocessing=True в evaluate_generator проблему, с которой у меня возникли неточности.

1 Ответ

1 голос
/ 29 января 2020

Оказывается, что расхождение вызвано OpenCV imread с использованием формата BGR, тогда как Keras flow_from_directory ожидает RGB по умолчанию . Возврат каналов к RGB решил проблему.

...