J'ai essayé de définir une fonction métrique personnalisée (F1-Score) dans Keras (backend Tensorflow) en fonction de ce qui suit:
def f1_score(tags, predicted):
tags = set(tags)
predicted = set(predicted)
tp = len(tags & predicted)
fp = len(predicted) - tp
fn = len(tags) - tp
if tp>0:
precision=float(tp)/(tp+fp)
recall=float(tp)/(tp+fn)
return 2*((precision*recall)/(precision+recall))
else:
return 0
Jusqu'à présent, tout va bien, mais quand j'essaie de l'appliquer dans la compilation de modèles:
model1.compile(loss="binary_crossentropy", optimizer=Adam(), metrics=[f1_score])
cela donne une erreur:
TypeError Traceback (most recent call last)
<ipython-input-85-4eca4def003f> in <module>()
5 model1.add(Dense(output_dim=10, activation="sigmoid"))
6
----> 7 model1.compile(loss="binary_crossentropy", optimizer=Adam(), metrics=[f1_score])
8
9 h=model1.fit(X_train, Y_train, batch_size=500, nb_epoch=5, verbose=True, validation_split=0.1)
/home/buda/anaconda2/lib/python2.7/site-packages/keras/models.pyc in compile(self, optimizer, loss, metrics, sample_weight_mode, **kwargs)
522 metrics=metrics,
523 sample_weight_mode=sample_weight_mode,
--> 524 **kwargs)
525 self.optimizer = self.model.optimizer
526 self.loss = self.model.loss
/home/buda/anaconda2/lib/python2.7/site-packages/keras/engine/training.pyc in compile(self, optimizer, loss, metrics, loss_weights, sample_weight_mode, **kwargs)
664 else:
665 metric_fn = metrics_module.get(metric)
--> 666 self.metrics_tensors.append(metric_fn(y_true, y_pred))
667 if len(self.output_names) == 1:
668 self.metrics_names.append(metric_fn.__name__)
<ipython-input-84-b8a5752b6d55> in f1_score(tags, predicted)
4 #tf.convert_to_tensor(img.eval())
5
----> 6 tags = set(tags)
7 predicted = set(predicted)
8
/home/buda/anaconda2/lib/python2.7/site-packages/tensorflow/python/framework/ops.pyc in __iter__(self)
493 TypeError: when invoked.
494 """
--> 495 raise TypeError("'Tensor' object is not iterable.")
496
497 def __bool__(self):
TypeError: 'Tensor' object is not iterable.
Quel est le problème ici? Le fait que mes entrées de fonction f1_score ne sont pas des tableaux Tensorflow? Si oui, où / comment puis-je les convertir correctement?
tensorflow
keras
evaluation
Hendrik
la source
la source
eval
lorsque vous voulez direeval()
Réponses:
Vous devez utiliser les fonctions backend de Keras . Malheureusement, ils ne prennent pas en charge l'
&
opérateur-, de sorte que vous devez construire une solution de contournement: nous générons des matrices de la dimensionbatch_size x 3
, où (par exemple pour un vrai positif) la première colonne est le vecteur de vérité au sol, la seconde la prédiction réelle et la troisième est sorte de colonne d'aide pour les étiquettes, qui ne contient que des vrais positifs. Ensuite, nous vérifions quelles instances sont des instances positives, prédites comme positives et l'assistant d'étiquette est également positif. Ce sont les vrais points positifs.Nous pouvons faire cet analogue avec de faux positifs, de faux négatifs et de vrais négatifs avec quelques calculs inverses des étiquettes.
Votre métrique f1 peut ressembler à ceci:
Puisque la calculatrice Keras-backend retourne nan pour la division par zéro, nous n'avons pas besoin de l'instruction if-else-pour l'instruction return.
Edit: J'ai trouvé une assez bonne idée pour une implémentation exacte. Le problème avec notre première approche est qu'elle est seulement "approximée", car elle est calculée par lots et ensuite moyennée. On pourrait également calculer cela après chaque époque avec le
keras.callback
s. Veuillez trouver l'idée ici: https://github.com/fchollet/keras/issues/5794Un exemple de mise en œuvre serait:
Pour que le réseau appelle cette fonction, il vous suffit de l'ajouter à vos rappels comme
Ensuite, vous pouvez simplement accéder aux membres de la
metrics
variable.la source