À l'origine, j'avais essayé d'utiliser la syntaxe generator
lors de l'écriture d'un générateur personnalisé pour la formation d'un modèle Keras. Alors j'ai yield
ed de __next__
. Cependant, lorsque 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. Le correctif consistait à changer yield
en return
, ce qui nécessitait également de modifier la logique de __next__
pour suivre l'état. C'est assez lourd comparé à laisser yield
faire le travail pour moi.
Existe-t-il un moyen de faire fonctionner cela avec yield
? J'aurai besoin d'écrire plusieurs autres itérateurs qui devront avoir une logique très maladroite si je dois utiliser une instruction return
.
Je ne peux pas vous aider à déboguer votre code car vous ne l'avez pas posté, mais j'ai abrégé un générateur de données personnalisé que j'ai écrit pour un projet de segmentation sémantique que vous pouvez 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)
Usage:
model.fit_generator(
generate_data('~/my_data', batch_size),
steps_per_Epoch=len(os.listdir('~/my_data')) // batch_size)
J'ai récemment joué avec les générateurs pour Keras et j'ai finalement réussi à préparer un exemple. Il utilise des données aléatoires, alors essayer d’enseigner NN dessus n’a aucun sens, mais c’est une bonne illustration de l’utilisation d’un générateur Python pour Keras.
Générer 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 the 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
C'est la façon dont je l'ai implémenté pour lire des fichiers de toute taille . Et cela fonctionne comme un charme.
import pandas as pd
hdr=[]
for i in range(num_labels+num_features):
hdr.append("Col-"+str(i)) # data file do not have header so I need to
# provide one for pd.read_csv by chunks to work
def tgen(filename):
csvfile = open(filename)
reader = pd.read_csv(csvfile, chunksize=batch_size,names=hdr,header=None)
while True:
for chunk in reader:
W=chunk.values # labels and features
Y =W[:,:num_labels] # labels
X =W[:,num_labels:] # features
X= X / 255 # any required transformation
yield X, Y
csvfile = open(filename)
reader = pd.read_csv(csvfile, chunksize=batchz,names=hdr,header=None)
Le dos dans la main j'ai
nval=number_of_validation_samples//batchz
ntrain=number_of_training_samples//batchz
ftgen=tgen("training.csv")
fvgen=tgen("validation.csv")
history = model.fit_generator(ftgen,
steps_per_Epoch=ntrain,
validation_data=fvgen,
validation_steps=nval,
epochs=number_of_epochs,
callbacks=[checkpointer, stopper],
verbose=2)