Ich habe versucht, eine benutzerdefinierte metrische Funktion (F1-Score) in Keras (Tensorflow-Backend) wie folgt zu definieren:
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
So weit, so gut, aber wenn ich versuche, es bei der Modellzusammenstellung anzuwenden:
model1.compile(loss="binary_crossentropy", optimizer=Adam(), metrics=[f1_score])
es gibt Fehler:
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.
Was ist das Problem hier? Die Tatsache, dass meine f1_score-Funktionseingänge keine Tensorflow-Arrays sind? Wenn ja, wo / wie kann ich sie richtig konvertieren?
tensorflow
keras
evaluation
Hendrik
quelle
quelle
eval
wenn Sie meineneval()
Antworten:
Sie müssen Keras-Backend-Funktionen verwenden . Leider unterstützen sie den
&
Operator nicht, so dass Sie eine Problemumgehung erstellen müssen: Wir generieren Matrizen der Dimensionbatch_size x 3
, wobei (z. B. für wahres Positiv) die erste Spalte der Grundwahrheitsvektor ist, die zweite die tatsächliche Vorhersage und die dritte Art einer Label-Helfer-Spalte, die im Falle von wirklich positiven nur solche enthält. Dann prüfen wir, welche Instanzen positive Instanzen sind, werden als positiv vorhergesagt und der Label-Helfer ist ebenfalls positiv. Das sind die wahren positiven Aspekte.Wir können dieses Analogon mit falsch positiven, falsch negativen und wahr negativen Ergebnissen mit einigen umgekehrten Berechnungen der Bezeichnungen machen.
Ihre f1-Metrik sieht möglicherweise wie folgt aus:
Da der Keras-Backend-Rechner nan zur Division durch Null zurückgibt, benötigen wir die if-else-Anweisung nicht für die return-Anweisung.
Edit: Ich habe eine ziemlich gute Idee für eine genaue Implementierung gefunden. Das Problem bei unserem ersten Ansatz ist, dass er nur "angenähert" wird, da er chargenweise berechnet und anschließend gemittelt wird. Man könnte dies auch nach jeder Epoche mit dem
keras.callback
s berechnen . Die Idee finden Sie hier: https://github.com/fchollet/keras/issues/5794Eine beispielhafte Implementierung wäre:
Damit das Netzwerk diese Funktion aufruft, fügen Sie sie einfach Ihren Rückrufen wie hinzu
Dann können Sie einfach auf die Mitglieder der zugreifen
metrics
Variablen .quelle