Saya sudah mencoba menggunakan kode yang diberikan dari Keras sebelum kode-kode tersebut dihapus. Ini kodenya:
def precision(y_true, y_pred):
true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
precision = true_positives / (predicted_positives + K.epsilon())
return precision
def recall(y_true, y_pred):
true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
recall = true_positives / (possible_positives + K.epsilon())
return recall
def fbeta_score(y_true, y_pred, beta=1):
if beta < 0:
raise ValueError('The lowest choosable beta is zero (only precision).')
# If there are no true positives, fix the F score at 0 like sklearn.
if K.sum(K.round(K.clip(y_true, 0, 1))) == 0:
return 0
p = precision(y_true, y_pred)
r = recall(y_true, y_pred)
bb = beta ** 2
fbeta_score = (1 + bb) * (p * r) / (bb * p + r + K.epsilon())
return fbeta_score
def fmeasure(y_true, y_pred):
return fbeta_score(y_true, y_pred, beta=1)
Dari apa yang saya lihat (saya amatir dalam hal ini), sepertinya mereka menggunakan rumus yang benar. Tapi, ketika saya mencoba menggunakannya sebagai metrik dalam proses pelatihan, saya mendapatkan output yang sama persis untuk val_accuracy, val_precision, val_recall, dan val_fmeasure. Saya percaya bahwa hal itu mungkin terjadi bahkan jika rumusnya benar, tetapi saya yakin itu tidak mungkin terjadi. Adakah penjelasan untuk masalah ini? Terima kasih
sejak Keras 2.0 metrik f1, precision, dan recall telah dihapus. Solusinya adalah dengan menggunakan fungsi metrik khusus:
from keras import backend as K
def f1(y_true, y_pred):
def recall(y_true, y_pred):
"""Recall metric.
Only computes a batch-wise average of recall.
Computes the recall, a metric for multi-label classification of
how many relevant items are selected.
"""
true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
recall = true_positives / (possible_positives + K.epsilon())
return recall
def precision(y_true, y_pred):
"""Precision metric.
Only computes a batch-wise average of precision.
Computes the precision, a metric for multi-label classification of
how many selected items are relevant.
"""
true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
precision = true_positives / (predicted_positives + K.epsilon())
return precision
precision = precision(y_true, y_pred)
recall = recall(y_true, y_pred)
return 2*((precision*recall)/(precision+recall+K.epsilon()))
model.compile(loss='binary_crossentropy',
optimizer= "adam",
metrics=[f1])
Baris pengembalian dari fungsi ini
return 2*((precision*recall)/(precision+recall+K.epsilon()))
dimodifikasi dengan menambahkan konstanta epsilon, untuk menghindari pembagian dengan 0. Dengan demikian NaN tidak akan dihitung.
Saya juga menyarankan solusi ini
model.fit(nb_epoch=1, ...)
di dalam for loop dengan memanfaatkan metrik presisi/recall yang dihasilkan setelah setiap epochSeperti ini:
for mini_batch in range(epochs):
model_hist = model.fit(X_train, Y_train, batch_size=batch_size, epochs=1,
verbose=2, validation_data=(X_val, Y_val))
precision = model_hist.history['val_precision'][0]
recall = model_hist.history['val_recall'][0]
f_score = (2.0 * precision * recall) / (precision + recall)
print 'F1-SCORE {}'.format(f_score)
Seperti yang dikatakan @Pedia dalam komentarnya di atas, on_epoch_end
, seperti yang dinyatakan dalam github.com/fchollet/keras/issues/5400 adalah pendekatan terbaik.