J'adapte un train_generator et au moyen d'un rappel personnalisé, je veux calculer des métriques personnalisées sur mon validation_generator. Comment puis-je accéder aux paramètres validation_steps
et validation_data
Dans un rappel personnalisé? Ce n'est pas dans self.params
, ne le trouve pas dans self.model
Soit. Voici ce que j'aimerais faire. Toute approche différente serait la bienvenue.
model.fit_generator(generator=train_generator,
steps_per_Epoch=steps_per_Epoch,
epochs=epochs,
validation_data=validation_generator,
validation_steps=validation_steps,
callbacks=[CustomMetrics()])
class CustomMetrics(keras.callbacks.Callback):
def on_Epoch_end(self, batch, logs={}):
for i in validation_steps:
# features, labels = next(validation_data)
# compute custom metric: f(features, labels)
return
keras: 2.1.1
Mise à jour
J'ai réussi à transmettre mes données de validation au constructeur d'un rappel personnalisé. Cependant, cela se traduit par un ennuyeux "Le noyau semble être mort. Il redémarrera automatiquement." message. Je doute que ce soit la bonne façon de procéder. Toute suggestion?
class CustomMetrics(keras.callbacks.Callback):
def __init__(self, validation_generator, validation_steps):
self.validation_generator = validation_generator
self.validation_steps = validation_steps
def on_Epoch_end(self, batch, logs={}):
self.scores = {
'recall_score': [],
'precision_score': [],
'f1_score': []
}
for batch_index in range(self.validation_steps):
features, y_true = next(self.validation_generator)
y_pred = np.asarray(self.model.predict(features))
y_pred = y_pred.round().astype(int)
self.scores['recall_score'].append(recall_score(y_true[:,0], y_pred[:,0]))
self.scores['precision_score'].append(precision_score(y_true[:,0], y_pred[:,0]))
self.scores['f1_score'].append(f1_score(y_true[:,0], y_pred[:,0]))
return
metrics = CustomMetrics(validation_generator, validation_steps)
model.fit_generator(generator=train_generator,
steps_per_Epoch=steps_per_Epoch,
epochs=epochs,
validation_data=validation_generator,
validation_steps=validation_steps,
shuffle=True,
callbacks=[metrics],
verbose=1)
Vous pouvez parcourir directement self.validation_data pour agréger toutes les données de validation à la fin de chaque époque. Si vous souhaitez calculer la précision, rappeler et F1 sur l'ensemble de données de validation complet:
# Validation metrics callback: validation precision, recall and F1
# Some of the code was adapted from https://medium.com/@thongonary/how-to-compute-f1-score-for-each-Epoch-in-keras-a1acd17715a2
class Metrics(callbacks.Callback):
def on_train_begin(self, logs={}):
self.val_f1s = []
self.val_recalls = []
self.val_precisions = []
def on_Epoch_end(self, Epoch, logs):
# 5.4.1 For each validation batch
for batch_index in range(0, len(self.validation_data)):
# 5.4.1.1 Get the batch target values
temp_targ = self.validation_data[batch_index][1]
# 5.4.1.2 Get the batch prediction values
temp_predict = (np.asarray(self.model.predict(
self.validation_data[batch_index][0]))).round()
# 5.4.1.3 Append them to the corresponding output objects
if(batch_index == 0):
val_targ = temp_targ
val_predict = temp_predict
else:
val_targ = np.vstack((val_targ, temp_targ))
val_predict = np.vstack((val_predict, temp_predict))
val_f1 = round(f1_score(val_targ, val_predict), 4)
val_recall = round(recall_score(val_targ, val_predict), 4)
val_precis = round(precision_score(val_targ, val_predict), 4)
self.val_f1s.append(val_f1)
self.val_recalls.append(val_recall)
self.val_precisions.append(val_precis)
# Add custom metrics to the logs, so that we can use them with
# EarlyStop and csvLogger callbacks
logs["val_f1"] = val_f1
logs["val_recall"] = val_recall
logs["val_precis"] = val_precis
print("— val_f1: {} — val_precis: {} — val_recall {}".format(
val_f1, val_precis, val_recall))
return
valid_metrics = Metrics()
Ensuite, vous pouvez ajouter valid_metrics à l'argument de rappel:
your_model.fit_generator(..., callbacks = [valid_metrics])
Assurez-vous de le mettre au début des rappels au cas où vous souhaiteriez que d'autres rappels utilisent ces mesures.
J'étais en train de verrouiller la solution pour le même problème, puis je trouve la vôtre et une autre solution dans la réponse acceptée ici . Si la deuxième solution fonctionne, je pense que ce sera mieux que d'itérer de nouveau une validation approfondie à "on Epoch end"
L'idée est d'enregistrer les espaces réservés cibles et précédents dans des variables et de mettre à jour les variables via un rappel personnalisé à la fin du lot.