web-dev-qa-db-fra.com

Keras - Comment les lots et les époques sont-ils utilisés dans fit_generator ()?

J'ai une vidéo de 8000 images et j'aimerais former un modèle Keras sur des lots de 200 images chacun. J'ai un générateur d'images qui parcourt la vidéo image par image et accumule les images (3 x 480 x 640) dans une matrice numpy X de forme (200, 3, 480, 640)taille de lot, rgb, frame frame, frame width) - et donne X et Y chaque 200ème frame:

import cv2
...
def _frameGenerator(videoPath, dataPath, batchSize):
    """
    Yield X and Y data when the batch is filled.
    """
    camera = cv2.VideoCapture(videoPath)
    width = camera.get(3)
    height = camera.get(4)
    frameCount = int(camera.get(7))  # Number of frames in the video file.

    truthData = _prepData(dataPath, frameCount)

    X = np.zeros((batchSize, 3, height, width))
    Y = np.zeros((batchSize, 1))

    batch = 0
    for frameIdx, truth in enumerate(truthData):
        ret, frame = camera.read()
        if ret is False: continue

        batchIndex = frameIdx%batchSize

        X[batchIndex] = frame
        Y[batchIndex] = truth

        if batchIndex == 0 and frameIdx != 0:
            batch += 1
            print "now yielding batch", batch
            yield X, Y

Voici comment exécuter --- (fit_generator() :

        batchSize = 200
        print "Starting training..."
        model.fit_generator(
            _frameGenerator(videoPath, dataPath, batchSize),
            samples_per_Epoch=8000,
            nb_Epoch=10,
            verbose=args.verbosity
        )

Ma compréhension est qu'une époque se termine lorsque samples_per_Epoch Échantillons ont été vus par le modèle, et samples_per_Epoch = Taille du lot * nombre de lots = 200 * 40. Donc, après la formation pour une époque sur les images 0- 7999, la prochaine Epoque recommencera l'entraînement à partir de l'image 0. Est-ce correct?

Avec cette configuration je m'attends à ce que 40 lots (de 200 images chacun) soient passés du générateur à fit_generator, Par époque; ce serait 8000 images au total par époque - c'est-à-dire samples_per_Epoch=8000. Ensuite, pour les époques suivantes, fit_generator Réinitialiserait le générateur de telle sorte que nous recommençons l'entraînement depuis le début de la vidéo. Pourtant, ce n'est pas le cas. Une fois la première époque terminée (une fois que le modèle enregistre les lots 0-24), le générateur reprend là où il s'était arrêté. La nouvelle Epoch ne devrait-elle pas recommencer depuis le début du jeu de données d'entraînement?

S'il y a quelque chose de incorrect dans ma compréhension de fit_generator, Veuillez expliquer. J'ai parcouru la documentation, ceci exemple , et ces liésproblèmes . J'utilise Keras v1.0.7 avec le backend TensorFlow. Ce problème est également publié dans le Keras repo .

17
BoltzmannBrain

Une fois la première époque terminée (une fois que le modèle enregistre les lots 0-24), le générateur reprend là où il s'était arrêté

Il s'agit d'une description précise de ce qui se passe. Si vous souhaitez réinitialiser ou rembobiner le générateur, vous devrez le faire en interne. Notez que le comportement des keras est très utile dans de nombreuses situations. Par exemple, vous pouvez mettre fin à une époque après avoir vu la moitié des données puis effectuer une époque sur l'autre moitié, ce qui serait impossible si l'état du générateur était réinitialisé (ce qui peut être utile pour surveiller la validation de plus près).

9
yhenon

Vous pouvez forcer votre générateur à se réinitialiser en ajoutant un while 1: boucle, c'est comme ça que je procède. Ainsi, votre générateur peut fournir des données par lots pour chaque époque.

6
Adrien G.

Parce que le générateur est une fonction complètement séparée, il continuera sa boucle infinie chaque fois qu'il sera rappelé.

Ce que je ne peux pas justifier, c'est que fit_generator() appellera le générateur jusqu'à ce qu'il ait suffisamment d'échantillons. Je ne trouve pas la variable batch_size, mais il doit y avoir un critère qui définit une variable interne qui définit la taille.

J'ai vérifié cela lors de l'impression d'un état dans chaque séquence de boucle:

def generator():

while 1:
    for i in range(0,len(x_v)-1):
        if (i != predict_batch_nr):
            print("\n -> usting Datasett ", i+1 ," of ", len(x_v))
            x = x_v[i] #x_v has Batches of different length
            y = y_v[i] #y_v has Batches of different length

            yield x, y


model.fit_generator(generator(),steps_per_Epoch=5000,epochs=20, verbose=1)

Exemple de sortie:

4914/5000 [============================>.] - ETA: 13s - loss: 2442.8587
usting Datasett  77  of  92
4915/5000 [============================>.] - ETA: 12s - loss: 2442.3785
-> usting Datasett  78  of  92
-> usting Datasett  79  of  92
-> usting Datasett  80  of  92
4918/5000 [============================>.] - ETA: 12s - loss: 2442.2111
-> usting Datasett  81  of  92
-> usting Datasett  82  of  92
0
Felix Petersilie