如何使用 precision_recall_curve 计算最大 F1 分数?

12

针对一个简单的二元分类问题,我希望找到最大化f1分数的阈值设置,该分数是精确率和召回率的调和平均值。是否有scikit learn内建的方法实现这一点?目前,我只是简单地调用

precision, recall, thresholds = precision_recall_curve(y_test, y_test_predicted_probas)

然后,我可以使用三个数组中每个索引处的信息来计算f1分数:

curr_f1 = compute_f1(precision[index], recall[index])

有没有更好的方法来做这件事,或者这是该库预期使用的方式?谢谢。


请注意,我正在使用带有二元逻辑输出的XGBoost分类器,如果这会改变任何内容。 - information_interchange
2个回答

15

计算精确率、召回率和阈值分数后,你会获得NumPy数组。
只需使用NumPy函数找到最大化F1分数的阈值即可:

f1_scores = 2*recall*precision/(recall+precision)
print('Best threshold: ', thresholds[np.argmax(f1_scores)])
print('Best F1-Score: ', np.max(f1_scores))

如果我们关心“加权 F1 得分”呢?为了考虑不平衡的分类。 - Luca Guarro

7
有时precision_recall_curve会选择一些对于数据来说过高的阈值,导致在某些点上既有precision也有recall 为零。这可能会导致计算 F1 分数时出现nan。为确保正确输出,请使用np.divide仅在分母非零时进行除法运算:
precision, recall, thresholds = precision_recall_curve(y_test, y_test_predicted_probas)
numerator = 2 * recall * precision
denom = recall + precision
f1_scores = np.divide(numerator, denom, out=np.zeros_like(denom), where=(denom!=0))
max_f1 = np.max(f1_scores)
max_f1_thresh = thresholds[np.argmax(f1_scores)]

这是一个巧妙使用输出参数的例子 - 对于像我一样短暂困惑的其他人来说,当分母不为零时,f1_scores将默认为零。 - twink_ml

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接