web-dev-qa-db-fra.com

Comment spécifier manuellement les étiquettes de classe dans les keras flow_from_directory?

Problème: J'entraîne un modèle pour la reconnaissance d'images multi-étiquettes. Mes images sont donc associées à plusieurs étiquettes y. Ceci est en conflit avec la méthode keras pratique "flow_from_directory" de ImageDataGenerator, où chaque image est censée se trouver dans le dossier de l'étiquette correspondante ( https://keras.io/preprocessing/image/ ) .

Solution: Actuellement, je lis toutes les images dans un tableau numpy et j'utilise la fonction "flow" à partir de là. Mais cela entraîne de lourdes charges de mémoire et un processus de lecture lent.

Question: Existe-t-il un moyen d'utiliser la méthode "flow_from_directory" et de fournir manuellement les (multiples) étiquettes de classe?


Mise à jour : J'ai fini par étendre la classe DirectoryIterator pour le cas multilabel. Vous pouvez maintenant définir l'attribut "class_mode" sur la valeur "multilabel" et fournir un dictionnaire "multlabel_classes" qui mappe les noms de fichiers à leurs étiquettes. Code: https://github.com/tholor/keras/commit/29ceafca3c4792cb480829c5768510e4bdb489c5

17
Malte

Vous pouvez écrire une classe de générateur personnalisée qui lirait les fichiers depuis le répertoire et appliquerait l'étiquetage. Ce générateur personnalisé pourrait également prendre une instance ImageDataGenerator qui produirait les lots à l'aide de flow ().

J'imagine quelque chose comme ça:

class Generator():

    def __init__(self, X, Y, img_data_gen, batch_size):
        self.X = X
        self.Y = Y  # Maybe a file that has the appropriate label mapping?
        self.img_data_gen = img_data_gen  # The ImageDataGenerator Instance
        self.batch_size = batch_size

    def apply_labels(self):
        # Code to apply labels to each sample based on self.X and self.Y

    def get_next_batch(self):
        """Get the next training batch"""
        self.img_data_gen.flow(self.X, self.Y, self.batch_size)

Alors simplement:

img_gen = ImageDataGenerator(...)
gen = Generator(X, Y, img_gen, 128)

model.fit_generator(gen.get_next_batch(), ...)

* Avertissement: je n'ai pas réellement testé cela, mais cela devrait fonctionner en théorie.

2
gaw89

Vous pouvez simplement utiliser le flow_from_directory et l'étendre à une multiclasse de la manière suivante:

def multiclass_flow_from_directory(flow_from_directory_gen, multiclasses_getter):
    for x, y in flow_from_directory_gen:
        yield x, multiclasses_getter(x, y)

multiclasses_getter attribue un vecteur multiclasse/votre représentation multiclasse à vos images. Notez que x et y ne sont pas des exemples uniques mais des lots d'exemples, donc cela devrait être inclus dans votre multiclasses_getter conception.

8
Marcin Możejko