2017-09-29 3 views
1

J'ai essayé à l'origine d'utiliser la syntaxe generator lors de l'écriture d'un générateur personnalisé pour l'entraînement d'un modèle Keras. Donc je yield éd de __next__. Cependant, quand j'essayerais de former mon mode avec model.fit_generator j'obtiendrais une erreur que mon générateur n'était pas un itérateur. La solution consistait à remplacer yield par return, ce qui nécessitait également de réorganiser la logique de __next__ pour suivre l'état. C'est assez pénible comparé à laisser faire le travail pour moi.Utiliser un générateur pour Keras model.fit_generator

Y at-il un moyen que je peux faire ce travail avec yield? Je vais devoir écrire plusieurs autres itérateurs qui devront avoir une logique très maladroite si je dois utiliser une instruction return.

+0

Est-ce que cela aide? http://anandology.com/python-practice-book/iterators.html – Rob

Répondre

1

Je ne peux pas aider à déboguer votre code puisque vous ne postez pas, mais j'abrégé un générateur de données personnalisé j'ai écrit pour un projet de segmentation sémantique pour vous d'utiliser comme modèle:

def generate_data(directory, batch_size): 
    """Replaces Keras' native ImageDataGenerator.""" 
    i = 0 
    file_list = os.listdir(directory) 
    while True: 
     image_batch = [] 
     for b in range(batch_size): 
      if i == len(file_list): 
       i = 0 
       random.shuffle(file_list) 
      sample = file_list[i] 
      i += 1 
      image = cv2.resize(cv2.imread(sample[0]), INPUT_SHAPE) 
      image_batch.append((image.astype(float) - 128)/128) 

     yield np.array(image_batch) 

Utilisation :

model.fit_generator(
    generate_data('~/my_data', batch_size), 
    steps_per_epoch=len(os.listdir('~/my_data')) // batch_size) 
+0

Merci pour ça. J'essayais de le faire en passant une instance d'une classe avec une instruction 'yield' dans la méthode' __next__' de la classe. Votre chemin indique une autre route, alors je vais essayer. – doogFromMT

0

J'ai récemment joué avec les générateurs pour keras et j'ai finalement réussi à préparer et exemple. Il utilise des données aléatoires, donc traîner pour enseigner NN sur cela n'a aucun sens, mais c'est une bonne illustration de l'utilisation de générateur pour keras.

Générez des données

import numpy as np 
import pandas as pd 
data = np.random.rand(200,2) 
expected = np.random.randint(2, size=200).reshape(-1,1) 

dataFrame = pd.DataFrame(data, columns = ['a','b']) 
expectedFrame = pd.DataFrame(expected, columns = ['expected']) 

dataFrameTrain, dataFrameTest = dataFrame[:100],dataFrame[-100:] 
expectedFrameTrain, expectedFrameTest = expectedFrame[:100],expectedFrame[-100:] 

Générateur

def generator(X_data, y_data, batch_size): 

    samples_per_epoch = X_data.shape[0] 
    number_of_batches = samples_per_epoch/batch_size 
    counter=0 

    while 1: 

    X_batch = np.array(X_data[batch_size*counter:batch_size*(counter+1)]).astype('float32') 
    y_batch = np.array(y_data[batch_size*counter:batch_size*(counter+1)]).astype('float32') 
    counter += 1 
    yield X_batch,y_batch 

    #restart counter to yeild data in the next epoch as well 
    if counter <= number_of_batches: 
     counter = 0 

modèle Keras

from keras.datasets import mnist 
from keras.models import Sequential 
from keras.layers.core import Dense, Dropout, Activation, Flatten, Reshape 
from keras.layers.convolutional import Convolution1D, Convolution2D, MaxPooling2D 
from keras.utils import np_utils 


model = Sequential() 
model.add(Dense(12, activation='relu', input_dim=dataFrame.shape[1])) 
model.add(Dense(1, activation='sigmoid')) 


model.compile(loss='binary_crossentropy', optimizer='adadelta', metrics=['accuracy']) 

#Train the model using generator vs using full batch 
batch_size = 8 

model.fit_generator(generator(dataFrameTrain,expectedFrameTrain,batch_size), epochs=3,steps_per_epoch = dataFrame.shape[0]/batch_size, validation_data=generator(dataFrameTest,expectedFrameTest,batch_size*2),validation_steps=dataFrame.shape[0]/batch_size*2) 

#without generator 
#model.fit(x = np.array(dataFrame), y = np.array(expected), batch_size = batch_size, epochs = 3) 

Sortie

Epoch 1/3 
25/25 [==============================] - 3s - loss: 0.7297 - acc: 0.4750 - 
val_loss: 0.7183 - val_acc: 0.5000 
Epoch 2/3 
25/25 [==============================] - 0s - loss: 0.7213 - acc: 0.3750 - 
val_loss: 0.7117 - val_acc: 0.5000 
Epoch 3/3 
25/25 [==============================] - 0s - loss: 0.7132 - acc: 0.3750 - 
val_loss: 0.7065 - val_acc: 0.5000