好的,这是我的尝试。非常欢迎评论!
主要 F1 得分逻辑取自 here。对于y_pred 和y_true 都作为(batch_size, sequence_length, classes_number) 形状的3D 张量,我们在它们对应的切片上计算单类F1,然后平均结果。 0 类保留用于填充,不计入分数。
from keras import backend as K
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
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 f1_binary(y_true, y_pred):
p = precision(y_true, y_pred)
r = recall(y_true, y_pred)
return 2 * ((p * r) / (p + r + K.epsilon()))
def f1(classes_number, y_true, y_pred):
result = 0.0
for class_id in xrange(1, classes_number + 1):
y_true_single_class = y_true[:,:,class_id]
y_pred_single_class = y_pred[:,:,class_id]
f1_single = f1_binary(y_true_single_class, y_pred_single_class)
result += f1_single / float(classes_number)
return result
下面是如何将它与 Keras 模型一起使用(classes_number 参数通过wrapped_partial 绑定):
model.compile(optimizer=opt,
loss='categorical_crossentropy',
metrics=[wrapped_partial(f1, classes_number)])